From: Wolfgang Mauerer <wolfgang.mauerer@xxxxxxxxxxx> This augments virDomainDevice with a <controller> element that is used to represent disk controllers (e.g., scsi controllers). The XML format is given by <controller type="scsi" index="<num>"> <address type="pci" domain="0xNUM" bus="0xNUM" slot="0xNUM"/> </controller> where type denotes the disk interface (scsi, ide,...), index is an integer that identifies the controller for association with disks, and the <address> element specifies the controller address on the PCI bus as described in previous commits The address element can be omitted; in this case, an address will be assigned automatically. Most of the code in this patch is from Wolfgang Mauerer's previous disk controller series --- src/conf/domain_conf.c | 207 +++++++++++++++++++++++++++++++++++++++++++++- src/conf/domain_conf.h | 30 +++++++ src/libvirt_private.syms | 2 + 3 files changed, 238 insertions(+), 1 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 533a1b0..95a9d52 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -86,7 +86,8 @@ VIR_ENUM_IMPL(virDomainDevice, VIR_DOMAIN_DEVICE_LAST, "sound", "video", "hostdev", - "watchdog") + "watchdog", + "controller") VIR_ENUM_IMPL(virDomainDeviceAddress, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST, "none", @@ -124,6 +125,12 @@ VIR_ENUM_IMPL(virDomainDiskCache, VIR_DOMAIN_DISK_CACHE_LAST, "writethrough", "writeback") +VIR_ENUM_IMPL(virDomainController, VIR_DOMAIN_CONTROLLER_TYPE_LAST, + "ide", + "fdc", + "scsi", + "sata") + VIR_ENUM_IMPL(virDomainFS, VIR_DOMAIN_FS_TYPE_LAST, "mount", "block", @@ -371,6 +378,14 @@ void virDomainDiskDefFree(virDomainDiskDefPtr def) VIR_FREE(def); } +void virDomainControllerDefFree(virDomainControllerDefPtr def) +{ + if (!def) + return; + + VIR_FREE(def); +} + void virDomainFSDefFree(virDomainFSDefPtr def) { if (!def) @@ -523,6 +538,9 @@ void virDomainDeviceDefFree(virDomainDeviceDefPtr def) case VIR_DOMAIN_DEVICE_WATCHDOG: virDomainWatchdogDefFree(def->data.watchdog); break; + case VIR_DOMAIN_DEVICE_CONTROLLER: + virDomainControllerDefFree(def->data.controller); + break; } VIR_FREE(def); @@ -556,6 +574,10 @@ void virDomainDefFree(virDomainDefPtr def) virDomainDiskDefFree(def->disks[i]); VIR_FREE(def->disks); + for (i = 0 ; i < def->ncontrollers ; i++) + virDomainControllerDefFree(def->controllers[i]); + VIR_FREE(def->controllers); + for (i = 0 ; i < def->nfss ; i++) virDomainFSDefFree(def->fss[i]); VIR_FREE(def->fss); @@ -1390,6 +1412,76 @@ cleanup: } +/* Parse the XML definition for a controller + * @param node XML nodeset to parse for controller definition + */ +static virDomainControllerDefPtr +virDomainControllerDefParseXML(virConnectPtr conn, + xmlNodePtr node, + int flags) { + virDomainControllerDefPtr def; + xmlNodePtr cur; + char *type = NULL; + char *idx = NULL; + xmlNodePtr addr = NULL; + + if (VIR_ALLOC(def) < 0) { + virReportOOMError(conn); + return NULL; + } + + type = virXMLPropString(node, "type"); + if (type) { + if ((def->type = virDomainDiskBusTypeFromString(type)) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("unknown disk controller type '%s'"), type); + goto error; + } + } + + idx = virXMLPropString(node, "index"); + if (idx) { + if (virStrToLong_i(idx, NULL, 10, &def->idx) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("cannot parse disk controller index %s"), idx); + goto error; + } + } + + cur = node->children; + while (cur != NULL) { + if (cur->type == XML_ELEMENT_NODE && + addr == NULL) { + addr = cur; + } + + cur = cur->next; + } + + if (addr) { + if (virDomainDeviceAddressParseXML(conn, addr, &def->addr,flags) < 0) + goto error; + } + + 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", + _("Disk controllers must use the 'pci' address type")); + goto error; + } + +cleanup: + VIR_FREE(type); + VIR_FREE(idx); + + return def; + + error: + virDomainControllerDefFree(def); + def = NULL; + goto cleanup; +} + /* Parse the XML definition for a disk * @param node XML nodeset to parse for disk definition */ @@ -3092,6 +3184,10 @@ virDomainDeviceDefPtr virDomainDeviceDefParse(virConnectPtr conn, dev->type = VIR_DOMAIN_DEVICE_HOSTDEV; if (!(dev->data.hostdev = virDomainHostdevDefParseXML(conn, node, flags))) goto error; + } else if (xmlStrEqual(node->name, BAD_CAST "controller")) { + dev->type = VIR_DOMAIN_DEVICE_CONTROLLER; + if (!(dev->data.controller = virDomainControllerDefParseXML(conn, node, flags))) + goto error; } else { virDomainReportError(conn, VIR_ERR_XML_ERROR, "%s", _("unknown device type")); @@ -3164,6 +3260,59 @@ void virDomainDiskInsertPreAlloced(virDomainDefPtr def, } +int virDomainControllerInsert(virDomainDefPtr def, + virDomainControllerDefPtr controller) +{ + + if (VIR_REALLOC_N(def->controllers, def->ncontrollers+1) < 0) + return -1; + + virDomainControllerInsertPreAlloced(def, controller); + + return 0; +} + +void virDomainControllerInsertPreAlloced(virDomainDefPtr def, + virDomainControllerDefPtr controller) +{ + int i; + /* Tenatively plan to insert controller at the end. */ + int insertAt = -1; + + /* Then work backwards looking for controllers of + * the same type. If we find a controller with a + * index greater than the new one, insert at + * that position + */ + for (i = (def->ncontrollers - 1) ; i >= 0 ; i--) { + /* If bus matches and current controller is after + * new controller, then new controller should go here */ + if ((def->controllers[i]->type == controller->type) && + (def->controllers[i]->idx > controller->idx)) { + insertAt = i; + } else if (def->controllers[i]->type == controller->type && + insertAt == -1) { + /* Last controller with match bus is before the + * new controller, then put new controller just after + */ + insertAt = i + 1; + } + } + + /* No controllers with this bus yet, so put at end of list */ + if (insertAt == -1) + insertAt = def->ncontrollers; + + if (insertAt < def->ncontrollers) + memmove(def->controllers + insertAt + 1, + def->controllers + insertAt, + (sizeof(def->controllers[0]) * (def->ncontrollers-insertAt))); + + def->controllers[insertAt] = controller; + def->ncontrollers++; +} + + #ifndef PROXY static char *virDomainDefDefaultEmulator(virConnectPtr conn, virDomainDefPtr def, @@ -3479,6 +3628,25 @@ static virDomainDefPtr virDomainDefParseXML(virConnectPtr conn, } VIR_FREE(nodes); + /* analysis of the controller devices */ + if ((n = virXPathNodeSet(conn, "./devices/controller", ctxt, &nodes)) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("cannot extract controller devices")); + goto error; + } + if (n && VIR_ALLOC_N(def->controllers, n) < 0) + goto no_memory; + for (i = 0 ; i < n ; i++) { + virDomainControllerDefPtr controller = virDomainControllerDefParseXML(conn, + nodes[i], + flags); + if (!controller) + goto error; + + def->controllers[def->ncontrollers++] = controller; + } + VIR_FREE(nodes); + /* analysis of the filesystems */ if ((n = virXPathNodeSet(conn, "./devices/filesystem", ctxt, &nodes)) < 0) { virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, @@ -4387,6 +4555,36 @@ virDomainDiskDefFormat(virConnectPtr conn, } static int +virDomainControllerDefFormat(virConnectPtr conn, + virBufferPtr buf, + virDomainControllerDefPtr def, + int flags) +{ + const char *type = virDomainControllerTypeToString(def->type); + + if (!type) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("unexpected controller type %d"), def->type); + return -1; + } + + virBufferVSprintf(buf, + " <controller type='%s' index='%d'", + type, def->idx); + + if (def->addr.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) { + virBufferAddLit(buf, ">\n"); + if (virDomainDeviceAddressFormat(buf, &def->addr, flags) < 0) + return -1; + virBufferAddLit(buf, " </controller>\n"); + } else { + virBufferAddLit(buf, "/>\n"); + } + + return 0; +} + +static int virDomainFSDefFormat(virConnectPtr conn, virBufferPtr buf, virDomainFSDefPtr def) @@ -5138,6 +5336,10 @@ char *virDomainDefFormat(virConnectPtr conn, if (virDomainDiskDefFormat(conn, &buf, def->disks[n], flags) < 0) goto cleanup; + for (n = 0 ; n < def->ncontrollers ; n++) + if (virDomainControllerDefFormat(conn, &buf, def->controllers[n], flags) < 0) + goto cleanup; + for (n = 0 ; n < def->nfss ; n++) if (virDomainFSDefFormat(conn, &buf, def->fss[n]) < 0) goto cleanup; @@ -5316,6 +5518,9 @@ void virDomainDefClearDynamicValues(virDomainDefPtr def) for (i = 0 ; i < def->nnets ; i++) { virDomainDeviceAddressClearDynamicValues(&def->nets[i]->addr); } + for (i = 0 ; i < def->ncontrollers ; i++) { + virDomainDeviceAddressClearDynamicValues(&def->controllers[i]->addr); + } if (def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC) { VIR_FREE(def->seclabel.label); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index c93aed6..413647b 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -176,6 +176,25 @@ struct _virDomainDiskDef { }; +enum virDomainControllerType { + VIR_DOMAIN_CONTROLLER_TYPE_IDE, + VIR_DOMAIN_CONTROLLER_TYPE_FDC, + VIR_DOMAIN_CONTROLLER_TYPE_SCSI, + VIR_DOMAIN_CONTROLLER_TYPE_SATA, + + VIR_DOMAIN_CONTROLLER_TYPE_LAST +}; + +/* Stores the virtual disk controller configuration */ +typedef struct _virDomainControllerDef virDomainControllerDef; +typedef virDomainControllerDef *virDomainControllerDefPtr; +struct _virDomainControllerDef { + int type; + int idx; + virDomainDeviceAddress addr; +}; + + /* Two types of disk backends */ enum virDomainFSType { VIR_DOMAIN_FS_TYPE_MOUNT, /* Better named 'bind' */ @@ -500,6 +519,7 @@ enum virDomainDeviceType { VIR_DOMAIN_DEVICE_VIDEO, VIR_DOMAIN_DEVICE_HOSTDEV, VIR_DOMAIN_DEVICE_WATCHDOG, + VIR_DOMAIN_DEVICE_CONTROLLER, VIR_DOMAIN_DEVICE_LAST, }; @@ -510,6 +530,7 @@ struct _virDomainDeviceDef { int type; union { virDomainDiskDefPtr disk; + virDomainControllerDefPtr controller; virDomainFSDefPtr fs; virDomainNetDefPtr net; virDomainInputDefPtr input; @@ -622,6 +643,9 @@ struct _virDomainDef { int ndisks; virDomainDiskDefPtr *disks; + int ncontrollers; + virDomainControllerDefPtr *controllers; + int nfss; virDomainFSDefPtr *fss; @@ -704,6 +728,7 @@ virDomainObjPtr virDomainFindByName(const virDomainObjListPtr doms, void virDomainGraphicsDefFree(virDomainGraphicsDefPtr def); void virDomainInputDefFree(virDomainInputDefPtr def); void virDomainDiskDefFree(virDomainDiskDefPtr def); +void virDomainControllerDefFree(virDomainControllerDefPtr def); void virDomainFSDefFree(virDomainFSDefPtr def); void virDomainNetDefFree(virDomainNetDefPtr def); void virDomainChrDefFree(virDomainChrDefPtr def); @@ -790,6 +815,10 @@ int virDomainDiskInsert(virDomainDefPtr def, virDomainDiskDefPtr disk); void virDomainDiskInsertPreAlloced(virDomainDefPtr def, virDomainDiskDefPtr disk); +int virDomainControllerInsert(virDomainDefPtr def, + virDomainControllerDefPtr controller); +void virDomainControllerInsertPreAlloced(virDomainDefPtr def, + virDomainControllerDefPtr controller); int virDomainSaveXML(virConnectPtr conn, const char *configDir, @@ -871,6 +900,7 @@ VIR_ENUM_DECL(virDomainDisk) VIR_ENUM_DECL(virDomainDiskDevice) VIR_ENUM_DECL(virDomainDiskBus) VIR_ENUM_DECL(virDomainDiskCache) +VIR_ENUM_DECL(virDomainController) VIR_ENUM_DECL(virDomainFS) VIR_ENUM_DECL(virDomainNet) VIR_ENUM_DECL(virDomainChrTarget) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 285715d..8622e5b 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -109,6 +109,8 @@ virDomainDiskDefFree; virDomainDiskDeviceTypeToString; virDomainDiskInsert; virDomainDiskInsertPreAlloced; +virDomainControllerInsert; +virDomainControllerInsertPreAlloced; virDomainFindByID; virDomainFindByName; virDomainFindByUUID; -- 1.6.5.2 -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list