[libvirt] [PATCH v3 1/3] conf: Add @target_bus to virDomainDefHasDeviceAddress

John Ferlan jferlan at redhat.com
Mon Jul 16 21:14:22 UTC 2018


Add the @target_bus argument which will allow a caller to
pass the virDomainDiskBus onto which the @info (<address>)
would be placed. This will allow logic to provide the bus for
cold plugged devices to determine whether the about to
be added device <address> is already present on the @bus.

Just passing the @info isn't sufficient since, for example,
ADDRESS_TYPE_DRIVE is used for both SCSI and IDE <disk>'s
as well as 'scsi' and 'scsi_host' <hostdev>'s.

Signed-off-by: John Ferlan <jferlan at redhat.com>
---
 src/conf/domain_conf.c | 32 ++++++++++++++++++++++++++++----
 src/conf/domain_conf.h |  3 ++-
 src/qemu/qemu_driver.c |  2 +-
 3 files changed, 31 insertions(+), 6 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 7396616eda..82df8012af 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -3688,13 +3688,31 @@ virDomainDeviceGetInfo(virDomainDeviceDefPtr device)
 }
 
 
+struct virDomainDefHasDeviceAddressIteratorData {
+    int target_bus; /* virDomainDiskBus or -1 */
+    virDomainDeviceInfoPtr info;
+};
+
 static int
 virDomainDefHasDeviceAddressIterator(virDomainDefPtr def ATTRIBUTE_UNUSED,
-                                     virDomainDeviceDefPtr dev ATTRIBUTE_UNUSED,
+                                     virDomainDeviceDefPtr dev,
                                      virDomainDeviceInfoPtr info,
                                      void *opaque)
 {
-    virDomainDeviceInfoPtr needle = opaque;
+    struct virDomainDefHasDeviceAddressIteratorData *data = opaque;
+    int target_bus = data->target_bus;
+    virDomainDeviceInfoPtr needle = data->info;
+
+    /* If the target_bus of the about to be cold plugged device needs
+     * to be checked and the currently to be matched device is a disk,
+     * then compare it's target bus against the new device. If they don't
+     * match, then no need to compare. For disks this ensures addresses
+     * using drive won't erroneously match if one is IDE and another is SCSI.
+     * Likewise, for SCSI hostdev's this ensures the new hostdev doesn't
+     * erroneously match an IDE for the address comparison. */
+    if (target_bus != -1 && dev->type == VIR_DOMAIN_DEVICE_DISK &&
+        dev->data.disk->bus != target_bus)
+        return 0;
 
     /* break iteration if the info was found */
     if (virDomainDeviceInfoAddressIsEqual(info, needle))
@@ -3933,12 +3951,18 @@ virDomainDeviceInfoIterate(virDomainDefPtr def,
 
 bool
 virDomainDefHasDeviceAddress(virDomainDefPtr def,
+                             int target_bus,
                              virDomainDeviceInfoPtr info)
 {
+    struct virDomainDefHasDeviceAddressIteratorData data = {
+        .target_bus = target_bus,
+        .info = info,
+    };
+
     if (virDomainDeviceInfoIterateInternal(def,
                                            virDomainDefHasDeviceAddressIterator,
                                            true,
-                                           info) < 0)
+                                           &data) < 0)
         return true;
 
     return false;
@@ -17508,7 +17532,7 @@ virDomainMemoryInsert(virDomainDefPtr def,
     int id = def->nmems;
 
     if (mem->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
-        virDomainDefHasDeviceAddress(def, &mem->info)) {
+        virDomainDefHasDeviceAddress(def, -1, &mem->info)) {
         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                        _("Domain already contains a device with the same "
                          "address"));
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 0f10e242fd..82231161c6 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2912,8 +2912,9 @@ int virDomainDeviceInfoIterate(virDomainDefPtr def,
                                void *opaque);
 
 bool virDomainDefHasDeviceAddress(virDomainDefPtr def,
+                                  int target_bus,
                                   virDomainDeviceInfoPtr info)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3) ATTRIBUTE_RETURN_CHECK;
 
 void virDomainDefFree(virDomainDefPtr vm);
 
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 8fae46370e..5f91d463ae 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -8082,7 +8082,7 @@ qemuDomainAttachDeviceConfig(virDomainDefPtr vmdef,
 
     case VIR_DOMAIN_DEVICE_RNG:
         if (dev->data.rng->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
-            virDomainDefHasDeviceAddress(vmdef, &dev->data.rng->info)) {
+            virDomainDefHasDeviceAddress(vmdef, -1, &dev->data.rng->info)) {
             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                            _("a device with the same address already exists "));
             return -1;
-- 
2.17.1




More information about the libvir-list mailing list