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 * docs/schemas/domain.rng: Define syntax for <controller> XML element * src/conf/domain_conf.c, src/conf/domain_conf.h: Define virDomainControllerDef struct, and routines for parsing and formatting XML * src/libvirt_private.syms: Add virDomainControllerInsert and virDomainControllerDefFree --- docs/schemas/domain.rng | 20 +++++ src/conf/domain_conf.c | 192 +++++++++++++++++++++++++++++++++++++++++++++- src/conf/domain_conf.h | 31 ++++++++ src/libvirt_private.syms | 2 + 4 files changed, 244 insertions(+), 1 deletions(-) diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng index dd729c0..a32ce45 100644 --- a/docs/schemas/domain.rng +++ b/docs/schemas/domain.rng @@ -521,6 +521,25 @@ </choice> </attribute> </define> + <define name="controller"> + <element name="controller"> + <optional> + <attribute name="type"> + <choice> + <value>fdc</value> + <value>ide</value> + <value>scsi</value> + </choice> + </attribute> + </optional> + <attribute name="index"> + <ref name="unsignedInt"/> + </attribute> + <optional> + <ref name="address"/> + </optional> + </element> + </define> <define name="filesystem"> <element name="filesystem"> <choice> @@ -1225,6 +1244,7 @@ <zeroOrMore> <choice> <ref name="disk"/> + <ref name="controller"/> <ref name="filesystem"/> <ref name="interface"/> <ref name="input"/> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 662ff81..dd10f36 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", @@ -119,6 +120,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", @@ -367,6 +374,16 @@ void virDomainDiskDefFree(virDomainDiskDefPtr def) VIR_FREE(def); } +void virDomainControllerDefFree(virDomainControllerDefPtr def) +{ + if (!def) + return; + + virDomainDeviceInfoClear(&def->info); + + VIR_FREE(def); +} + void virDomainFSDefFree(virDomainFSDefPtr def) { if (!def) @@ -528,6 +545,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); @@ -561,6 +581,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); @@ -1335,6 +1359,63 @@ 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; + char *type = NULL; + char *idx = 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; + } + } + + if (virDomainDeviceInfoParseXML(conn, node, &def->info, flags) < 0) + goto error; + + if (def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE && + def->info.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 */ @@ -2995,6 +3076,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")); @@ -3067,6 +3152,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, @@ -3382,6 +3520,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, @@ -4299,6 +4456,35 @@ virDomainDiskDefFormat(virConnectPtr conn, } static int +virDomainControllerDefFormat(virConnectPtr conn, + virBufferPtr buf, + virDomainControllerDefPtr def) +{ + 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 (virDomainDeviceInfoIsSet(&def->info)) { + virBufferAddLit(buf, ">\n"); + if (virDomainDeviceInfoFormat(buf, &def->info) < 0) + return -1; + virBufferAddLit(buf, " </controller>\n"); + } else { + virBufferAddLit(buf, "/>\n"); + } + + return 0; +} + +static int virDomainFSDefFormat(virConnectPtr conn, virBufferPtr buf, virDomainFSDefPtr def) @@ -5045,6 +5231,10 @@ char *virDomainDefFormat(virConnectPtr conn, if (virDomainDiskDefFormat(conn, &buf, def->disks[n]) < 0) goto cleanup; + for (n = 0 ; n < def->ncontrollers ; n++) + if (virDomainControllerDefFormat(conn, &buf, def->controllers[n]) < 0) + goto cleanup; + for (n = 0 ; n < def->nfss ; n++) if (virDomainFSDefFormat(conn, &buf, def->fss[n]) < 0) goto cleanup; diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index a05835a..9f2271c 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -160,6 +160,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; + virDomainDeviceInfo info; +}; + + /* Two types of disk backends */ enum virDomainFSType { VIR_DOMAIN_FS_TYPE_MOUNT, /* Better named 'bind' */ @@ -488,6 +507,7 @@ enum virDomainDeviceType { VIR_DOMAIN_DEVICE_VIDEO, VIR_DOMAIN_DEVICE_HOSTDEV, VIR_DOMAIN_DEVICE_WATCHDOG, + VIR_DOMAIN_DEVICE_CONTROLLER, VIR_DOMAIN_DEVICE_LAST, }; @@ -498,6 +518,7 @@ struct _virDomainDeviceDef { int type; union { virDomainDiskDefPtr disk; + virDomainControllerDefPtr controller; virDomainFSDefPtr fs; virDomainNetDefPtr net; virDomainInputDefPtr input; @@ -610,6 +631,9 @@ struct _virDomainDef { int ndisks; virDomainDiskDefPtr *disks; + int ncontrollers; + virDomainControllerDefPtr *controllers; + int nfss; virDomainFSDefPtr *fss; @@ -693,6 +717,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); @@ -775,6 +800,11 @@ void virDomainDiskInsertPreAlloced(virDomainDefPtr def, virDomainDiskDefPtr disk); void virDomainDiskDefAssignAddress(virDomainDiskDefPtr def); +int virDomainControllerInsert(virDomainDefPtr def, + virDomainControllerDefPtr controller); +void virDomainControllerInsertPreAlloced(virDomainDefPtr def, + virDomainControllerDefPtr controller); + int virDomainSaveXML(virConnectPtr conn, const char *configDir, virDomainDefPtr def, @@ -855,6 +885,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 9a4f444..a346aa5 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -130,6 +130,8 @@ virDomainDiskDeviceTypeToString; virDomainDiskInsert; virDomainDiskInsertPreAlloced; virDomainDiskDefAssignAddress; +virDomainControllerInsert; +virDomainControllerInsertPreAlloced; virDomainFindByID; virDomainFindByName; virDomainFindByUUID; -- 1.6.5.2 -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list