mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-08-28 19:41:16 +00:00
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.
This commit is contained in:
parent
7383c1d762
commit
ed1e711b99
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -266,12 +266,14 @@ virDomainClockOffsetTypeFromString;
|
||||
virDomainClockOffsetTypeToString;
|
||||
virDomainConfigFile;
|
||||
virDomainControllerDefFree;
|
||||
virDomainControllerFind;
|
||||
virDomainControllerInsert;
|
||||
virDomainControllerInsertPreAlloced;
|
||||
virDomainControllerModelSCSITypeFromString;
|
||||
virDomainControllerModelSCSITypeToString;
|
||||
virDomainControllerModelUSBTypeFromString;
|
||||
virDomainControllerModelUSBTypeToString;
|
||||
virDomainControllerRemove;
|
||||
virDomainControllerTypeToString;
|
||||
virDomainCpuPlacementModeTypeFromString;
|
||||
virDomainCpuPlacementModeTypeToString;
|
||||
|
@ -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"));
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user