[libvirt] [PATCH 18/25] qemu: Refactor the helpers to track shared scsi host device

Osier Yang jyang at redhat.com
Fri May 3 18:07:37 UTC 2013


This changes the helpers qemu{Add,Remove}SharedDisk into
qemu{Add,Remove}SharedDevice, as most of the code in the helpers
can be reused for scsi host device.

To track the shared scsi host device, first it finds out the
device path (e.g. /dev/s[dr]*) which is mapped to the sg device,
and use device ID of the found device path (/dev/s[dr]*) as the
hash key. This is because of the device ID is not unique between
between /dev/s[dr]* and /dev/sg*, e.g.

% sg_map
/dev/sg0  /dev/sda
/dev/sg1  /dev/sr0

% ls -l /dev/sda
brw-rw----. 1 root disk 8, 0 May  2 19:26 /dev/sda

%ls -l /dev/sg0
crw-rw----. 1 root disk 21, 0 May  2 19:26 /dev/sg0
---
 src/qemu/qemu_conf.c    | 143 ++++++++++++++++++++++++++++++++++++------------
 src/qemu/qemu_conf.h    |  20 +++----
 src/qemu/qemu_driver.c  |  16 +++---
 src/qemu/qemu_process.c |  19 +++++--
 4 files changed, 140 insertions(+), 58 deletions(-)

diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 244795d..ebcd176 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -1084,47 +1084,80 @@ cleanup:
     return NULL;
 }
 
-/* qemuAddSharedDisk:
+/* qemuAddSharedDevice:
  * @driver: Pointer to qemu driver struct
- * @disk: The disk def
+ * @dev: The device def
  * @name: The domain name
  *
  * Increase ref count and add the domain name into the list which
- * records all the domains that use the shared disk if the entry
+ * records all the domains that use the shared device if the entry
  * already exists, otherwise add a new entry.
  */
 int
-qemuAddSharedDisk(virQEMUDriverPtr driver,
-                  virDomainDiskDefPtr disk,
-                  const char *name)
+qemuAddSharedDevice(virQEMUDriverPtr driver,
+                    virDomainDeviceDefPtr dev,
+                    const char *name)
 {
     qemuSharedDeviceEntry *entry = NULL;
     qemuSharedDeviceEntry *new_entry = NULL;
+    virDomainDiskDefPtr disk = NULL;
+    virDomainHostdevDefPtr hostdev = NULL;
+    char *dev_name = NULL;
+    char *dev_path = NULL;
     char *key = NULL;
     int ret = -1;
 
-    /* Currently the only conflicts we have to care about
-     * for the shared disk is "sgio" setting, which is only
-     * valid for block disk.
+    /* Currently the only conflicts we have to care about for
+     * the shared disk and shared host device is "sgio" setting,
+     * which is only valid for block disk and scsi host device.
      */
-    if (!disk->shared ||
-        !disk->src ||
-        (disk->type != VIR_DOMAIN_DISK_TYPE_BLOCK &&
-         !(disk->type == VIR_DOMAIN_DISK_TYPE_VOLUME &&
-           disk->srcpool &&
-           disk->srcpool->voltype == VIR_STORAGE_VOL_BLOCK)))
+    if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
+        disk = dev->data.disk;
+
+        if (disk->shared ||
+            !disk->src ||
+            (disk->type != VIR_DOMAIN_DISK_TYPE_BLOCK &&
+             !(disk->type == VIR_DOMAIN_DISK_TYPE_VOLUME &&
+               disk->srcpool &&
+               disk->srcpool->voltype == VIR_STORAGE_VOL_BLOCK)))
+            return 0;
+    } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) {
+        hostdev = dev->data.hostdev;
+
+        if (!hostdev->shareable ||
+            (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
+             hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI))
+            return 0;
+    } else {
         return 0;
+    }
 
     qemuDriverLock(driver);
