|
|
c480ed |
From 874617d278b58554feee567b2e79d208aaef214c Mon Sep 17 00:00:00 2001
|
|
|
c480ed |
Message-Id: <874617d278b58554feee567b2e79d208aaef214c@dist-git>
|
|
|
c480ed |
From: Michal Privoznik <mprivozn@redhat.com>
|
|
|
c480ed |
Date: Tue, 6 Aug 2019 13:29:22 +0200
|
|
|
c480ed |
Subject: [PATCH] virDomainObjListAddLocked: Produce better error message than
|
|
|
c480ed |
'Duplicate key'
|
|
|
c480ed |
MIME-Version: 1.0
|
|
|
c480ed |
Content-Type: text/plain; charset=UTF-8
|
|
|
c480ed |
Content-Transfer-Encoding: 8bit
|
|
|
c480ed |
|
|
|
c480ed |
If there are two concurrent threads, one of which is removing a
|
|
|
c480ed |
domain from the list and the other is trying to add it back they
|
|
|
c480ed |
may serialize in the following order:
|
|
|
c480ed |
|
|
|
c480ed |
1) vm->removing is set and @vm is unlocked.
|
|
|
c480ed |
2) The tread that's trying to add the domain onto the list locks
|
|
|
c480ed |
the list and tries to find, if the domain already exists.
|
|
|
c480ed |
3) Our lookup functions say it doesn't, so the thread proceeds to
|
|
|
c480ed |
virHashAddEntry() which fails with 'Duplicate key' error.
|
|
|
c480ed |
|
|
|
c480ed |
This is obviously not helpful error message at all.
|
|
|
c480ed |
|
|
|
c480ed |
The problem lies in our lookup functions
|
|
|
c480ed |
(virDomainObjListFindByUUIDLocked() and
|
|
|
c480ed |
virDomainObjListFindByNameLocked()) which return NULL even if the
|
|
|
c480ed |
object is still on the list. They do this so that the object is
|
|
|
c480ed |
not mistakenly looked up by some driver. The fix consists of
|
|
|
c480ed |
moving 'removing' check one level up and thus allowing
|
|
|
c480ed |
virDomainObjListAddLocked() to produce meaningful error message.
|
|
|
c480ed |
|
|
|
c480ed |
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
|
|
|
c480ed |
Reviewed-by: Cole Robinson <crobinso@redhat.com>
|
|
|
c480ed |
(cherry picked from commit a5c71129bf2c12a827f1bc00149acd1c572ffe9c)
|
|
|
c480ed |
|
|
|
c480ed |
Signed-off-by: Ján Tomko <jtomko@redhat.com>
|
|
|
c480ed |
RHEL-8.1.0: https://bugzilla.redhat.com/show_bug.cgi?id=1737790
|
|
|
c480ed |
Message-Id: <c63ca487bf56af5240e273b5a112a753c2bc85a3.1565090956.git.jtomko@redhat.com>
|
|
|
c480ed |
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
|
|
|
c480ed |
---
|
|
|
c480ed |
src/conf/virdomainobjlist.c | 35 +++++++++++++++++++++--------------
|
|
|
c480ed |
1 file changed, 21 insertions(+), 14 deletions(-)
|
|
|
c480ed |
|
|
|
c480ed |
diff --git a/src/conf/virdomainobjlist.c b/src/conf/virdomainobjlist.c
|
|
|
c480ed |
index e7c3e326ca..3b388e2ba2 100644
|
|
|
c480ed |
--- a/src/conf/virdomainobjlist.c
|
|
|
c480ed |
+++ b/src/conf/virdomainobjlist.c
|
|
|
c480ed |
@@ -142,14 +142,9 @@ virDomainObjListFindByUUIDLocked(virDomainObjListPtr doms,
|
|
|
c480ed |
|
|
|
c480ed |
virUUIDFormat(uuid, uuidstr);
|
|
|
c480ed |
obj = virHashLookup(doms->objs, uuidstr);
|
|
|
c480ed |
- virObjectRef(obj);
|
|
|
c480ed |
if (obj) {
|
|
|
c480ed |
+ virObjectRef(obj);
|
|
|
c480ed |
virObjectLock(obj);
|
|
|
c480ed |
- if (obj->removing) {
|
|
|
c480ed |
- virObjectUnlock(obj);
|
|
|
c480ed |
- virObjectUnref(obj);
|
|
|
c480ed |
- obj = NULL;
|
|
|
c480ed |
- }
|
|
|
c480ed |
}
|
|
|
c480ed |
return obj;
|
|
|
c480ed |
}
|
|
|
c480ed |
@@ -173,6 +168,12 @@ virDomainObjListFindByUUID(virDomainObjListPtr doms,
|
|
|
c480ed |
obj = virDomainObjListFindByUUIDLocked(doms, uuid);
|
|
|
c480ed |
virObjectRWUnlock(doms);
|
|
|
c480ed |
|
|
|
c480ed |
+ if (obj && obj->removing) {
|
|
|
c480ed |
+ virObjectUnlock(obj);
|
|
|
c480ed |
+ virObjectUnref(obj);
|
|
|
c480ed |
+ obj = NULL;
|
|
|
c480ed |
+ }
|
|
|
c480ed |
+
|
|
|
c480ed |
return obj;
|
|
|
c480ed |
}
|
|
|
c480ed |
|
|
|
c480ed |
@@ -184,14 +185,9 @@ virDomainObjListFindByNameLocked(virDomainObjListPtr doms,
|
|
|
c480ed |
virDomainObjPtr obj;
|
|
|
c480ed |
|
|
|
c480ed |
obj = virHashLookup(doms->objsName, name);
|
|
|
c480ed |
- virObjectRef(obj);
|
|
|
c480ed |
if (obj) {
|
|
|
c480ed |
+ virObjectRef(obj);
|
|
|
c480ed |
virObjectLock(obj);
|
|
|
c480ed |
- if (obj->removing) {
|
|
|
c480ed |
- virObjectUnlock(obj);
|
|
|
c480ed |
- virObjectUnref(obj);
|
|
|
c480ed |
- obj = NULL;
|
|
|
c480ed |
- }
|
|
|
c480ed |
}
|
|
|
c480ed |
return obj;
|
|
|
c480ed |
}
|
|
|
c480ed |
@@ -215,6 +211,12 @@ virDomainObjListFindByName(virDomainObjListPtr doms,
|
|
|
c480ed |
obj = virDomainObjListFindByNameLocked(doms, name);
|
|
|
c480ed |
virObjectRWUnlock(doms);
|
|
|
c480ed |
|
|
|
c480ed |
+ if (obj && obj->removing) {
|
|
|
c480ed |
+ virObjectUnlock(obj);
|
|
|
c480ed |
+ virObjectUnref(obj);
|
|
|
c480ed |
+ obj = NULL;
|
|
|
c480ed |
+ }
|
|
|
c480ed |
+
|
|
|
c480ed |
return obj;
|
|
|
c480ed |
}
|
|
|
c480ed |
|
|
|
c480ed |
@@ -286,8 +288,13 @@ virDomainObjListAddLocked(virDomainObjListPtr doms,
|
|
|
c480ed |
|
|
|
c480ed |
/* See if a VM with matching UUID already exists */
|
|
|
c480ed |
if ((vm = virDomainObjListFindByUUIDLocked(doms, def->uuid))) {
|
|
|
c480ed |
- /* UUID matches, but if names don't match, refuse it */
|
|
|
c480ed |
- if (STRNEQ(vm->def->name, def->name)) {
|
|
|
c480ed |
+ if (vm->removing) {
|
|
|
c480ed |
+ virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
c480ed |
+ _("domain '%s' is already being removed"),
|
|
|
c480ed |
+ vm->def->name);
|
|
|
c480ed |
+ goto error;
|
|
|
c480ed |
+ } else if (STRNEQ(vm->def->name, def->name)) {
|
|
|
c480ed |
+ /* UUID matches, but if names don't match, refuse it */
|
|
|
c480ed |
virUUIDFormat(vm->def->uuid, uuidstr);
|
|
|
c480ed |
virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
c480ed |
_("domain '%s' is already defined with uuid %s"),
|
|
|
c480ed |
--
|
|
|
c480ed |
2.22.1
|
|
|
c480ed |
|