[libvirt] [PATCH 3/8] Integrate the QEMU driver with the lock manager infrastructure

Daniel P. Berrange berrange at redhat.com
Mon Nov 22 18:09:22 UTC 2010


The QEMU integrates with the lock manager instructure in a number
of key places

 * During startup, a lock is acquired in between the fork & exec
 * During startup, the libvirtd process acquires a lock before
   setting file labelling
 * During shutdown, the libvirtd process acquires a lock
   before restoring file labelling
 * During hotplug, unplug & media change the libvirtd process
   holds a lock while setting/restoring labels

The main content lock is only ever held by the QEMU child process,
or libvirtd during VM shutdown. The rest of the operations only
require libvirtd to hold the metadata locks, relying on the active
QEMU still holding the content lock.

* src/qemu/qemu_conf.c, src/qemu/qemu_conf.h,
  src/qemu/libvirtd_qemu.aug, src/qemu/test_libvirtd_qemu.aug:
  Add config parameter for configuring lock managers
* src/qemu/qemu_driver.c: Add calls to the lock manager
---
 src/qemu/libvirtd_qemu.aug      |    1 +
 src/qemu/qemu_conf.c            |   30 +++++
 src/qemu/qemu_conf.h            |    5 +
 src/qemu/qemu_driver.c          |  253 +++++++++++++++++++++++++++++++++------
 src/qemu/test_libvirtd_qemu.aug |    4 +
 5 files changed, 256 insertions(+), 37 deletions(-)

diff --git a/src/qemu/libvirtd_qemu.aug b/src/qemu/libvirtd_qemu.aug
index 78852f3..5adc447 100644
--- a/src/qemu/libvirtd_qemu.aug
+++ b/src/qemu/libvirtd_qemu.aug
@@ -43,6 +43,7 @@ module Libvirtd_qemu =
                  | bool_entry "clear_emulator_capabilities"
                  | bool_entry "allow_disk_format_probing"
                  | bool_entry "set_process_name"
