From ed1e711b996bd28e0f995643f029658d5618f774 Mon Sep 17 00:00:00 2001 From: Osier Yang Date: Mon, 23 Jul 2012 16:18:57 +0800 Subject: [PATCH] qemu: Allow to attach/detach controller device persistently * src/conf/domain_conf.c: - Add virDomainControllerFind to find controller device by type and index. - Add virDomainControllerRemove to remove the controller device from maintained controler list. * src/conf/domain_conf.h: - Declare the two new helpers. * src/libvirt_private.syms: - Expose private symbols for the two new helpers. * src/qemu/qemu_driver.c: - Support attach/detach controller device persistently * src/qemu/qemu_hotplug.c: - Use the two helpers to simplify the codes. --- src/conf/domain_conf.c | 37 +++++++++++++++++++++++++++++++ src/conf/domain_conf.h | 3 ++- src/libvirt_private.syms | 2 ++ src/qemu/qemu_driver.c | 35 ++++++++++++++++++++++++++++-- src/qemu/qemu_hotplug.c | 47 +++++++++++----------------------------- 5 files changed, 87 insertions(+), 37 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 43b3f804af..58603a3710 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -7556,6 +7556,43 @@ void virDomainControllerInsertPreAlloced(virDomainDefPtr def, def->ncontrollers++; } +int +virDomainControllerFind(virDomainDefPtr def, + int type, int idx) +{ + int i; + + for (i = 0 ; i < def->ncontrollers ; i++) { + if ((def->controllers[i]->type == type) && + (def->controllers[i]->idx == idx)) { + return i; + } + } + + return -1; +} + +virDomainControllerDefPtr +virDomainControllerRemove(virDomainDefPtr def, size_t i) +{ + virDomainControllerDefPtr controller = def->controllers[i]; + + if (def->ncontrollers > 1) { + memmove(def->controllers + i, + def->controllers + i + 1, + sizeof(*def->controllers) * + (def->ncontrollers - (i + 1))); + def->ncontrollers--; + if (VIR_REALLOC_N(def->controllers, def->ncontrollers) < 0) { + /* ignore, harmless */ + } + } else { + VIR_FREE(def->controllers); + def->ncontrollers = 0; + } + + return controller; +} int virDomainLeaseIndex(virDomainDefPtr def, virDomainLeaseDefPtr lease) diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 9fdda785ce..f4c43c64c9 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2048,7 +2048,8 @@ int virDomainControllerInsert(virDomainDefPtr def, virDomainControllerDefPtr controller); void virDomainControllerInsertPreAlloced(virDomainDefPtr def, virDomainControllerDefPtr controller); - +int virDomainControllerFind(virDomainDefPtr def, int type, int idx); +virDomainControllerDefPtr virDomainControllerRemove(virDomainDefPtr def, size_t i); int virDomainLeaseIndex(virDomainDefPtr def, virDomainLeaseDefPtr lease); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index aace7486a1..75997fedea 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -266,12 +266,14 @@ virDomainClockOffsetTypeFromString; virDomainClockOffsetTypeToString; virDomainConfigFile; virDomainControllerDefFree; +virDomainControllerFind; virDomainControllerInsert; virDomainControllerInsertPreAlloced; virDomainControllerModelSCSITypeFromString; virDomainControllerModelSCSITypeToString; virDomainControllerModelUSBTypeFromString; virDomainControllerModelUSBTypeToString; +virDomainControllerRemove; virDomainControllerTypeToString; virDomainCpuPlacementModeTypeFromString; virDomainCpuPlacementModeTypeToString; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 270e4dd93a..369e8edd9e 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -5535,6 +5535,7 @@ qemuDomainAttachDeviceConfig(virDomainDefPtr vmdef, virDomainNetDefPtr net; virDomainHostdevDefPtr hostdev; virDomainLeaseDefPtr lease; + virDomainControllerDefPtr controller; switch (dev->type) { case VIR_DOMAIN_DEVICE_DISK: @@ -5607,6 +5608,23 @@ qemuDomainAttachDeviceConfig(virDomainDefPtr vmdef, dev->data.lease = NULL; break; + case VIR_DOMAIN_DEVICE_CONTROLLER: + controller = dev->data.controller; + if (virDomainControllerFind(vmdef, controller->type, + controller->idx) > 0) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("Target already exists")); + return -1; + } + + if (virDomainControllerInsert(vmdef, controller) < 0) + return -1; + dev->data.controller = NULL; + + if (qemuDomainAssignAddresses(vmdef, NULL, NULL) < 0) + return -1; + break; + default: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("persistent attach of device is not supported")); @@ -5624,6 +5642,8 @@ qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef, virDomainNetDefPtr net, det_net; virDomainHostdevDefPtr hostdev, det_hostdev; virDomainLeaseDefPtr lease, det_lease; + virDomainControllerDefPtr cont, det_cont; + int idx; switch (dev->type) { case VIR_DOMAIN_DEVICE_DISK: @@ -5650,8 +5670,6 @@ qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef, break; case VIR_DOMAIN_DEVICE_HOSTDEV: { - int idx; - hostdev = dev->data.hostdev; if ((idx = virDomainHostdevFind(vmdef, hostdev, &det_hostdev)) < 0) { virReportError(VIR_ERR_INVALID_ARG, "%s", @@ -5674,6 +5692,19 @@ qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef, virDomainLeaseDefFree(det_lease); break; + case VIR_DOMAIN_DEVICE_CONTROLLER: + cont = dev->data.controller; + if ((idx = virDomainControllerFind(vmdef, cont->type, + cont->idx)) < 0) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("device not present in domain configuration")); + return -1; + } + det_cont = virDomainControllerRemove(vmdef, idx); + virDomainControllerDefFree(det_cont); + + break; + default: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("persistent detach of device is not supported")); diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index f5f96ed8dd..71ec48438b 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -308,21 +308,17 @@ int qemuDomainAttachPciControllerDevice(struct qemud_driver *driver, virDomainObjPtr vm, virDomainControllerDefPtr controller) { - int i; int ret = -1; const char* type = virDomainControllerTypeToString(controller->type); char *devstr = NULL; qemuDomainObjPrivatePtr priv = vm->privateData; bool releaseaddr = false; - for (i = 0 ; i < vm->def->ncontrollers ; i++) { - if ((vm->def->controllers[i]->type == controller->type) && - (vm->def->controllers[i]->idx == controller->idx)) { - virReportError(VIR_ERR_OPERATION_FAILED, - _("target %s:%d already exists"), - type, controller->idx); - return -1; - } + if (virDomainControllerFind(vm->def, controller->type, controller->idx) > 0) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("target %s:%d already exists"), + type, controller->idx); + return -1; } if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) { @@ -1875,19 +1871,13 @@ int qemuDomainDetachPciControllerDevice(struct qemud_driver *driver, virDomainObjPtr vm, virDomainDeviceDefPtr dev) { - int i, ret = -1; + int idx, ret = -1; virDomainControllerDefPtr detach = NULL; qemuDomainObjPrivatePtr priv = vm->privateData; - for (i = 0 ; i < vm->def->ncontrollers ; i++) { - if ((vm->def->controllers[i]->type == dev->data.controller->type) && - (vm->def->controllers[i]->idx == dev->data.controller->idx)) { - detach = vm->def->controllers[i]; - break; - } - } - - if (!detach) { + if ((idx = virDomainControllerFind(vm->def, + dev->data.controller->type, + dev->data.controller->idx)) < 0) { virReportError(VIR_ERR_OPERATION_FAILED, _("disk controller %s:%d not found"), virDomainControllerTypeToString(dev->data.controller->type), @@ -1895,6 +1885,8 @@ int qemuDomainDetachPciControllerDevice(struct qemud_driver *driver, goto cleanup; } + detach = vm->def->controllers[idx]; + if (!virDomainDeviceAddressIsValid(&detach->info, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)) { virReportError(VIR_ERR_OPERATION_FAILED, "%s", @@ -1935,27 +1927,14 @@ int qemuDomainDetachPciControllerDevice(struct qemud_driver *driver, } qemuDomainObjExitMonitorWithDriver(driver, vm); - if (vm->def->ncontrollers > 1) { - memmove(vm->def->controllers + i, - vm->def->controllers + i + 1, - sizeof(*vm->def->controllers) * - (vm->def->ncontrollers - (i + 1))); - vm->def->ncontrollers--; - if (VIR_REALLOC_N(vm->def->controllers, vm->def->ncontrollers) < 0) { - /* ignore, harmless */ - } - } else { - VIR_FREE(vm->def->controllers); - vm->def->ncontrollers = 0; - } + virDomainControllerRemove(vm->def, idx); + virDomainControllerDefFree(detach); if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE) && qemuDomainPCIAddressReleaseSlot(priv->pciaddrs, detach->info.addr.pci.slot) < 0) VIR_WARN("Unable to release PCI address on controller"); - virDomainControllerDefFree(detach); - ret = 0; cleanup: