From c88b323bf5d5a070c074fda7adc11085f14415ce Mon Sep 17 00:00:00 2001 From: Peter Krempa Date: Wed, 21 Jan 2015 15:41:44 +0100 Subject: [PATCH] conf: Introduce helper to find duplicate device address When adding devices to the definition it's useful to check whether the devices don't reside on a conflicting address. This patch adds a helper that iterates all device info and compares the addresses with the given info. --- src/conf/domain_conf.c | 98 ++++++++++++++++++++++++++++++++++++++++ src/conf/domain_conf.h | 4 ++ src/libvirt_private.syms | 1 + 3 files changed, 103 insertions(+) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 77319dc6e8..e9766e7b38 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -2715,6 +2715,90 @@ virDomainDeviceInfoNeedsFormat(virDomainDeviceInfoPtr info, unsigned int flags) return false; } +static bool +virDomainDeviceInfoAddressIsEqual(const virDomainDeviceInfo *a, + const virDomainDeviceInfo *b) +{ + + if (a->type != b->type) + return false; + + switch ((virDomainDeviceAddressType) a->type) { + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE: + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST: + /* address types below don't have any specific data */ + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_MMIO: + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390: + break; + + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI: + /* the 'multi' field shouldn't be checked */ + if (a->addr.pci.domain != b->addr.pci.domain || + a->addr.pci.bus != b->addr.pci.bus || + a->addr.pci.slot != b->addr.pci.slot || + a->addr.pci.function != b->addr.pci.function) + return false; + break; + + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE: + if (memcmp(&a->addr.drive, &b->addr.drive, sizeof(a->addr.drive))) + return false; + break; + + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL: + if (memcmp(&a->addr.vioserial, &b->addr.vioserial, sizeof(a->addr.vioserial))) + return false; + break; + + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCID: + if (memcmp(&a->addr.ccid, &b->addr.ccid, sizeof(a->addr.ccid))) + return false; + break; + + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB: + if (memcmp(&a->addr.usb, &b->addr.usb, sizeof(a->addr.usb))) + return false; + break; + + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO: + if (memcmp(&a->addr.spaprvio, &b->addr.spaprvio, sizeof(a->addr.spaprvio))) + return false; + break; + + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW: + /* the 'assigned' field denotes that the address was generated */ + if (a->addr.ccw.cssid != b->addr.ccw.cssid || + a->addr.ccw.ssid != b->addr.ccw.ssid || + a->addr.ccw.devno != b->addr.ccw.devno) + return false; + break; + + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_ISA: + if (memcmp(&a->addr.isa, &b->addr.isa, sizeof(a->addr.isa))) + return false; + break; + } + + return true; +} + + +static int +virDomainDefHasDeviceAddressIterator(virDomainDefPtr def ATTRIBUTE_UNUSED, + virDomainDeviceDefPtr dev ATTRIBUTE_UNUSED, + virDomainDeviceInfoPtr info, + void *opaque) +{ + virDomainDeviceInfoPtr needle = opaque; + + /* break iteration if the info was found */ + if (virDomainDeviceInfoAddressIsEqual(info, needle)) + return -1; + + return 0; +} + + int virDomainDeviceInfoCopy(virDomainDeviceInfoPtr dst, virDomainDeviceInfoPtr src) @@ -2967,6 +3051,20 @@ virDomainDeviceInfoIterate(virDomainDefPtr def, } +bool +virDomainDefHasDeviceAddress(virDomainDefPtr def, + virDomainDeviceInfoPtr info) +{ + if (virDomainDeviceInfoIterateInternal(def, + virDomainDefHasDeviceAddressIterator, + true, + info) < 0) + return true; + + return false; +} + + static int virDomainDefRejectDuplicateControllers(virDomainDefPtr def) { diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 93f2314395..f0177c34dc 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2382,6 +2382,10 @@ int virDomainDeviceInfoIterate(virDomainDefPtr def, virDomainDeviceInfoCallback cb, void *opaque); +bool virDomainDefHasDeviceAddress(virDomainDefPtr def, + virDomainDeviceInfoPtr info) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK; + void virDomainDefFree(virDomainDefPtr vm); virDomainChrDefPtr virDomainChrDefNew(void); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 376c69ba52..ece26f07d3 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -198,6 +198,7 @@ virDomainDefFormatInternal; virDomainDefFree; virDomainDefGetDefaultEmulator; virDomainDefGetSecurityLabelDef; +virDomainDefHasDeviceAddress; virDomainDefMaybeAddController; virDomainDefMaybeAddInput; virDomainDefNeedsPlacementAdvice;