All guest devices now use a common device address structure summarized by: enum virDomainDeviceAddressType { VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI, }; enum virDomainDeviceAddressMode { VIR_DOMAIN_DEVICE_ADDRESS_MODE_DYNAMIC, VIR_DOMAIN_DEVICE_ADDRESS_MODE_STATIC, }; struct _virDomainDevicePCIAddress { unsigned int domain; unsigned int bus; unsigned int slot; unsigned int function; }; struct _virDomainDeviceAddress { int type; int mode; union { virDomainDevicePCIAddress pci; } data; }; This replaces the anonymous structs in Disk/Net/Hostdev data structures. Where available, the address is *always* printed in the XML file, instead of being hidden in the internal state file. <address type='pci' mode='static' domain='0x0000' bus='0x1e' slot='0x07' function='0x0'/> A 'static' address is one assigned by the user, never changing, while a 'dynamic' address is one assigned on the fly by QEMU. 'dynamic' addresses are thrown away when a VM stops. The structure definition is based on Wolfgang Mauerer's disk controller patch series. --- src/conf/domain_conf.c | 432 ++++++++++++++++++++++++++++++++++----------- src/conf/domain_conf.h | 90 ++++++----- src/libvirt_private.syms | 5 + src/qemu/qemu_driver.c | 64 ++++--- 4 files changed, 418 insertions(+), 173 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index dca2e49..975b62b 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -88,6 +88,14 @@ VIR_ENUM_IMPL(virDomainDevice, VIR_DOMAIN_DEVICE_LAST, "hostdev", "watchdog") +VIR_ENUM_IMPL(virDomainDeviceAddress, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST, + "none", + "pci") + +VIR_ENUM_IMPL(virDomainDeviceAddressMode, VIR_DOMAIN_DEVICE_ADDRESS_MODE_LAST, + "dynamic", + "static") + VIR_ENUM_IMPL(virDomainDisk, VIR_DOMAIN_DISK_TYPE_LAST, "block", "file", @@ -729,6 +737,245 @@ void virDomainRemoveInactive(virDomainObjListPtr doms, } +int virDomainDeviceAddressIsValid(virDomainDeviceAddressPtr addr, + int type) +{ + if (addr->type != type) + return 0; + + switch (addr->type) { + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI: + return virDomainDevicePCIAddressIsValid(&addr->data.pci); + } + + return 0; +} + + +int virDomainDevicePCIAddressIsValid(virDomainDevicePCIAddressPtr addr) +{ + return addr->domain || addr->bus || addr->slot; +} + + +void virDomainDeviceAddressClear(virDomainDeviceAddressPtr addr) +{ + memset(addr, 0, sizeof(addr)); + addr->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE; +} + + +/* Generate a string representation of a device address + * @param address Device address to stringify + */ +static int virDomainDeviceAddressFormat(virBufferPtr buf, + virDomainDeviceAddressPtr addr, + int flags) +{ + if (!addr) { + virDomainReportError(NULL, VIR_ERR_INTERNAL_ERROR, "%s", + _("missing address information")); + return -1; + } + + if (addr->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) + return 0; + + /* Don't output dynamically allocated addresses when doing inactive XML dump */ + if ((addr->mode == VIR_DOMAIN_DEVICE_ADDRESS_MODE_DYNAMIC) && + (flags & VIR_DOMAIN_XML_INACTIVE)) + return 0; + + /* We'll be in domain/devices/[device type]/ so 3 level indent */ + virBufferVSprintf(buf, " <address type='%s'", + virDomainDeviceAddressTypeToString(addr->type)); + virBufferVSprintf(buf, " mode='%s'", + virDomainDeviceAddressModeTypeToString(addr->mode)); + + switch (addr->type) { + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI: + virBufferVSprintf(buf, " domain='0x%.4x' bus='0x%.2x' slot='0x%.2x' function='0x%.1x'", + addr->data.pci.domain, + addr->data.pci.bus, + addr->data.pci.slot, + addr->data.pci.function); + break; + + default: + virDomainReportError(NULL, VIR_ERR_INTERNAL_ERROR, + _("unknown address type '%d'"), addr->type); + return -1; + } + + virBufferAddLit(buf, "/>\n"); + + return 0; +} + +/* Compare two device addresses. Returns true if addresses are + * identical and false if the they differ (or are of different types) + * @param a, @para b Pointers to the addresses + */ +int virDomainDeviceAddressEqual(virDomainDeviceAddressPtr a, + virDomainDeviceAddressPtr b) +{ + if (!a || !b || a->type != b-> type) { + return 0; + } + + switch (a->type) { + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI: + return virDomainDevicePCIAddressEqual(&a->data.pci, + &b->data.pci); + } + + return 0; +} + + +int virDomainDevicePCIAddressEqual(virDomainDevicePCIAddressPtr a, + virDomainDevicePCIAddressPtr b) +{ + if (a->domain == b->domain && + a->bus == b->bus && + a->slot == b->slot && + a->function == b->function) + return 1; + + return 0; +} + + +static int +virDomainDevicePCIAddressParseXML(virConnectPtr conn, + xmlNodePtr node, + virDomainDevicePCIAddressPtr addr) +{ + char *domain, *slot, *bus, *function; + int ret = -1; + + memset(addr, 0, sizeof(*addr)); + + domain = virXMLPropString(node, "domain"); + bus = virXMLPropString(node, "bus"); + slot = virXMLPropString(node, "slot"); + function = virXMLPropString(node, "function"); + + if (domain && + virStrToLong_ui(domain, NULL, 16, &addr->domain) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot parse <address> 'domain' attribute")); + goto cleanup; + } + + if (bus && + virStrToLong_ui(bus, NULL, 16, &addr->bus) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot parse <address> 'bus' attribute")); + goto cleanup; + } + + if (slot && + virStrToLong_ui(slot, NULL, 16, &addr->slot) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot parse <address> 'slot' attribute")); + goto cleanup; + } + + if (function && + virStrToLong_ui(function, NULL, 16, &addr->function) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot parse <address> 'function' attribute")); + goto cleanup; + } + + if (!virDomainDevicePCIAddressIsValid(addr)) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s", + _("Insufficient specification for PCI address")); + goto cleanup; + } + + ret = 0; + +cleanup: + VIR_FREE(domain); + VIR_FREE(bus); + VIR_FREE(slot); + VIR_FREE(function); + return ret; +} + + +/* Parse the XML definition for a device address + * @param node XML nodeset to parse for device address definition + */ +static int +virDomainDeviceAddressParseXML(virConnectPtr conn, + xmlNodePtr node, + virDomainDeviceAddressPtr addr, + int flags) +{ + char *type = NULL; + char *mode = NULL; + int ret = -1; + + memset(addr, 0, sizeof(*addr)); + + type = virXMLPropString(node, "type"); + mode = virXMLPropString(node, "mode"); + + if (type) { + if ((addr->type = virDomainDeviceAddressTypeFromString(type)) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("unknown address type '%s'"), type); + goto cleanup; + } + } else { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("No type specified for device address")); + goto cleanup; + } + + if (mode) { + if ((addr->mode = virDomainDeviceAddressModeTypeFromString(mode)) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("unknown address mode '%s'"), mode); + goto cleanup; + } + } else { + addr->mode = VIR_DOMAIN_DEVICE_ADDRESS_MODE_DYNAMIC; + } + + /* Dynamic addresses are only valid in the live config */ + if ((flags & VIR_DOMAIN_XML_INACTIVE) && + addr->mode == VIR_DOMAIN_DEVICE_ADDRESS_MODE_DYNAMIC) { + addr->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE; + ret = 0; + goto cleanup; + } + + switch (addr->type) { + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI: + if (virDomainDevicePCIAddressParseXML(conn, node, &addr->data.pci) < 0) + goto cleanup; + break; + + default: + /* Should not happen */ + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("Unknown device address type")); + goto cleanup; + } + + ret = 0; + +cleanup: + VIR_FREE(type); + VIR_FREE(mode); + return ret; +} + + /* Parse the XML definition for a disk * @param node XML nodeset to parse for disk definition */ @@ -747,6 +994,7 @@ virDomainDiskDefParseXML(virConnectPtr conn, char *bus = NULL; char *cachetag = NULL; char *devaddr = NULL; + xmlNodePtr addr = NULL; virStorageEncryptionPtr encryption = NULL; char *serial = NULL; @@ -827,6 +1075,9 @@ virDomainDiskDefParseXML(virConnectPtr conn, } else if ((serial == NULL) && (xmlStrEqual(cur->name, BAD_CAST "serial"))) { serial = (char *)xmlNodeGetContent(cur); + } else if ((addr == NULL) && + (xmlStrEqual(cur->name, BAD_CAST "address"))) { + addr = cur; } } cur = cur->next; @@ -926,15 +1177,20 @@ virDomainDiskDefParseXML(virConnectPtr conn, goto error; } - if (devaddr && - sscanf(devaddr, "%x:%x:%x", - &def->pci_addr.domain, - &def->pci_addr.bus, - &def->pci_addr.slot) < 3) { - virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, - _("Unable to parse devaddr parameter '%s'"), - devaddr); - goto error; + if (devaddr) { + if (sscanf(devaddr, "%x:%x:%x", + &def->addr.data.pci.domain, + &def->addr.data.pci.bus, + &def->addr.data.pci.slot) < 3) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("Unable to parse devaddr parameter '%s'"), + devaddr); + goto error; + } + def->addr.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; + } else if (addr) { + if (virDomainDeviceAddressParseXML(conn, addr, &def->addr, flags) < 0) + goto error; } def->src = source; @@ -1083,6 +1339,7 @@ virDomainNetDefParseXML(virConnectPtr conn, char *hostnet_name = NULL; char *devaddr = NULL; char *vlan = NULL; + xmlNodePtr addr = NULL; if (VIR_ALLOC(def) < 0) { virReportOOMError(conn); @@ -1155,6 +1412,9 @@ virDomainNetDefParseXML(virConnectPtr conn, hostnet_name = virXMLPropString(cur, "hostnet"); devaddr = virXMLPropString(cur, "devaddr"); vlan = virXMLPropString(cur, "vlan"); + } else if ((addr == NULL) && + (xmlStrEqual(cur->name, BAD_CAST "address"))) { + addr = cur; } } cur = cur->next; @@ -1171,14 +1431,28 @@ virDomainNetDefParseXML(virConnectPtr conn, virCapabilitiesGenerateMac(caps, def->mac); } - if (devaddr && - sscanf(devaddr, "%x:%x:%x", - &def->pci_addr.domain, - &def->pci_addr.bus, - &def->pci_addr.slot) < 3) { - virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, - _("Unable to parse devaddr parameter '%s'"), - devaddr); + if (devaddr) { + if (sscanf(devaddr, "%x:%x:%x", + &def->addr.data.pci.domain, + &def->addr.data.pci.bus, + &def->addr.data.pci.slot) < 3) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("Unable to parse devaddr parameter '%s'"), + devaddr); + goto error; + } + def->addr.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; + } else if (addr) { + if (virDomainDeviceAddressParseXML(conn, addr, &def->addr, flags) < 0) + goto error; + } + + /* XXX what about ISA/USB based NIC models - once we support + * them we should make sure address type is correct */ + if (def->addr.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE && + def->addr.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s", + _("Network interfaces must use 'pci' address type")); goto error; } @@ -2319,83 +2593,26 @@ virDomainHostdevSubsysPciDefParseXML(virConnectPtr conn, while (cur != NULL) { if (cur->type == XML_ELEMENT_NODE) { if (xmlStrEqual(cur->name, BAD_CAST "address")) { + virDomainDevicePCIAddressPtr addr = + &def->source.subsys.u.pci; - char *domain = virXMLPropString(cur, "domain"); - if (domain) { - if (virStrToLong_ui(domain, NULL, 0, - &def->source.subsys.u.pci.domain) < 0) { - virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, - _("cannot parse domain %s"), - domain); - VIR_FREE(domain); - goto out; - } - VIR_FREE(domain); - } - - char *bus = virXMLPropString(cur, "bus"); - if (bus) { - if (virStrToLong_ui(bus, NULL, 0, - &def->source.subsys.u.pci.bus) < 0) { - virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, - _("cannot parse bus %s"), bus); - VIR_FREE(bus); - goto out; - } - VIR_FREE(bus); - } else { - virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, - "%s", _("pci address needs bus id")); - goto out; - } - - char *slot = virXMLPropString(cur, "slot"); - if (slot) { - if (virStrToLong_ui(slot, NULL, 0, - &def->source.subsys.u.pci.slot) < 0) { - virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, - _("cannot parse slot %s"), - slot); - VIR_FREE(slot); - goto out; - } - VIR_FREE(slot); - } else { - virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, - "%s", _("pci address needs slot id")); - goto out; - } - - char *function = virXMLPropString(cur, "function"); - if (function) { - if (virStrToLong_ui(function, NULL, 0, - &def->source.subsys.u.pci.function) < 0) { - virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, - _("cannot parse function %s"), - function); - VIR_FREE(function); - goto out; - } - VIR_FREE(function); - } else { - virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s", - _("pci address needs function id")); + if (virDomainDevicePCIAddressParseXML(conn, cur, addr) < 0) goto out; - } } else if ((flags & VIR_DOMAIN_XML_INTERNAL_STATUS) && xmlStrEqual(cur->name, BAD_CAST "state")) { char *devaddr = virXMLPropString(cur, "devaddr"); if (devaddr && sscanf(devaddr, "%x:%x:%x", - &def->source.subsys.u.pci.guest_addr.domain, - &def->source.subsys.u.pci.guest_addr.bus, - &def->source.subsys.u.pci.guest_addr.slot) < 3) { + &def->addr.data.pci.domain, + &def->addr.data.pci.bus, + &def->addr.data.pci.slot) < 3) { virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, _("Unable to parse devaddr parameter '%s'"), devaddr); VIR_FREE(devaddr); goto out; } + def->addr.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; } else { virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, _("unknown pci source type '%s'"), @@ -2473,6 +2690,9 @@ virDomainHostdevDefParseXML(virConnectPtr conn, if (virDomainHostdevSubsysPciDefParseXML(conn, cur, def, flags) < 0) goto error; } + } else if (xmlStrEqual(cur->name, BAD_CAST "address")) { + if (virDomainDeviceAddressParseXML(conn, cur, &def->addr, flags) < 0) + goto error; } else { virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, _("unknown node %s"), cur->name); @@ -2481,6 +2701,18 @@ virDomainHostdevDefParseXML(virConnectPtr conn, cur = cur->next; } + if (def->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) { + switch (def->source.subsys.type) { + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: + if (def->addr.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s", + _("PCI host devices must use 'pci' address type")); + goto error; + } + break; + } + } + cleanup: VIR_FREE(type); VIR_FREE(mode); @@ -3934,15 +4166,9 @@ virDomainDiskDefFormat(virConnectPtr conn, virStorageEncryptionFormat(conn, buf, def->encryption) < 0) return -1; - if (flags & VIR_DOMAIN_XML_INTERNAL_STATUS) { - virBufferAddLit(buf, " <state"); - if (virDiskHasValidPciAddr(def)) - virBufferVSprintf(buf, " devaddr='%.4x:%.2x:%.2x'", - def->pci_addr.domain, - def->pci_addr.bus, - def->pci_addr.slot); - virBufferAddLit(buf, "/>\n"); - } + if (def->addr.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE && + virDomainDeviceAddressFormat(buf, &def->addr, flags) < 0) + return -1; virBufferAddLit(buf, " </disk>\n"); @@ -4081,16 +4307,15 @@ virDomainNetDefFormat(virConnectPtr conn, virBufferEscapeString(buf, " nic='%s'", def->nic_name); if (def->hostnet_name) virBufferEscapeString(buf, " hostnet='%s'", def->hostnet_name); - if (virNetHasValidPciAddr(def)) - virBufferVSprintf(buf, " devaddr='%.4x:%.2x:%.2x'", - def->pci_addr.domain, - def->pci_addr.bus, - def->pci_addr.slot); if (def->vlan > 0) virBufferVSprintf(buf, " vlan='%d'", def->vlan); virBufferAddLit(buf, "/>\n"); } + if (def->addr.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE && + virDomainDeviceAddressFormat(buf, &def->addr, flags) < 0) + return -1; + virBufferAddLit(buf, " </interface>\n"); return 0; @@ -4499,25 +4724,20 @@ virDomainHostdevDefFormat(virConnectPtr conn, def->source.subsys.u.usb.bus, def->source.subsys.u.usb.device); } - } - if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) { + } else if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) { virBufferVSprintf(buf, " <address domain='0x%.4x' bus='0x%.2x' slot='0x%.2x' function='0x%.1x'/>\n", def->source.subsys.u.pci.domain, def->source.subsys.u.pci.bus, def->source.subsys.u.pci.slot, def->source.subsys.u.pci.function); - if (flags & VIR_DOMAIN_XML_INTERNAL_STATUS) { - virBufferAddLit(buf, " <state"); - if (virHostdevHasValidGuestAddr(def)) - virBufferVSprintf(buf, " devaddr='%.4x:%.2x:%.2x'", - def->source.subsys.u.pci.guest_addr.domain, - def->source.subsys.u.pci.guest_addr.bus, - def->source.subsys.u.pci.guest_addr.slot); - virBufferAddLit(buf, "/>\n"); - } } virBufferAddLit(buf, " </source>\n"); + + if (def->addr.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE && + virDomainDeviceAddressFormat(buf, &def->addr, flags) < 0) + return -1; + virBufferAddLit(buf, " </hostdev>\n"); return 0; diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index ac39dcd..31a2f9d 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -63,6 +63,40 @@ enum virDomainVirtType { VIR_DOMAIN_VIRT_LAST, }; +enum virDomainDeviceAddressType { + VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE, + VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI, + + VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST +}; + +enum virDomainDeviceAddressMode { + VIR_DOMAIN_DEVICE_ADDRESS_MODE_DYNAMIC, + VIR_DOMAIN_DEVICE_ADDRESS_MODE_STATIC, + + VIR_DOMAIN_DEVICE_ADDRESS_MODE_LAST +}; + +typedef struct _virDomainDevicePCIAddress virDomainDevicePCIAddress; +typedef virDomainDevicePCIAddress *virDomainDevicePCIAddressPtr; +struct _virDomainDevicePCIAddress { + unsigned int domain; + unsigned int bus; + unsigned int slot; + unsigned int function; +}; + +typedef struct _virDomainDeviceAddress virDomainDeviceAddress; +typedef virDomainDeviceAddress *virDomainDeviceAddressPtr; +struct _virDomainDeviceAddress { + int type; + int mode; + union { + virDomainDevicePCIAddress pci; + } data; +}; + + /* Two types of disk backends */ enum virDomainDiskType { VIR_DOMAIN_DISK_TYPE_BLOCK, @@ -118,20 +152,10 @@ struct _virDomainDiskDef { int cachemode; unsigned int readonly : 1; unsigned int shared : 1; - struct { - unsigned domain; - unsigned bus; - unsigned slot; - } pci_addr; + virDomainDeviceAddress addr; virStorageEncryptionPtr encryption; }; -static inline int -virDiskHasValidPciAddr(virDomainDiskDefPtr def) -{ - return def->pci_addr.domain || def->pci_addr.bus || def->pci_addr.slot; -} - /* Two types of disk backends */ enum virDomainFSType { @@ -200,20 +224,10 @@ struct _virDomainNetDef { char *ifname; char *nic_name; char *hostnet_name; - struct { - unsigned domain; - unsigned bus; - unsigned slot; - } pci_addr; + virDomainDeviceAddress addr; int vlan; }; -static inline int -virNetHasValidPciAddr(virDomainNetDefPtr def) -{ - return def->pci_addr.domain || def->pci_addr.bus || def->pci_addr.slot; -} - enum virDomainChrTargetType { VIR_DOMAIN_CHR_TARGET_TYPE_NULL = 0, VIR_DOMAIN_CHR_TARGET_TYPE_MONITOR, @@ -441,17 +455,7 @@ struct _virDomainHostdevDef { unsigned vendor; unsigned product; } usb; - struct { - unsigned domain; - unsigned bus; - unsigned slot; - unsigned function; - struct { - unsigned domain; - unsigned bus; - unsigned slot; - } guest_addr; - } pci; + virDomainDevicePCIAddress pci; /* host address */ } u; } subsys; struct { @@ -462,16 +466,9 @@ struct _virDomainHostdevDef { } caps; } source; char* target; + virDomainDeviceAddress addr; /* Guest address */ }; -static inline int -virHostdevHasValidGuestAddr(virDomainHostdevDefPtr def) -{ - return def->source.subsys.u.pci.guest_addr.domain || - def->source.subsys.u.pci.guest_addr.bus || - def->source.subsys.u.pci.guest_addr.slot; -} - /* Flags for the 'type' field in next struct */ enum virDomainDeviceType { VIR_DOMAIN_DEVICE_DISK, @@ -671,6 +668,7 @@ virDomainObjIsActive(virDomainObjPtr dom) return dom->def->id != -1; } + int virDomainObjListInit(virDomainObjListPtr objs); void virDomainObjListDeinit(virDomainObjListPtr objs); @@ -693,6 +691,14 @@ void virDomainWatchdogDefFree(virDomainWatchdogDefPtr def); void virDomainVideoDefFree(virDomainVideoDefPtr def); void virDomainHostdevDefFree(virDomainHostdevDefPtr def); void virDomainDeviceDefFree(virDomainDeviceDefPtr def); +int virDomainDeviceAddressEqual(virDomainDeviceAddressPtr a, + virDomainDeviceAddressPtr b); +int virDomainDevicePCIAddressEqual(virDomainDevicePCIAddressPtr a, + virDomainDevicePCIAddressPtr b); +int virDomainDeviceAddressIsValid(virDomainDeviceAddressPtr addr, + int type); +int virDomainDevicePCIAddressIsValid(virDomainDevicePCIAddressPtr addr); +void virDomainDeviceAddressClear(virDomainDeviceAddressPtr addr); void virDomainDefFree(virDomainDefPtr vm); void virDomainObjRef(virDomainObjPtr vm); /* Returns 1 if the object was freed, 0 if more refs exist */ @@ -830,6 +836,8 @@ VIR_ENUM_DECL(virDomainBoot) VIR_ENUM_DECL(virDomainFeature) VIR_ENUM_DECL(virDomainLifecycle) VIR_ENUM_DECL(virDomainDevice) +VIR_ENUM_DECL(virDomainDeviceAddress) +VIR_ENUM_DECL(virDomainDeviceAddressMode) VIR_ENUM_DECL(virDomainDisk) VIR_ENUM_DECL(virDomainDiskDevice) VIR_ENUM_DECL(virDomainDiskBus) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 72257d7..963206b 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -154,6 +154,11 @@ virDomainObjListInit; virDomainObjListDeinit; virDomainObjRef; virDomainObjUnref; +virDomainDeviceAddressEqual; +virDomainDevicePCIAddressEqual; +virDomainDeviceAddressIsValid; +virDomainDevicePCIAddressIsValid; +virDomainDeviceAddressClear; # domain_event.h diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 7e60d0e..5920ab3 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -4947,13 +4947,15 @@ static int qemudDomainAttachPciDiskDevice(virConnectPtr conn, ret = qemuMonitorAddPCIDisk(priv->mon, dev->data.disk->src, type, - &dev->data.disk->pci_addr.domain, - &dev->data.disk->pci_addr.bus, - &dev->data.disk->pci_addr.slot); + &dev->data.disk->addr.data.pci.domain, + &dev->data.disk->addr.data.pci.bus, + &dev->data.disk->addr.data.pci.slot); qemuDomainObjExitMonitorWithDriver(driver, vm); - if (ret == 0) + if (ret == 0) { + dev->data.disk->addr.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; virDomainDiskInsertPreAlloced(vm->def, dev->data.disk); + } return ret; } @@ -5076,12 +5078,13 @@ static int qemudDomainAttachNetDevice(virConnectPtr conn, qemuDomainObjEnterMonitorWithDriver(driver, vm); if (qemuMonitorAddPCINetwork(priv->mon, nicstr, - &net->pci_addr.domain, - &net->pci_addr.bus, - &net->pci_addr.slot) < 0) { + &net->addr.data.pci.domain, + &net->addr.data.pci.bus, + &net->addr.data.pci.slot) < 0) { qemuDomainObjExitMonitorWithDriver(driver, vm); goto try_remove; } + net->addr.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; qemuDomainObjExitMonitorWithDriver(driver, vm); ret = 0; @@ -5164,12 +5167,13 @@ static int qemudDomainAttachHostPciDevice(virConnectPtr conn, hostdev->source.subsys.u.pci.bus, hostdev->source.subsys.u.pci.slot, hostdev->source.subsys.u.pci.function, - &hostdev->source.subsys.u.pci.guest_addr.domain, - &hostdev->source.subsys.u.pci.guest_addr.bus, - &hostdev->source.subsys.u.pci.guest_addr.slot); + &hostdev->addr.data.pci.domain, + &hostdev->addr.data.pci.bus, + &hostdev->addr.data.pci.slot); qemuDomainObjExitMonitorWithDriver(driver, vm); if (ret < 0) goto error; + hostdev->addr.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; vm->def->hostdevs[vm->def->nhostdevs++] = hostdev; @@ -5399,18 +5403,18 @@ static int qemudDomainDetachPciDiskDevice(virConnectPtr conn, goto cleanup; } - if (!virDiskHasValidPciAddr(detach)) { - qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, - _("disk %s cannot be detached - no PCI address for device"), - detach->dst); + if (!virDomainDeviceAddressIsValid(&detach->addr, + VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)) { + qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, "%s", + _("device cannot be detached without a PCI address")); goto cleanup; } qemuDomainObjEnterMonitorWithDriver(driver, vm); if (qemuMonitorRemovePCIDevice(priv->mon, - detach->pci_addr.domain, - detach->pci_addr.bus, - detach->pci_addr.slot) < 0) { + detach->addr.data.pci.domain, + detach->addr.data.pci.bus, + detach->addr.data.pci.slot) < 0) { qemuDomainObjExitMonitor(vm); goto cleanup; } @@ -5465,7 +5469,14 @@ qemudDomainDetachNetDevice(virConnectPtr conn, goto cleanup; } - if (!virNetHasValidPciAddr(detach) || detach->vlan < 0 || !detach->hostnet_name) { + if (!virDomainDeviceAddressIsValid(&detach->addr, + VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)) { + qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, + "%s", _("device cannot be detached without a PCI address")); + goto cleanup; + } + + if (detach->vlan < 0 || !detach->hostnet_name) { qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("network device cannot be detached - device state missing")); goto cleanup; @@ -5473,9 +5484,9 @@ qemudDomainDetachNetDevice(virConnectPtr conn, qemuDomainObjEnterMonitorWithDriver(driver, vm); if (qemuMonitorRemovePCIDevice(priv->mon, - detach->pci_addr.domain, - detach->pci_addr.bus, - detach->pci_addr.slot) < 0) { + detach->addr.data.pci.domain, + detach->addr.data.pci.bus, + detach->addr.data.pci.slot) < 0) { qemuDomainObjExitMonitorWithDriver(driver, vm); goto cleanup; } @@ -5553,17 +5564,18 @@ static int qemudDomainDetachHostPciDevice(virConnectPtr conn, return -1; } - if (!virHostdevHasValidGuestAddr(detach)) { + if (!virDomainDeviceAddressIsValid(&detach->addr, + VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)) { qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, - "%s", _("hostdev cannot be detached - device state missing")); + "%s", _("device cannot be detached without a PCI address")); return -1; } qemuDomainObjEnterMonitorWithDriver(driver, vm); if (qemuMonitorRemovePCIDevice(priv->mon, - detach->source.subsys.u.pci.guest_addr.domain, - detach->source.subsys.u.pci.guest_addr.bus, - detach->source.subsys.u.pci.guest_addr.slot) < 0) { + detach->addr.data.pci.domain, + detach->addr.data.pci.bus, + detach->addr.data.pci.slot) < 0) { qemuDomainObjExitMonitorWithDriver(driver, vm); return -1; } -- 1.6.5.2 -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list