+                 | str_entry "lock_manager"
 
    (* Each enty in the config is one of the following three ... *)
    let entry = vnc_entry
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 35caccc..dce9a63 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -148,6 +148,14 @@ int qemudLoadDriverConfig(struct qemud_driver *driver,
      */
     if (access (filename, R_OK) == -1) {
         VIR_INFO("Could not read qemu config file %s", filename);
+        if (!(driver->contentLockManager =
+              virLockManagerPluginNew("nop",
+                                      VIR_LOCK_MANAGER_MODE_CONTENT)))
+            VIR_ERROR("Failed to load lock manager %s", "nop");
+        if (!(driver->metadataLockManager =
+              virLockManagerPluginNew("nop",
+                                      VIR_LOCK_MANAGER_MODE_METADATA)))
+            VIR_ERROR("Failed to load lock manager %s", "nop");
         return 0;
     }
 
@@ -435,6 +443,28 @@ int qemudLoadDriverConfig(struct qemud_driver *driver,
     CHECK_TYPE ("set_process_name", VIR_CONF_LONG);
     if (p) driver->setProcessName = p->l;
 
+     p = virConfGetValue (conf, "lock_manager");
+     CHECK_TYPE ("lock_manager", VIR_CONF_STRING);
+     if (p && p->str) {
+         if (!(driver->contentLockManager =
+               virLockManagerPluginNew(p->str,
+                                       VIR_LOCK_MANAGER_MODE_CONTENT)))
+             VIR_ERROR("Failed to load lock manager %s", p->str);
+         if (!(driver->metadataLockManager =
+               virLockManagerPluginNew(p->str,
+                                       VIR_LOCK_MANAGER_MODE_METADATA)))
+             VIR_ERROR("Failed to load lock manager %s", p->str);
+     } else {
+         if (!(driver->contentLockManager =
+               virLockManagerPluginNew("nop",
+                                       VIR_LOCK_MANAGER_MODE_CONTENT)))
+             VIR_ERROR("Failed to load lock manager %s", "nop");
+         if (!(driver->metadataLockManager =
+               virLockManagerPluginNew("nop",
+                                       VIR_LOCK_MANAGER_MODE_METADATA)))
+             VIR_ERROR("Failed to load lock manager %s", "nop");
+     }
+
     virConfFree (conf);
     return 0;
 }
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index ba3c7b1..3789ed2 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -40,6 +40,7 @@
 # include "cpu_conf.h"
 # include "driver.h"
 # include "bitmap.h"
+# include "locking/lock_manager.h"
 
 # define qemudDebug(fmt, ...) do {} while(0)
 
@@ -176,6 +177,10 @@ struct qemud_driver {
     virBitmapPtr reservedVNCPorts;
 
     virSysinfoDefPtr hostsysinfo;
+
+    /* These two might point to the same instance */
+    virLockManagerPluginPtr contentLockManager;
+    virLockManagerPluginPtr metadataLockManager;
 };
 
 typedef struct _qemuDomainPCIAddressSet qemuDomainPCIAddressSet;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 2b901b8..9dcf02d 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -83,6 +83,8 @@
 #include "files.h"
 #include "fdstream.h"
 #include "configmake.h"
+#include "locking/domain_lock.h"
+
 
 #define VIR_FROM_THIS VIR_FROM_QEMU
 
@@ -1857,6 +1859,15 @@ qemudStartup(int privileged) {
         goto error;
     }
 
+    /* We should always at least have the 'nop' manager, so
+     * NULLs here are a fatal error
+     */
+    if (!qemu_driver->contentLockManager ||
+        !qemu_driver->metadataLockManager) {
+        VIR_ERROR0("Missing content/metadata lock managers");
+        goto error;
+    }
+
     if (qemudSecurityInit(qemu_driver) < 0)
         goto error;
 
@@ -2088,6 +2099,9 @@ qemudShutdown(void) {
 
     virCgroupFree(&qemu_driver->cgroup);
 
+    virLockManagerPluginUnref(qemu_driver->contentLockManager);
+    virLockManagerPluginUnref(qemu_driver->metadataLockManager);
+
     qemuDriverUnlock(qemu_driver);
     virMutexDestroy(&qemu_driver->lock);
     VIR_FREE(qemu_driver);
@@ -3650,26 +3664,45 @@ struct qemudHookData {
     virConnectPtr conn;
     virDomainObjPtr vm;
     struct qemud_driver *driver;
+    char *lockState;
 };
 
 static int qemudSecurityHook(void *data) {
     struct qemudHookData *h = data;
+    virDomainLockPtr lock;
+    int ret = -1;
+
+    if (!(lock = virDomainLockForExec(h->driver->contentLockManager,
+                                      h->lockState,
+                                      h->vm)))
+        goto cleanup;
 
     /* This must take place before exec(), so that all QEMU
      * memory allocation is on the correct NUMA node
      */
     if (qemuAddToCgroup(h->driver, h->vm->def) < 0)
-        return -1;
+        goto cleanup;
 
     /* This must be done after cgroup placement to avoid resetting CPU
      * affinity */
     if (qemudInitCpuAffinity(h->vm) < 0)
-        return -1;
+        goto cleanup;
 
     if (virSecurityManagerSetProcessLabel(h->driver->securityManager, h->vm) < 0)
-        return -1;
+        goto cleanup;
 
-    return 0;
+    /* XXX temp hack to let disk labelling complete */
+    sleep(10);
+
+    ret = 0;
+
+cleanup:
+    /* Free, but don't release the lock. The object lock
+     * must remain for lifetime of QEMU process.
+     */
+    virDomainLockFree(lock);
+
+    return ret;
 }
 
 static int
@@ -3864,11 +3897,13 @@ static int qemudStartVMDaemon(virConnectPtr conn,
     int logfile = -1;
     char *timestamp;
     qemuDomainObjPrivatePtr priv = vm->privateData;
+    virDomainLockPtr lock = NULL;
 
     struct qemudHookData hookData;
     hookData.conn = conn;
     hookData.vm = vm;
     hookData.driver = driver;
+    hookData.lockState = NULL; /* XXX add lock state from migration source ! */
 
     FD_ZERO(&keepfd);
 
@@ -3902,11 +3937,6 @@ static int qemudStartVMDaemon(virConnectPtr conn,
     }
     qemuDomainSecurityLabelAudit(vm, true);
 
-    DEBUG0("Generating setting domain security labels (if required)");
-    if (virSecurityManagerSetAllLabel(driver->securityManager,
-                                      vm, stdin_path) < 0)
-        goto cleanup;
-
     /* Ensure no historical cgroup for this VM is lying around bogus
      * settings */
     DEBUG0("Ensuring no historical cgroup is lying around");
@@ -4117,13 +4147,33 @@ static int qemudStartVMDaemon(virConnectPtr conn,
         runflags |= VIR_EXEC_CLEAR_CAPS;
     }
 
+    VIR_WARN("Executing %s", argv[0]);
     ret = virExecDaemonize(argv, progenv, &keepfd, &child,
                            stdin_fd, &logfile, &logfile,
                            runflags,
                            qemudSecurityHook, &hookData,
                            pidfile);
+    VIR_WARN("Executing done %s", argv[0]);
     VIR_FREE(pidfile);
 
+    /* XXX this is bollocks. Need a sync point */
+    sleep(5);
+
+    VIR_WARN("Locking %s", argv[0]);
+    if (!(lock = virDomainLockForStartup(driver->contentLockManager,
+                                         driver->metadataLockManager,
+                                         NULL, /* XXX lock state */
+                                         vm)))
+        goto cleanup;
+
+    VIR_WARN("Labelling %s", argv[0]);
+    DEBUG0("Setting domain security labels");
+    if (virSecurityManagerSetAllLabel(driver->securityManager,
+                                      vm, stdin_path) < 0)
+        goto cleanup;
+    VIR_WARN("All done %s", argv[0]);
+
+
     /* wait for qemu process to to show up */
     if (ret == 0) {
         if (virFileReadPid(driver->stateDir, vm->def->name, &vm->pid)) {
@@ -4213,11 +4263,18 @@ static int qemudStartVMDaemon(virConnectPtr conn,
     if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
         goto cleanup;
 
+    virDomainLockReleaseAndFree(lock);
+
     VIR_FORCE_CLOSE(logfile);
 
     return 0;
 
 cleanup:
+    /* Must release before we call into ShutdownVMDaemon() because
+     * that will re-aquire the lock in order to perform relabelling
+     */
+    virDomainLockReleaseAndFree(lock);
+
     /* We jump here if we failed to start the VM for any reason, or
      * if we failed to initialize the now running VM. kill it off and
      * pretend we never started it */
@@ -4320,8 +4377,14 @@ static void qemudShutdownVMDaemon(struct qemud_driver *driver,
     }
 
     /* Reset Security Labels */
-    virSecurityManagerRestoreAllLabel(driver->securityManager,
-                                      vm, migrated);
+    virDomainLockPtr lock = NULL;
+    if ((lock = virDomainLockForShutdown(driver->contentLockManager,
+                                         driver->metadataLockManager,
+                                         vm)) != NULL) {
+        virSecurityManagerRestoreAllLabel(driver->securityManager,
+                                          vm, migrated);
+        virDomainLockReleaseAndFree(lock);
+    }
     virSecurityManagerReleaseLabel(driver->securityManager,
                                    vm);
 
@@ -7709,6 +7772,8 @@ static int qemudDomainChangeEjectableMedia(struct qemud_driver *driver,
     int i;
     int ret;
     char *driveAlias = NULL;
+    qemuDomainObjPrivatePtr priv = vm->privateData;
+    virDomainLockPtr lock;
 
     origdisk = NULL;
     for (i = 0 ; i < vm->def->ndisks ; i++) {
@@ -7741,14 +7806,28 @@ static int qemudDomainChangeEjectableMedia(struct qemud_driver *driver,
         return -1;
     }
 
+    if (!(lock = virDomainLockForModify(driver->contentLockManager,
+                                        driver->metadataLockManager,
+                                        vm)))
+        return -1;
+
+    if (virDomainLockBeginDiskAttach(lock, disk) < 0) {
+        virDomainLockReleaseAndFree(lock);
+        return -1;
+    }
+
     if (virSecurityManagerSetImageLabel(driver->securityManager,
-                                        vm, disk) < 0)
+                                        vm, disk) < 0) {
+        virDomainLockReleaseAndFree(lock);
         return -1;
+    }
+
+    if (virDomainLockEndDiskAttach(lock, disk) < 0)
+        VIR_WARN("Unable to release lock on disk %s", disk->src);
 
     if (!(driveAlias = qemuDeviceDriveHostAlias(origdisk, qemuCmdFlags)))
         goto error;
 
-    qemuDomainObjPrivatePtr priv = vm->privateData;
     qemuDomainObjEnterMonitorWithDriver(driver, vm);
     if (disk->src) {
         const char *format = NULL;
@@ -7771,9 +7850,13 @@ static int qemudDomainChangeEjectableMedia(struct qemud_driver *driver,
     if (ret < 0)
         goto error;
 
-    if (virSecurityManagerRestoreImageLabel(driver->securityManager,
-                                            vm, origdisk) < 0)
-        VIR_WARN("Unable to restore security label on ejected image %s", origdisk->src);
+    if (virDomainLockBeginDiskDetach(lock, origdisk) >= 0) {
+        if (virSecurityManagerRestoreImageLabel(driver->securityManager,
+                                                vm, origdisk) < 0)
+            VIR_WARN("Unable to restore security label on ejected image %s", origdisk->src);
+        if (virDomainLockEndDiskDetach(lock, origdisk) < 0)
+            VIR_WARN("Unable to release lock on disk %s", origdisk->src);
+    }
 
     VIR_FREE(origdisk->src);
     origdisk->src = disk->src;
@@ -7783,14 +7866,21 @@ static int qemudDomainChangeEjectableMedia(struct qemud_driver *driver,
     VIR_FREE(driveAlias);
 
     virDomainDiskDefFree(disk);
+    virDomainLockReleaseAndFree(lock);
 
     return ret;
 
 error:
     VIR_FREE(driveAlias);
-    if (virSecurityManagerRestoreImageLabel(driver->securityManager,
-                                            vm, disk) < 0)
-        VIR_WARN("Unable to restore security label on new media %s", disk->src);
+
+    if (virDomainLockBeginDiskDetach(lock, disk) >= 0) {
+        if (virSecurityManagerRestoreImageLabel(driver->securityManager,
+                                                vm, disk) < 0)
+            VIR_WARN("Unable to restore security label on new media %s", disk->src);
+        if (virDomainLockEndDiskDetach(lock, disk) < 0)
+            VIR_WARN("Unable to release lock on disk %s", disk->src);
+    }
+    virDomainLockReleaseAndFree(lock);
 
     return -1;
 }
@@ -7806,6 +7896,7 @@ static int qemudDomainAttachPciDiskDevice(struct qemud_driver *driver,
     qemuDomainObjPrivatePtr priv = vm->privateData;
     char *devstr = NULL;
     char *drivestr = NULL;
+    virDomainLockPtr lock = NULL;
 
     for (i = 0 ; i < vm->def->ndisks ; i++) {
         if (STREQ(vm->def->disks[i]->dst, disk->dst)) {
@@ -7815,9 +7906,24 @@ static int qemudDomainAttachPciDiskDevice(struct qemud_driver *driver,
         }
     }
 
+    if (!(lock = virDomainLockForModify(driver->contentLockManager,
+                                        driver->metadataLockManager,
+                                        vm)))
+        return -1;
+
+    if (virDomainLockBeginDiskAttach(lock, disk) < 0) {
+        virDomainLockReleaseAndFree(lock);
+        return -1;
+    }
+
     if (virSecurityManagerSetImageLabel(driver->securityManager,
-                                        vm, disk) < 0)
+                                        vm, disk) < 0) {
+        virDomainLockReleaseAndFree(lock);
         return -1;
+    }
+
+    if (virDomainLockEndDiskAttach(lock, disk) < 0)
+        VIR_WARN("Unable to release lock on disk %s", disk->src);
 
     if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
         if (qemuDomainPCIAddressEnsureAddr(priv->pciaddrs, &disk->info) < 0)
@@ -7871,6 +7977,7 @@ static int qemudDomainAttachPciDiskDevice(struct qemud_driver *driver,
 
     VIR_FREE(devstr);
     VIR_FREE(drivestr);
+    virDomainLockReleaseAndFree(lock);
 
     return 0;
 
@@ -7883,9 +7990,14 @@ error:
         qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &disk->info) < 0)
         VIR_WARN("Unable to release PCI address on %s", disk->src);
 
-    if (virSecurityManagerRestoreImageLabel(driver->securityManager,
-                                            vm, disk) < 0)
-        VIR_WARN("Unable to restore security label on %s", disk->src);
+    if (virDomainLockBeginDiskDetach(lock, disk) >= 0) {
+        if (virSecurityManagerRestoreImageLabel(driver->securityManager,
+                                                vm, disk) < 0)
+            VIR_WARN("Unable to restore security label on %s", disk->src);
+        if (virDomainLockEndDiskDetach(lock, disk) < 0)
+            VIR_WARN("Unable to release lock on disk %s", disk->src);
+    }
+    virDomainLockReleaseAndFree(lock);
 
     return -1;
 }
@@ -8014,6 +8126,7 @@ static int qemudDomainAttachSCSIDisk(struct qemud_driver *driver,
     char *drivestr = NULL;
     char *devstr = NULL;
     int ret = -1;
+    virDomainLockPtr lock = NULL;
 
     for (i = 0 ; i < vm->def->ndisks ; i++) {
         if (STREQ(vm->def->disks[i]->dst, disk->dst)) {
@@ -8023,10 +8136,24 @@ static int qemudDomainAttachSCSIDisk(struct qemud_driver *driver,
         }
     }
 
+    if (!(lock = virDomainLockForModify(driver->contentLockManager,
+                                        driver->metadataLockManager,
+                                        vm)))
+        return -1;
+
+    if (virDomainLockBeginDiskAttach(lock, disk) < 0) {
+        virDomainLockReleaseAndFree(lock);
+        return -1;
+    }
 
     if (virSecurityManagerSetImageLabel(driver->securityManager,
-                                        vm, disk) < 0)
+                                        vm, disk) < 0) {
+        virDomainLockReleaseAndFree(lock);
         return -1;
+    }
+
+    if (virDomainLockEndDiskAttach(lock, disk) < 0)
+        VIR_WARN("Unable to release lock on disk %s", disk->src);
 
     /* We should have an address already, so make sure */
     if (disk->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE) {
@@ -8104,6 +8231,7 @@ static int qemudDomainAttachSCSIDisk(struct qemud_driver *driver,
 
     VIR_FREE(devstr);
     VIR_FREE(drivestr);
+    virDomainLockReleaseAndFree(lock);
 
     return 0;
 
@@ -8111,9 +8239,14 @@ error:
     VIR_FREE(devstr);
     VIR_FREE(drivestr);
 
-    if (virSecurityManagerRestoreImageLabel(driver->securityManager,
-                                            vm, disk) < 0)
-        VIR_WARN("Unable to restore security label on %s", disk->src);
+    if (virDomainLockBeginDiskDetach(lock, disk) >= 0) {
+        if (virSecurityManagerRestoreImageLabel(driver->securityManager,
+                                                vm, disk) < 0)
+            VIR_WARN("Unable to restore security label on %s", disk->src);
+        if (virDomainLockEndDiskDetach(lock, disk) < 0)
+            VIR_WARN("Unable to release lock on disk %s", disk->src);
+    }
+    virDomainLockReleaseAndFree(lock);
 
     return -1;
 }
@@ -8128,6 +8261,7 @@ static int qemudDomainAttachUsbMassstorageDevice(struct qemud_driver *driver,
     int i, ret;
     char *drivestr = NULL;
     char *devstr = NULL;
+    virDomainLockPtr lock = NULL;
 
     for (i = 0 ; i < vm->def->ndisks ; i++) {
         if (STREQ(vm->def->disks[i]->dst, disk->dst)) {
@@ -8137,10 +8271,26 @@ static int qemudDomainAttachUsbMassstorageDevice(struct qemud_driver *driver,
         }
     }
 
+    if (!(lock = virDomainLockForModify(driver->contentLockManager,
+                                        driver->metadataLockManager,
+                                        vm)))
+        return -1;
+
+    if (virDomainLockBeginDiskAttach(lock, disk) < 0) {
+        virDomainLockReleaseAndFree(lock);
+        return -1;
+    }
+
     if (virSecurityManagerSetImageLabel(driver->securityManager,
-                                        vm, disk) < 0)
+                                        vm, disk) < 0) {
+        virDomainLockReleaseAndFree(lock);
         return -1;
+    }
+
+    if (virDomainLockEndDiskAttach(lock, disk) < 0)
+        VIR_WARN("Unable to release lock on disk %s", disk->src);
 
+    /* XXX not correct once we allow attaching a USB CDROM */
     if (!disk->src) {
         qemuReportError(VIR_ERR_INTERNAL_ERROR,
                         "%s", _("disk source path is missing"));
@@ -8187,6 +8337,7 @@ static int qemudDomainAttachUsbMassstorageDevice(struct qemud_driver *driver,
 
     VIR_FREE(devstr);
     VIR_FREE(drivestr);
+    virDomainLockReleaseAndFree(lock);
 
     return 0;
 
@@ -8194,9 +8345,15 @@ error:
     VIR_FREE(devstr);
     VIR_FREE(drivestr);
 
-    if (virSecurityManagerRestoreImageLabel(driver->securityManager,
-                                            vm, disk) < 0)
-        VIR_WARN("Unable to restore security label on %s", disk->src);
+
+    if (virDomainLockBeginDiskDetach(lock, disk) >= 0) {
+        if (virSecurityManagerRestoreImageLabel(driver->securityManager,
+                                                vm, disk) < 0)
+            VIR_WARN("Unable to restore security label on %s", disk->src);
+        if (virDomainLockEndDiskDetach(lock, disk) < 0)
+            VIR_WARN("Unable to release lock on disk %s", disk->src);
+    }
+    virDomainLockReleaseAndFree(lock);
 
     return -1;
 }
@@ -9032,6 +9189,12 @@ static int qemudDomainDetachPciDiskDevice(struct qemud_driver *driver,
     virDomainDiskDefPtr detach = NULL;
     qemuDomainObjPrivatePtr priv = vm->privateData;
     virCgroupPtr cgroup = NULL;
+    virDomainLockPtr lock = NULL;
+
+    if (!(lock = virDomainLockForModify(driver->contentLockManager,
+                                        driver->metadataLockManager,
+                                        vm)))
+        return -1;
 
     i = qemudFindDisk(vm->def, dev->data.disk->dst);
 
@@ -9084,9 +9247,13 @@ static int qemudDomainDetachPciDiskDevice(struct qemud_driver *driver,
 
     virDomainDiskDefFree(detach);
 
-    if (virSecurityManagerRestoreImageLabel(driver->securityManager,
-                                            vm, dev->data.disk) < 0)
-        VIR_WARN("Unable to restore security label on %s", dev->data.disk->src);
+    if (virDomainLockBeginDiskDetach(lock, dev->data.disk)) {
+        if (virSecurityManagerRestoreImageLabel(driver->securityManager,
+                                                vm, dev->data.disk) < 0)
+            VIR_WARN("Unable to restore security label on %s", dev->data.disk->src);
+        if (virDomainLockEndDiskDetach(lock, dev->data.disk) < 0)
+            VIR_WARN("Unable to release lock on disk %s", dev->data.disk->src);
+    }
 
     if (cgroup != NULL) {
         if (qemuTeardownDiskCgroup(driver, cgroup, dev->data.disk) < 0)
@@ -9097,6 +9264,7 @@ static int qemudDomainDetachPciDiskDevice(struct qemud_driver *driver,
     ret = 0;
 
 cleanup:
+    virDomainLockReleaseAndFree(lock);
     return ret;
 }
 
@@ -9109,6 +9277,12 @@ static int qemudDomainDetachSCSIDiskDevice(struct qemud_driver *driver,
     virDomainDiskDefPtr detach = NULL;
     qemuDomainObjPrivatePtr priv = vm->privateData;
     virCgroupPtr cgroup = NULL;
+    virDomainLockPtr lock = NULL;
+
+    if (!(lock = virDomainLockForModify(driver->contentLockManager,
+                                        driver->metadataLockManager,
+                                        vm)))
+        return -1;
 
     i = qemudFindDisk(vm->def, dev->data.disk->dst);
 
@@ -9148,9 +9322,13 @@ static int qemudDomainDetachSCSIDiskDevice(struct qemud_driver *driver,
 
     virDomainDiskDefFree(detach);
 
-    if (virSecurityManagerRestoreImageLabel(driver->securityManager,
-                                            vm, dev->data.disk) < 0)
-        VIR_WARN("Unable to restore security label on %s", dev->data.disk->src);
+    if (virDomainLockBeginDiskDetach(lock, dev->data.disk)) {
+        if (virSecurityManagerRestoreImageLabel(driver->securityManager,
+                                                vm, dev->data.disk) < 0)
+            VIR_WARN("Unable to restore security label on %s", dev->data.disk->src);
+        if (virDomainLockEndDiskDetach(lock, dev->data.disk) < 0)
+            VIR_WARN("Unable to release lock on disk %s", dev->data.disk->src);
+    }
 
     if (cgroup != NULL) {
         if (qemuTeardownDiskCgroup(driver, cgroup, dev->data.disk) < 0)
@@ -9162,6 +9340,7 @@ static int qemudDomainDetachSCSIDiskDevice(struct qemud_driver *driver,
 
 cleanup:
     virCgroupFree(&cgroup);
+    virDomainLockReleaseAndFree(lock);
     return ret;
 }
 
diff --git a/src/qemu/test_libvirtd_qemu.aug b/src/qemu/test_libvirtd_qemu.aug
index d3ae58d..fd56eb9 100644
--- a/src/qemu/test_libvirtd_qemu.aug
+++ b/src/qemu/test_libvirtd_qemu.aug
@@ -107,6 +107,8 @@ vnc_allow_host_audio = 1
 clear_emulator_capabilities = 0
 
 allow_disk_format_probing = 1
+
+lock_manager = \"fcntl\"
 "
 
    test Libvirtd_qemu.lns get conf =
@@ -224,3 +226,5 @@ allow_disk_format_probing = 1
 { "clear_emulator_capabilities" = "0" }
 { "#empty" }
 { "allow_disk_format_probing" = "1" }
+{ "#empty" }
+{ "lock_manager" = "fcntl" }
-- 
1.7.2.3




More information about the libvir-list mailing list