From a87f4804dcea2ede3a20bb3d647e291c4bd9a579 Mon Sep 17 00:00:00 2001
From: KAMEZAWA Hiroyuki <kamezawa.hiroyu(a)jp.fujitsu.com>
Date: Fri, 1 Apr 2011 11:59:32 +0900
Subject: [PATCH 4/4] libvirt/qemu - check address conflict at attach.
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.
[Before Patch]
error: Failed to attach device from /home/kamezawa/testc.xml
error: An error occurred, but the cause is unknown
[After Patch]
error: Failed to attach device from /home/kamezawa/testc.xml
error: invalid argument in device address conflict
This error report is better. And this aslo checks devices other
and PCI devides, which wasn't done.
Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu(a)jp.fujitsu.com>
Changelog v7->v8
- fixed error messages.
- use STREQ.
---
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 8948ab0..032ad1e 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 fc46700..1124e73 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 e8c5dce..d539011 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 eeaea0c..4d4b7e6 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -3886,6 +3886,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