-    if (qemuCheckSharedDisk(driver->sharedDevices, disk) < 0)
-        goto cleanup;
+    if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
+        if (qemuCheckSharedDisk(driver->sharedDevices, disk) < 0)
+            goto cleanup;
 
-    if (!(key = qemuGetSharedDeviceKey(disk->src)))
-        goto cleanup;
+        if (!(key = qemuGetSharedDeviceKey(disk->src)))
+            goto cleanup;
+    } else {
+        if (!(dev_name = virSCSIDeviceGetDevName(hostdev->source.subsys.u.scsi.adapter,
+                                                 hostdev->source.subsys.u.scsi.bus,
+                                                 hostdev->source.subsys.u.scsi.target,
+                                                 hostdev->source.subsys.u.scsi.unit)))
+            goto cleanup;
+
+        if (virAsprintf(&dev_path, "/dev/%s", dev_name) < 0) {
+            virReportOOMError();
+            goto cleanup;
+        }
+
+        if (!(key = qemuGetSharedDeviceKey(dev_path)))
+            goto cleanup;
+    }
 
     if ((entry = virHashLookup(driver->sharedDevices, key))) {
-        /* Nothing to do if the shared disk is already recorded
-         * in the table.
+        /* Nothing to do if the shared scsi host device is already
+         * recorded in the table.
          */
         if (qemuSharedDeviceEntryDomainExists(entry, name, NULL)) {
             ret = 0;
@@ -1163,41 +1196,77 @@ qemuAddSharedDisk(virQEMUDriverPtr driver,
     ret = 0;
 cleanup:
     qemuDriverUnlock(driver);
+    VIR_FREE(dev_name);
+    VIR_FREE(dev_path);
     VIR_FREE(key);
     return ret;
 }
 
-/* qemuRemoveSharedDisk:
+/* qemuRemoveSharedDevice:
  * @driver: Pointer to qemu driver struct
- * @disk: The disk def
+ * @device: The device def
  * @name: The domain name
  *
  * Decrease ref count and remove the domain name from the list which
- * records all the domains that use the shared disk if ref is not 1,
- * otherwise remove the entry.
+ * records all the domains that use the shared device if ref is not
+ * 1, otherwise remove the entry.
  */
 int
-qemuRemoveSharedDisk(virQEMUDriverPtr driver,
-                     virDomainDiskDefPtr disk,
-                     const char *name)
+qemuRemoveSharedDevice(virQEMUDriverPtr driver,
+                       virDomainDeviceDefPtr dev,
+                       const char *name)
 {
     qemuSharedDeviceEntryPtr entry = NULL;
     qemuSharedDeviceEntryPtr new_entry = NULL;
+    virDomainDiskDefPtr disk = NULL;
+    virDomainHostdevDefPtr hostdev = NULL;
     char *key = NULL;
+    char *dev_name = NULL;
+    char *dev_path = NULL;
     int ret = -1;
     int idx;
 
-    if (!disk->shared ||
-        !disk->src ||
-        (disk->type != VIR_DOMAIN_DISK_TYPE_BLOCK &&
-         !(disk->type == VIR_DOMAIN_DISK_TYPE_VOLUME &&
-           disk->srcpool &&
-           disk->srcpool->voltype == VIR_STORAGE_VOL_BLOCK)))
+    if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
+        disk = dev->data.disk;
+
+        if (!disk->shared ||
+            !disk->src ||
+            (disk->type != VIR_DOMAIN_DISK_TYPE_BLOCK &&
+             !(disk->type == VIR_DOMAIN_DISK_TYPE_VOLUME &&
+               disk->srcpool &&
+               disk->srcpool->voltype == VIR_STORAGE_VOL_BLOCK)))
+            return 0;
+    } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) {
+        hostdev = dev->data.hostdev;
+
+        if (!hostdev->shareable ||
+            (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
+             hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI))
+            return 0;
+    } else {
         return 0;
+    }
 
     qemuDriverLock(driver);
-    if (!(key = qemuGetSharedDeviceKey(disk->src)))
-        goto cleanup;
+
+    if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
+        if (!(key = qemuGetSharedDeviceKey(disk->src)))
+            goto cleanup;
+    } else {
+        if (!(dev_name = virSCSIDeviceGetDevName(hostdev->source.subsys.u.scsi.adapter,
+                                                 hostdev->source.subsys.u.scsi.bus,
+                                                 hostdev->source.subsys.u.scsi.target,
+                                                 hostdev->source.subsys.u.scsi.unit)))
+            goto cleanup;
+
+        if (virAsprintf(&dev_path, "/dev/%s", dev_name) < 0) {
+            virReportOOMError();
+            goto cleanup;
+        }
+
+        if (!(key = qemuGetSharedDeviceKey(dev_path)))
+            goto cleanup;
+    }
 
     if (!(entry = virHashLookup(driver->sharedDevices, key)))
         goto cleanup;
