render / rpms / libvirt

Forked from rpms/libvirt 10 months ago
Clone
9119d9
From eeb166cea4a966f01d9241eba1d465d8466e7768 Mon Sep 17 00:00:00 2001
9119d9
Message-Id: <eeb166cea4a966f01d9241eba1d465d8466e7768@dist-git>
9119d9
From: Martin Kletzander <mkletzan@redhat.com>
9119d9
Date: Sat, 13 Dec 2014 10:10:52 +0100
9119d9
Subject: [PATCH] qemu: avoid rare race when undefining domain
9119d9
9119d9
When one domain is being undefined and at the same time started, for
9119d9
example, there is a possibility of a rare problem occuring.
9119d9
9119d9
 - Thread 1 does virDomainUndefine(), has the lock, checks that the
9119d9
   domain is active and because it's not, calls
9119d9
   virDomainObjListRemove().
9119d9
9119d9
 - Thread 2 does virDomainCreate() and tries to lock the domain.
9119d9
9119d9
 - Thread 1 needs to lock domain list in order to remove the domain from
9119d9
   it, but must unlock domain first (proper order is to lock domain list
9119d9
   first and the domain itself second).
9119d9
9119d9
 - Thread 2 grabs the lock, starts the domain and releases the lock.
9119d9
9119d9
 - Thread 1 grabs the lock and removes the domain from list.
9119d9
9119d9
With this patch:
9119d9
9119d9
 - The undefining domain gets marked as "to undefine" before it is
9119d9
    unlocked.
9119d9
9119d9
 - If domain is found in any of the search APIs, it's returned only if
9119d9
   it is not marked as "to undefine".  The check is done while the
9119d9
   domain is locked.
9119d9
9119d9
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1150505
9119d9
9119d9
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
9119d9
(cherry picked from commit c7d1c139ca3402e875002753952e80ce8054374e)
9119d9
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
9119d9
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
9119d9
---
9119d9
 src/conf/domain_conf.c | 22 +++++++++++++++++++---
9119d9
 src/conf/domain_conf.h |  1 +
9119d9
 2 files changed, 20 insertions(+), 3 deletions(-)
9119d9
9119d9
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
9119d9
index 25f20f8..20ae4e7 100644
9119d9
--- a/src/conf/domain_conf.c
9119d9
+++ b/src/conf/domain_conf.c
9119d9
@@ -1056,8 +1056,13 @@ virDomainObjPtr virDomainObjListFindByID(virDomainObjListPtr doms,
9119d9
     virDomainObjPtr obj;
9119d9
     virObjectLock(doms);
9119d9
     obj = virHashSearch(doms->objs, virDomainObjListSearchID, &id;;
9119d9
-    if (obj)
9119d9
+    if (obj) {
9119d9
         virObjectLock(obj);
9119d9
+        if (obj->removing) {
9119d9
+            virObjectUnlock(obj);
9119d9
+            obj = NULL;
9119d9
+        }
9119d9
+    }
9119d9
     virObjectUnlock(doms);
9119d9
     return obj;
9119d9
 }
9119d9
@@ -1073,8 +1078,13 @@ virDomainObjPtr virDomainObjListFindByUUID(virDomainObjListPtr doms,
9119d9
     virUUIDFormat(uuid, uuidstr);
9119d9
 
9119d9
     obj = virHashLookup(doms->objs, uuidstr);
9119d9
-    if (obj)
9119d9
+    if (obj) {
9119d9
         virObjectLock(obj);
9119d9
+        if (obj->removing) {
9119d9
+            virObjectUnlock(obj);
9119d9
+            obj = NULL;
9119d9
+        }
9119d9
+    }
9119d9
     virObjectUnlock(doms);
9119d9
     return obj;
9119d9
 }
9119d9
@@ -1099,8 +1109,13 @@ virDomainObjPtr virDomainObjListFindByName(virDomainObjListPtr doms,
9119d9
     virDomainObjPtr obj;
9119d9
     virObjectLock(doms);
9119d9
     obj = virHashSearch(doms->objs, virDomainObjListSearchName, name);
9119d9
-    if (obj)
9119d9
+    if (obj) {
9119d9
         virObjectLock(obj);
9119d9
+        if (obj->removing) {
9119d9
+            virObjectUnlock(obj);
9119d9
+            obj = NULL;
9119d9
+        }
9119d9
+    }
9119d9
     virObjectUnlock(doms);
9119d9
     return obj;
9119d9
 }
9119d9
@@ -2537,6 +2552,7 @@ void virDomainObjListRemove(virDomainObjListPtr doms,
9119d9
 {
9119d9
     char uuidstr[VIR_UUID_STRING_BUFLEN];
9119d9
 
9119d9
+    dom->removing = true;
9119d9
     virUUIDFormat(dom->def->uuid, uuidstr);
9119d9
     virObjectRef(dom);
9119d9
     virObjectUnlock(dom);
9119d9
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
9119d9
index 04cee80..01d5aeb 100644
9119d9
--- a/src/conf/domain_conf.h
9119d9
+++ b/src/conf/domain_conf.h
9119d9
@@ -2149,6 +2149,7 @@ struct _virDomainObj {
9119d9
     unsigned int autostart : 1;
9119d9
     unsigned int persistent : 1;
9119d9
     unsigned int updated : 1;
9119d9
+    unsigned int removing : 1;
9119d9
 
9119d9
     virDomainDefPtr def; /* The current definition */
9119d9
     virDomainDefPtr newDef; /* New definition to activate at shutdown */
9119d9
-- 
9119d9
2.2.0
9119d9