qemuDomainAttachDevicePersistent() calls qemuDomainAssignPCIAddresses()
and virDomainDefAddImplicitControllers() at the end of its call.
But PCI/Drive address confliction checks are
PCI - confliction will be found but error report is not verbose.
Drive - never done.
For example, when adding a device which has already used address.
error: Failed to attach device from /home/kamezawa/testc.xml
error: An error occurred, but the cause is unknown
After patch, the message will be
error: Failed to attach device from /home/kamezawa/testc.xml
error: invalid argument in device address conflict
This error report is better. And new code aslo checks devices other
than PCI devices.
Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu(a)jp.fujitsu.com>
Changelog:
- typo fix.
---
src/conf/domain_conf.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++
src/conf/domain_conf.h | 2 +
src/libvirt_private.syms | 1 +
src/qemu/qemu_driver.c | 3 ++
4 files changed, 71 insertions(+), 0 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index a39da7e..1de4c7a 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1305,6 +1305,71 @@ void virDomainDefClearDeviceAliases(virDomainDefPtr def)
virDomainDeviceInfoIterate(def, virDomainDeviceInfoClearAlias, NULL);
}
+static int virDomainDeviceAddressMatch(virDomainDefPtr def ATTRIBUTE_UNUSED,
+ virDomainDeviceInfoPtr info,
+ void *opaque)
+{
+ virDomainDeviceInfoPtr checked = opaque;
+ /* skip to check confliction of alias */
+ if (info->type != checked->type)
+ return 0;
+ if (info->alias && checked->alias && STREQ(info->alias,
checked->alias))
+ return -1;
+ /* addr is zero cleared before filled */
+ if (!memcmp(&info->addr, &checked->addr, sizeof(info->addr)))
+ return -1;
+ return 0;
+}
+
+int virDomainDefFindDeviceAddressConflict(virDomainDefPtr def,
+ virDomainDeviceDefPtr dev)
+{
+ virDomainDeviceInfoPtr checked;
+ int ret;
+
+ switch (dev->type) {
+ case VIR_DOMAIN_DEVICE_DISK:
+ checked = &dev->data.disk->info;
+ break;
+ case VIR_DOMAIN_DEVICE_FS:
+ checked = &dev->data.fs->info;
+ break;
+ case VIR_DOMAIN_DEVICE_NET:
+ checked = &dev->data.net->info;
+ break;
+ case VIR_DOMAIN_DEVICE_INPUT:
+ checked = &dev->data.input->info;
+ break;
+ case VIR_DOMAIN_DEVICE_SOUND:
+ checked = &dev->data.sound->info;
+ break;
+ case VIR_DOMAIN_DEVICE_VIDEO:
+ checked = &dev->data.video->info;
+ break;
+ case VIR_DOMAIN_DEVICE_HOSTDEV:
+ checked = &dev->data.hostdev->info;
+ break;
+ case VIR_DOMAIN_DEVICE_WATCHDOG:
+ checked = &dev->data.watchdog->info;
+ break;
+ case VIR_DOMAIN_DEVICE_CONTROLLER:
+ checked = &dev->data.controller->info;
+ break;
+ case VIR_DOMAIN_DEVICE_GRAPHICS: /* has no address info */
+ return 0;
+ default: /* internal error */
+ virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("Unknown device type"));
+ return -1;
+ }
+ if (checked->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
+ return 0;
+ ret = virDomainDeviceInfoIterate(def, virDomainDeviceAddressMatch, checked);
+ if (ret)
+ virDomainReportError(VIR_ERR_INVALID_ARG,
+ "%s", _("device address conflict"));
+ return ret;
+}
/* Generate a string representation of a device address
* @param address Device address to stringify
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 6b7cfe7..a33c60f 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1215,6 +1215,8 @@ int virDomainDeviceInfoIsSet(virDomainDeviceInfoPtr info);
void virDomainDeviceInfoClear(virDomainDeviceInfoPtr info);
void virDomainDefClearPCIAddresses(virDomainDefPtr def);
void virDomainDefClearDeviceAliases(virDomainDefPtr def);
+int virDomainDefFindDeviceAddressConflict(virDomainDefPtr def,
+ virDomainDeviceDefPtr dev);
typedef int (*virDomainDeviceInfoCallback)(virDomainDefPtr def,
virDomainDeviceInfoPtr dev,
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 5c241aa..9eb0d59 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -222,6 +222,7 @@ virDomainCpuSetParse;
virDomainDefAddImplicitControllers;
virDomainDefClearDeviceAliases;
virDomainDefClearPCIAddresses;
+virDomainDefFindDeviceAddressConflict;
virDomainDefFormat;
virDomainDefFree;
virDomainDefParseFile;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 9c4f290..aada6be 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -3923,6 +3923,9 @@ static int qemuDomainAttachDevicePersistent(virDomainDefPtr vmdef,
{
virDomainDiskDefPtr disk;
+ if (virDomainDefFindDeviceAddressConflict(vmdef, newdev))
+ return -1;
+
switch(newdev->type) {
case VIR_DOMAIN_DEVICE_DISK:
disk = newdev->data.disk;
--
1.7.4.1