diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index eafab067ca..a756f12658 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -564,3 +564,156 @@ virDomainPCIAddressReserveNextSlot(virDomainPCIAddressSetPtr addrs, addrs->lastFlags = flags; return 0; } + + +static char* +virDomainCCWAddressAsString(virDomainDeviceCCWAddressPtr addr) +{ + char *addrstr = NULL; + + ignore_value(virAsprintf(&addrstr, "%x.%x.%04x", + addr->cssid, + addr->ssid, + addr->devno)); + return addrstr; +} + +static int +virDomainCCWAddressIncrement(virDomainDeviceCCWAddressPtr addr) +{ + virDomainDeviceCCWAddress ccwaddr = *addr; + + /* We are not touching subchannel sets and channel subsystems */ + if (++ccwaddr.devno > VIR_DOMAIN_DEVICE_CCW_MAX_DEVNO) + return -1; + + *addr = ccwaddr; + return 0; +} + + +int +virDomainCCWAddressAssign(virDomainDeviceInfoPtr dev, + virDomainCCWAddressSetPtr addrs, + bool autoassign) +{ + int ret = -1; + char *addr = NULL; + + if (dev->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) + return 0; + + if (!autoassign && dev->addr.ccw.assigned) { + if (!(addr = virDomainCCWAddressAsString(&dev->addr.ccw))) + goto cleanup; + + if (virHashLookup(addrs->defined, addr)) { + virReportError(VIR_ERR_XML_ERROR, + _("The CCW devno '%s' is in use already "), + addr); + goto cleanup; + } + } else if (autoassign && !dev->addr.ccw.assigned) { + if (!(addr = virDomainCCWAddressAsString(&addrs->next)) < 0) + goto cleanup; + + while (virHashLookup(addrs->defined, addr)) { + if (virDomainCCWAddressIncrement(&addrs->next) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("There are no more free CCW devnos.")); + goto cleanup; + } + VIR_FREE(addr); + addr = virDomainCCWAddressAsString(&addrs->next); + } + dev->addr.ccw = addrs->next; + dev->addr.ccw.assigned = true; + } else { + return 0; + } + + if (virHashAddEntry(addrs->defined, addr, addr) < 0) + goto cleanup; + else + addr = NULL; /* memory will be freed by hash table */ + + ret = 0; + + cleanup: + VIR_FREE(addr); + return ret; +} + +int +virDomainCCWAddressAllocate(virDomainDefPtr def ATTRIBUTE_UNUSED, + virDomainDeviceDefPtr dev ATTRIBUTE_UNUSED, + virDomainDeviceInfoPtr info, + void *data) +{ + return virDomainCCWAddressAssign(info, data, true); +} + +int +virDomainCCWAddressValidate(virDomainDefPtr def ATTRIBUTE_UNUSED, + virDomainDeviceDefPtr dev ATTRIBUTE_UNUSED, + virDomainDeviceInfoPtr info, + void *data) +{ + return virDomainCCWAddressAssign(info, data, false); +} + +int +virDomainCCWAddressReleaseAddr(virDomainCCWAddressSetPtr addrs, + virDomainDeviceInfoPtr dev) +{ + char *addr; + int ret; + + addr = virDomainCCWAddressAsString(&(dev->addr.ccw)); + if (!addr) + return -1; + + if ((ret = virHashRemoveEntry(addrs->defined, addr)) == 0 && + dev->addr.ccw.cssid == addrs->next.cssid && + dev->addr.ccw.ssid == addrs->next.ssid && + dev->addr.ccw.devno < addrs->next.devno) { + addrs->next.devno = dev->addr.ccw.devno; + addrs->next.assigned = false; + } + + VIR_FREE(addr); + + return ret; +} + +void virDomainCCWAddressSetFree(virDomainCCWAddressSetPtr addrs) +{ + if (!addrs) + return; + + virHashFree(addrs->defined); + VIR_FREE(addrs); +} + +virDomainCCWAddressSetPtr +virDomainCCWAddressSetCreate(void) +{ + virDomainCCWAddressSetPtr addrs = NULL; + + if (VIR_ALLOC(addrs) < 0) + goto error; + + if (!(addrs->defined = virHashCreate(10, virHashValueFree))) + goto error; + + /* must use cssid = 0xfe (254) for virtio-ccw devices */ + addrs->next.cssid = 254; + addrs->next.ssid = 0; + addrs->next.devno = 0; + addrs->next.assigned = 0; + return addrs; + + error: + virDomainCCWAddressSetFree(addrs); + return NULL; +} diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h index ddad34abb4..2c3468e9e1 100644 --- a/src/conf/domain_addr.h +++ b/src/conf/domain_addr.h @@ -146,4 +146,31 @@ int virDomainPCIAddressReserveNextSlot(virDomainPCIAddressSetPtr addrs, virDomainPCIConnectFlags flags) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); +struct _virDomainCCWAddressSet { + virHashTablePtr defined; + virDomainDeviceCCWAddress next; +}; +typedef struct _virDomainCCWAddressSet virDomainCCWAddressSet; +typedef virDomainCCWAddressSet *virDomainCCWAddressSetPtr; + +int virDomainCCWAddressAssign(virDomainDeviceInfoPtr dev, + virDomainCCWAddressSetPtr addrs, + bool autoassign) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); +void virDomainCCWAddressSetFree(virDomainCCWAddressSetPtr addrs); +int virDomainCCWAddressAllocate(virDomainDefPtr def, + virDomainDeviceDefPtr dev, + virDomainDeviceInfoPtr info, + void *data) + ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4); +int virDomainCCWAddressValidate(virDomainDefPtr def, + virDomainDeviceDefPtr dev, + virDomainDeviceInfoPtr info, + void *data) + ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4); + +int virDomainCCWAddressReleaseAddr(virDomainCCWAddressSetPtr addrs, + virDomainDeviceInfoPtr dev) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); +virDomainCCWAddressSetPtr virDomainCCWAddressSetCreate(void); #endif /* __DOMAIN_ADDR_H__ */ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index ac56782b80..2a2b9c0797 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -90,6 +90,12 @@ virInterfaceStateTypeToString; # conf/domain_addr.h +virDomainCCWAddressAllocate; +virDomainCCWAddressAssign; +virDomainCCWAddressReleaseAddr; +virDomainCCWAddressSetCreate; +virDomainCCWAddressSetFree; +virDomainCCWAddressValidate; virDomainPCIAddressAsString; virDomainPCIAddressBusSetModel; virDomainPCIAddressEnsureAddr; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 2caee6665e..cc4b7cad54 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -1058,89 +1058,6 @@ qemuAssignDeviceAliases(virDomainDefPtr def, virQEMUCapsPtr qemuCaps) return 0; } -/* S390 ccw bus support */ - -struct _qemuDomainCCWAddressSet { - virHashTablePtr defined; - virDomainDeviceCCWAddress next; -}; - -static char* -qemuCCWAddressAsString(virDomainDeviceCCWAddressPtr addr) -{ - char *addrstr = NULL; - - ignore_value(virAsprintf(&addrstr, "%x.%x.%04x", - addr->cssid, - addr->ssid, - addr->devno)); - return addrstr; -} - -static int -qemuCCWAdressIncrement(virDomainDeviceCCWAddressPtr addr) -{ - virDomainDeviceCCWAddress ccwaddr = *addr; - - /* We are not touching subchannel sets and channel subsystems */ - if (++ccwaddr.devno > VIR_DOMAIN_DEVICE_CCW_MAX_DEVNO) - return -1; - - *addr = ccwaddr; - return 0; -} - - -int qemuDomainCCWAddressAssign(virDomainDeviceInfoPtr dev, - qemuDomainCCWAddressSetPtr addrs, - bool autoassign) -{ - int ret = -1; - char *addr = NULL; - - if (dev->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) - return 0; - - if (!autoassign && dev->addr.ccw.assigned) { - if (!(addr = qemuCCWAddressAsString(&dev->addr.ccw))) - goto cleanup; - - if (virHashLookup(addrs->defined, addr)) { - virReportError(VIR_ERR_XML_ERROR, - _("The CCW devno '%s' is in use already "), - addr); - goto cleanup; - } - } else if (autoassign && !dev->addr.ccw.assigned) { - if (!(addr = qemuCCWAddressAsString(&addrs->next)) < 0) - goto cleanup; - - while (virHashLookup(addrs->defined, addr)) { - if (qemuCCWAdressIncrement(&addrs->next) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("There are no more free CCW devnos.")); - goto cleanup; - } - VIR_FREE(addr); - addr = qemuCCWAddressAsString(&addrs->next); - } - dev->addr.ccw = addrs->next; - dev->addr.ccw.assigned = true; - } else { - return 0; - } - - if (virHashAddEntry(addrs->defined, addr, addr) < 0) - goto cleanup; - else - addr = NULL; /* memory will be freed by hash table */ - - ret = 0; - - cleanup: - VIR_FREE(addr); - return ret; -} static void qemuDomainPrimeVirtioDeviceAddresses(virDomainDefPtr def, @@ -1187,79 +1104,6 @@ qemuDomainPrimeVirtioDeviceAddresses(virDomainDefPtr def, def->rng->info.type = type; } -static int -qemuDomainCCWAddressAllocate(virDomainDefPtr def ATTRIBUTE_UNUSED, - virDomainDeviceDefPtr dev ATTRIBUTE_UNUSED, - virDomainDeviceInfoPtr info, - void *data) -{ - return qemuDomainCCWAddressAssign(info, data, true); -} - -static int -qemuDomainCCWAddressValidate(virDomainDefPtr def ATTRIBUTE_UNUSED, - virDomainDeviceDefPtr dev ATTRIBUTE_UNUSED, - virDomainDeviceInfoPtr info, - void *data) -{ - return qemuDomainCCWAddressAssign(info, data, false); -} - -static int -qemuDomainCCWAddressReleaseAddr(qemuDomainCCWAddressSetPtr addrs, - virDomainDeviceInfoPtr dev) -{ - char *addr; - int ret; - - addr = qemuCCWAddressAsString(&(dev->addr.ccw)); - if (!addr) - return -1; - - if ((ret = virHashRemoveEntry(addrs->defined, addr)) == 0 && - dev->addr.ccw.cssid == addrs->next.cssid && - dev->addr.ccw.ssid == addrs->next.ssid && - dev->addr.ccw.devno < addrs->next.devno) { - addrs->next.devno = dev->addr.ccw.devno; - addrs->next.assigned = false; - } - - VIR_FREE(addr); - - return ret; -} - -void qemuDomainCCWAddressSetFree(qemuDomainCCWAddressSetPtr addrs) -{ - if (!addrs) - return; - - virHashFree(addrs->defined); - VIR_FREE(addrs); -} - -static qemuDomainCCWAddressSetPtr -qemuDomainCCWAddressSetCreate(void) -{ - qemuDomainCCWAddressSetPtr addrs = NULL; - - if (VIR_ALLOC(addrs) < 0) - goto error; - - if (!(addrs->defined = virHashCreate(10, virHashValueFree))) - goto error; - - /* must use cssid = 0xfe (254) for virtio-ccw devices */ - addrs->next.cssid = 254; - addrs->next.ssid = 0; - addrs->next.devno = 0; - addrs->next.assigned = 0; - return addrs; - - error: - qemuDomainCCWAddressSetFree(addrs); - return NULL; -} /* * Three steps populating CCW devnos @@ -1273,7 +1117,7 @@ qemuDomainAssignS390Addresses(virDomainDefPtr def, virDomainObjPtr obj) { int ret = -1; - qemuDomainCCWAddressSetPtr addrs = NULL; + virDomainCCWAddressSetPtr addrs = NULL; qemuDomainObjPrivatePtr priv = NULL; if (STREQLEN(def->os.machine, "s390-ccw", 8) && @@ -1281,14 +1125,14 @@ qemuDomainAssignS390Addresses(virDomainDefPtr def, qemuDomainPrimeVirtioDeviceAddresses( def, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW); - if (!(addrs = qemuDomainCCWAddressSetCreate())) + if (!(addrs = virDomainCCWAddressSetCreate())) goto cleanup; - if (virDomainDeviceInfoIterate(def, qemuDomainCCWAddressValidate, + if (virDomainDeviceInfoIterate(def, virDomainCCWAddressValidate, addrs) < 0) goto cleanup; - if (virDomainDeviceInfoIterate(def, qemuDomainCCWAddressAllocate, + if (virDomainDeviceInfoIterate(def, virDomainCCWAddressAllocate, addrs) < 0) goto cleanup; } else if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_S390)) { @@ -1301,7 +1145,7 @@ qemuDomainAssignS390Addresses(virDomainDefPtr def, priv = obj->privateData; if (addrs) { /* if this is the live domain object, we persist the CCW addresses*/ - qemuDomainCCWAddressSetFree(priv->ccwaddrs); + virDomainCCWAddressSetFree(priv->ccwaddrs); priv->persistentAddrs = 1; priv->ccwaddrs = addrs; addrs = NULL; @@ -1312,7 +1156,7 @@ qemuDomainAssignS390Addresses(virDomainDefPtr def, ret = 0; cleanup: - qemuDomainCCWAddressSetFree(addrs); + virDomainCCWAddressSetFree(addrs); return ret; } @@ -1796,7 +1640,7 @@ qemuDomainReleaseDeviceAddress(virDomainObjPtr vm, if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW && STREQLEN(vm->def->os.machine, "s390-ccw", 8) && virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_VIRTIO_CCW) && - qemuDomainCCWAddressReleaseAddr(priv->ccwaddrs, info) < 0) + virDomainCCWAddressReleaseAddr(priv->ccwaddrs, info) < 0) VIR_WARN("Unable to release CCW address on %s", NULLSTR(devstr)); else if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI && diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index afbd6ff061..cf510561be 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -243,13 +243,9 @@ virDomainPCIAddressSetPtr qemuDomainPCIAddressSetCreate(virDomainDefPtr def, unsigned int nbuses, bool dryRun); -int qemuAssignDevicePCISlots(virDomainDefPtr def, - virQEMUCapsPtr qemuCaps, - virDomainPCIAddressSetPtr addrs); - -int qemuDomainCCWAddressAssign(virDomainDeviceInfoPtr dev, qemuDomainCCWAddressSetPtr addrs, - bool autoassign); -void qemuDomainCCWAddressSetFree(qemuDomainCCWAddressSetPtr addrs); +int qemuAssignDevicePCISlots(virDomainDefPtr def, + virQEMUCapsPtr qemuCaps, + virDomainPCIAddressSetPtr addrs); int qemuAssignDeviceAliases(virDomainDefPtr def, virQEMUCapsPtr qemuCaps); int qemuDomainNetVLAN(virDomainNetDefPtr def); diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 7c4fc67d50..a57f26eb42 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -249,7 +249,7 @@ qemuDomainObjPrivateFree(void *data) virCgroupFree(&priv->cgroup); virDomainPCIAddressSetFree(priv->pciaddrs); - qemuDomainCCWAddressSetFree(priv->ccwaddrs); + virDomainCCWAddressSetFree(priv->ccwaddrs); virDomainChrSourceDefFree(priv->monConfig); qemuDomainObjFreeJob(priv); VIR_FREE(priv->vcpupids); diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 8615f748e4..79dce29470 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -119,8 +119,6 @@ struct qemuDomainJobObj { typedef void (*qemuDomainCleanupCallback)(virQEMUDriverPtr driver, virDomainObjPtr vm); -typedef struct _qemuDomainCCWAddressSet qemuDomainCCWAddressSet; -typedef qemuDomainCCWAddressSet *qemuDomainCCWAddressSetPtr; typedef struct _qemuDomainObjPrivate qemuDomainObjPrivate; typedef qemuDomainObjPrivate *qemuDomainObjPrivatePtr; @@ -145,7 +143,7 @@ struct _qemuDomainObjPrivate { int *vcpupids; virDomainPCIAddressSetPtr pciaddrs; - qemuDomainCCWAddressSetPtr ccwaddrs; + virDomainCCWAddressSetPtr ccwaddrs; int persistentAddrs; virQEMUCapsPtr qemuCaps; diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 4590409e20..ca573c4208 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -279,8 +279,8 @@ qemuDomainAttachVirtioDiskDevice(virConnectPtr conn, if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) { if (disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) { - if (qemuDomainCCWAddressAssign(&disk->info, priv->ccwaddrs, - !disk->info.addr.ccw.assigned) < 0) + if (virDomainCCWAddressAssign(&disk->info, priv->ccwaddrs, + !disk->info.addr.ccw.assigned) < 0) goto error; } else if (!disk->info.type || disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) { @@ -389,8 +389,8 @@ int qemuDomainAttachControllerDevice(virQEMUDriverPtr driver, if (virDomainPCIAddressEnsureAddr(priv->pciaddrs, &controller->info) < 0) goto cleanup; } else if (controller->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) { - if (qemuDomainCCWAddressAssign(&controller->info, priv->ccwaddrs, - !controller->info.addr.ccw.assigned) < 0) + if (virDomainCCWAddressAssign(&controller->info, priv->ccwaddrs, + !controller->info.addr.ccw.assigned) < 0) goto cleanup; } releaseaddr = true; @@ -933,8 +933,8 @@ int qemuDomainAttachNetDevice(virConnectPtr conn, if (STREQLEN(vm->def->os.machine, "s390-ccw", 8) && virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_VIRTIO_CCW)) { net->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW; - if (qemuDomainCCWAddressAssign(&net->info, priv->ccwaddrs, - !net->info.addr.ccw.assigned) < 0) + if (virDomainCCWAddressAssign(&net->info, priv->ccwaddrs, + !net->info.addr.ccw.assigned) < 0) goto cleanup; } else if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_VIRTIO_S390)) virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 6af77c9758..0b8155b3d0 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -4448,7 +4448,7 @@ void qemuProcessStop(virQEMUDriverPtr driver, virDomainPCIAddressSetFree(priv->pciaddrs); priv->pciaddrs = NULL; virDomainDefClearCCWAddresses(vm->def); - qemuDomainCCWAddressSetFree(priv->ccwaddrs); + virDomainCCWAddressSetFree(priv->ccwaddrs); priv->ccwaddrs = NULL; }