On 01/05/2015 02:29 AM, Wang Rui wrote:
We can update device and attach device(cdrom) with the boot order
unchanged.
But the boot order check method will report an error:
"boot order %d is already used by another device"
In fact the boot order is used by itself, we just want to keep it as before.
This patch improves boot order check to distinguish the owner.
Signed-off-by: Wang Rui <moon.wangrui(a)huawei.com>
Signed-off-by: Zhou Yimin <zhouyimin(a)huawei.com>
---
src/conf/device_conf.c | 13 +++++++++++++
src/conf/device_conf.h | 12 ++++++++++++
src/conf/domain_conf.c | 31 +++++++++++++++++++++++++++----
src/conf/domain_conf.h | 9 ---------
4 files changed, 52 insertions(+), 13 deletions(-)
Probably could have split this in two in order to do code motion fi...
3a. -> Move virDomainDeviceDriveAddress from domain_conf.h to
device_conf.h which just seems to be separate from the... op
3b. -> Rest of this patch and you will also need to modify
src/libvirt_private.syms in order to add virDeviceDriveAddressEqual;
"properly" since it's global.
I also think that there's some synergies with patch 6/8 especially with
the matching logic
Perhaps an update to the "boot order" text in the <hostdev> section of
formatdomain.html.in would be beneficial to describe these additional
checks.
diff --git a/src/conf/device_conf.c b/src/conf/device_conf.c
index 5ffe159..907a7b8 100644
--- a/src/conf/device_conf.c
+++ b/src/conf/device_conf.c
@@ -144,6 +144,19 @@ virDevicePCIAddressEqual(virDevicePCIAddress *addr1,
return false;
}
+bool
+virDeviceDriveAddressEqual(virDomainDeviceDriveAddressPtr addr1,
+ virDomainDeviceDriveAddressPtr addr2)
+{
+ if (addr1->controller == addr2->controller &&
+ addr1->bus == addr2->bus &&
+ addr1->target == addr2->target &&
+ addr1->unit == addr2->unit) {
+ return true;
+ }
+ return false;
+}
+
int
virInterfaceLinkParseXML(xmlNodePtr node,
virInterfaceLinkPtr lnk)
diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h
index f067a35..afcf0ee 100644
--- a/src/conf/device_conf.h
+++ b/src/conf/device_conf.h
@@ -55,6 +55,15 @@ struct _virDevicePCIAddress {
int multi; /* enum virDomainDeviceAddressPCIMulti */
};
+typedef struct _virDomainDeviceDriveAddress virDomainDeviceDriveAddress;
+typedef virDomainDeviceDriveAddress *virDomainDeviceDriveAddressPtr;
+struct _virDomainDeviceDriveAddress {
+ unsigned int controller;
+ unsigned int bus;
+ unsigned int target;
+ unsigned int unit;
+};
+
typedef struct _virInterfaceLink virInterfaceLink;
typedef virInterfaceLink *virInterfaceLinkPtr;
struct _virInterfaceLink {
@@ -74,6 +83,9 @@ int virDevicePCIAddressFormat(virBufferPtr buf,
bool virDevicePCIAddressEqual(virDevicePCIAddress *addr1,
virDevicePCIAddress *addr2);
+bool virDeviceDriveAddressEqual(virDomainDeviceDriveAddressPtr addr1,
+ virDomainDeviceDriveAddressPtr addr2);
+
int virInterfaceLinkParseXML(xmlNodePtr node,
virInterfaceLinkPtr lnk);
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index aafc05e..d2c4a0a 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -19953,12 +19953,35 @@ virDomainDeviceInfoCheckBootIndex(virDomainDefPtr def
ATTRIBUTE_UNUSED,
virDomainDeviceInfoPtr newinfo = opaque;
if (info->bootIndex == newinfo->bootIndex) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- _("boot order %d is already used by another device"),
- newinfo->bootIndex);
- return -1;
+ /* check if the same boot order is used by another device or itself */
+ if (info->type != newinfo->type) {
+ goto error;
+ } else {
+ switch ((virDomainDeviceAddressType) newinfo->type) {
+ case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI:
+ if (virDevicePCIAddressEqual(&info->addr.pci,
+ &newinfo->addr.pci))
+ return 0;
+ else
+ goto error;
+ case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE:
+ if (virDeviceDriveAddressEqual(&info->addr.drive,
+ &newinfo->addr.drive))
+ return 0;
+ else
+ goto error;
+ default:
+ goto error;
This is difficult to read with all the if-then-else and goto's.
How about the following:
if (info->bootIndex == newinfo->bootIndex) {
/* check if the same boot order is used by another device or
itself */
if (info->type != newinfo->type)
goto error;
if ((newinfo->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI &&
virDevicePCIAddressEqual(&info->addr.pci,
&newinfo->addr.pci)) ||
(newinfo->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE &&
virDeviceDriveAddressEqual(&info->addr.drive,
&newinfo->addr.drive)))
return 0;
goto error;
}
return 0;
error:
...
Even with this change - I'm concerned about the cases where 'type'
doesn't match and is not PCI or DRIVE (e.g., the two new error paths).
Trying to wrap my mind about the timing of the check and when the 'type'
and address value are filled in w/r/t if they're not present in the XML
when the guest starts, but I think this is only called in an attach,
update, or detach path so it should be ok... Although I see
virDomainDefCompatibleDevice is called in an LXC path, so while I assume
you've made sure the qemu path works right, what about the lxc path as
it relates to the device info type/address checks?
Since patch 6 changes the Iterate from just 'attach' to 'attach' or
'update', it seems you're trying to "cover" the update case, but
may
have caused unforeseen issues with the attach case.
I think my 3b and 6 should be combined to make it easier to consider the
options.
In particular, it seems new restrictions are in place that bootIndex can
only work for PCI and DRIVE virDomainDeviceInfo address types. I think
the USB type is throwing me off a bit.
Just trying to make sure some already existing option isn't being
disallowed with the new changes. Adding in specific device address
checks based on types just raises that concern.
John
+ }
+ }
}
return 0;
+
+ error:
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("boot order %d is already used by another device"),
+ newinfo->bootIndex);
+ return -1;
}
int
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 57297cd..3bddc80 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -236,15 +236,6 @@ typedef enum {
VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST
} virDomainDeviceAddressType;
-typedef struct _virDomainDeviceDriveAddress virDomainDeviceDriveAddress;
-typedef virDomainDeviceDriveAddress *virDomainDeviceDriveAddressPtr;
-struct _virDomainDeviceDriveAddress {
- unsigned int controller;
- unsigned int bus;
- unsigned int target;
- unsigned int unit;
-};
-
typedef struct _virDomainDeviceVirtioSerialAddress virDomainDeviceVirtioSerialAddress;
typedef virDomainDeviceVirtioSerialAddress *virDomainDeviceVirtioSerialAddressPtr;
struct _virDomainDeviceVirtioSerialAddress {