@@ -1233,6 +1302,8 @@ qemuRemoveSharedDisk(virQEMUDriverPtr driver,
     ret = 0;
 cleanup:
     qemuDriverUnlock(driver);
+    VIR_FREE(dev_name);
+    VIR_FREE(dev_path);
     VIR_FREE(key);
     return ret;
 }
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index d4a54a0..c004f7f 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -283,22 +283,22 @@ bool qemuSharedDeviceEntryDomainExists(qemuSharedDeviceEntryPtr entry,
                                        int *index)
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
 
-int qemuAddSharedDisk(virQEMUDriverPtr driver,
-                      virDomainDiskDefPtr disk,
-                      const char *name)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
-
-int qemuRemoveSharedDisk(virQEMUDriverPtr driver,
-                         virDomainDiskDefPtr disk,
-                         const char *name)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
-
 char * qemuGetSharedDeviceKey(const char *disk_path)
     ATTRIBUTE_NONNULL(1);
 
 void qemuSharedDeviceEntryFree(void *payload, const void *name)
     ATTRIBUTE_NONNULL(1);
 
+int qemuAddSharedDevice(virQEMUDriverPtr driver,
+                        virDomainDeviceDefPtr dev,
+                        const char *name)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
+
+int qemuRemoveSharedDevice(virQEMUDriverPtr driver,
+                           virDomainDeviceDefPtr dev,
+                           const char *name)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
+
 int qemuDriverAllocateID(virQEMUDriverPtr driver);
 virDomainXMLOptionPtr virQEMUDriverCreateXMLConf(virQEMUDriverPtr driver);
 
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 4c2ab7b..991b68b 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -5648,7 +5648,7 @@ qemuDomainAttachDeviceDiskLive(virConnectPtr conn,
     if (qemuTranslateDiskSourcePool(conn, disk) < 0)
         goto end;
 
-    if (qemuAddSharedDisk(driver, disk, vm->def->name) < 0)
+    if (qemuAddSharedDevice(driver, dev, vm->def->name) < 0)
         goto end;
 
     if (qemuSetUnprivSGIO(disk) < 0)
@@ -5694,8 +5694,8 @@ qemuDomainAttachDeviceDiskLive(virConnectPtr conn,
          * if the operation is either ejecting or updating.
          */
         if (ret == 0)
-            ignore_value(qemuRemoveSharedDisk(driver, dev_copy->data.disk,
-                                              vm->def->name));
+            ignore_value(qemuRemoveSharedDevice(driver, dev_copy,
+                                                vm->def->name));
         break;
     case VIR_DOMAIN_DISK_DEVICE_DISK:
     case VIR_DOMAIN_DISK_DEVICE_LUN:
@@ -5732,7 +5732,7 @@ qemuDomainAttachDeviceDiskLive(virConnectPtr conn,
 
 end:
     if (ret != 0)
-        ignore_value(qemuRemoveSharedDisk(driver, disk, vm->def->name));
+        ignore_value(qemuRemoveSharedDevice(driver, dev, vm->def->name));
     virObjectUnref(caps);
     virDomainDeviceDefFree(dev_copy);
     return ret;
@@ -5848,7 +5848,7 @@ qemuDomainDetachDeviceDiskLive(virQEMUDriverPtr driver,
     }
 
     if (ret == 0)
-        ignore_value(qemuRemoveSharedDisk(driver, disk, vm->def->name));
+        ignore_value(qemuRemoveSharedDevice(driver, dev, vm->def->name));
 
     return ret;
 }
@@ -5955,7 +5955,7 @@ qemuDomainChangeDiskMediaLive(virConnectPtr conn,
         dev->data.disk = tmp;
 
         /* Add the new disk src into shared disk hash table */
-        if (qemuAddSharedDisk(driver, dev->data.disk, vm->def->name) < 0)
+        if (qemuAddSharedDevice(driver, dev, vm->def->name) < 0)
             goto end;
 
         ret = qemuDomainChangeEjectableMedia(driver, vm, disk, orig_disk, force);
@@ -5968,8 +5968,8 @@ qemuDomainChangeDiskMediaLive(virConnectPtr conn,
          */
         if (ret == 0) {
             dev->data.disk = NULL;
-            ignore_value(qemuRemoveSharedDisk(driver, dev_copy->data.disk,
-                                              vm->def->name));
+            ignore_value(qemuRemoveSharedDevice(driver, dev_copy,
+                                                vm->def->name));
         }
         break;
     default:
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 70eadb6..117c669 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -2982,10 +2982,14 @@ qemuProcessReconnect(void *opaque)
      * qemu_driver->sharedDevices.
      */
     for (i = 0; i < obj->def->ndisks; i++) {
+        virDomainDeviceDef dev;
+
         if (qemuTranslateDiskSourcePool(conn, obj->def->disks[i]) < 0)
             goto error;
-        if (qemuAddSharedDisk(driver, obj->def->disks[i],
-                              obj->def->name) < 0)
+
+        dev.type = VIR_DOMAIN_DEVICE_DISK;
+        dev.data.disk = obj->def->disks[i];
+        if (qemuAddSharedDevice(driver, &dev, obj->def->name) < 0)
             goto error;
     }
 
@@ -3663,6 +3667,7 @@ int qemuProcessStart(virConnectPtr conn,
 
     /* in case a certain disk is desirous of CAP_SYS_RAWIO, add this */
     for (i = 0; i < vm->def->ndisks; i++) {
+        virDomainDeviceDef dev;
         virDomainDiskDefPtr disk = vm->def->disks[i];
 
         if (vm->def->disks[i]->rawio == 1)
@@ -3673,7 +3678,9 @@ int qemuProcessStart(virConnectPtr conn,
                            _("Raw I/O is not supported on this platform"));
 #endif
 
-        if (qemuAddSharedDisk(driver, disk, vm->def->name) < 0)
+        dev.type = VIR_DOMAIN_DEVICE_DISK;
+        dev.data.disk = disk;
+        if (qemuAddSharedDevice(driver, &dev, vm->def->name) < 0)
             goto cleanup;
 
         if (qemuSetUnprivSGIO(disk) < 0)
@@ -4084,8 +4091,12 @@ void qemuProcessStop(virQEMUDriverPtr driver,
     virSecurityManagerReleaseLabel(driver->securityManager, vm->def);
 
     for (i = 0; i < vm->def->ndisks; i++) {
+        virDomainDeviceDef dev;
         virDomainDiskDefPtr disk = vm->def->disks[i];
-        ignore_value(qemuRemoveSharedDisk(driver, disk, vm->def->name));
+
+        dev.type = VIR_DOMAIN_DEVICE_DISK;
+        dev.data.disk = disk;
+        ignore_value(qemuRemoveSharedDevice(driver, &dev, vm->def->name));
     }
 
     /* Clear out dynamically assigned labels */
-- 
1.8.1.4




More information about the libvir-list mailing list