mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-25 23:25:24 +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++;
|
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,
|
int virDomainLeaseIndex(virDomainDefPtr def,
|
||||||
virDomainLeaseDefPtr lease)
|
virDomainLeaseDefPtr lease)
|
||||||
|
@ -2048,7 +2048,8 @@ int virDomainControllerInsert(virDomainDefPtr def,
|
|||||||
virDomainControllerDefPtr controller);
|
virDomainControllerDefPtr controller);
|
||||||
void virDomainControllerInsertPreAlloced(virDomainDefPtr def,
|
void virDomainControllerInsertPreAlloced(virDomainDefPtr def,
|
||||||
virDomainControllerDefPtr controller);
|
virDomainControllerDefPtr controller);
|
||||||
|
int virDomainControllerFind(virDomainDefPtr def, int type, int idx);
|
||||||
|
virDomainControllerDefPtr virDomainControllerRemove(virDomainDefPtr def, size_t i);
|
||||||
|
|
||||||
int virDomainLeaseIndex(virDomainDefPtr def,
|
int virDomainLeaseIndex(virDomainDefPtr def,
|
||||||
virDomainLeaseDefPtr lease);
|
virDomainLeaseDefPtr lease);
|
||||||
|
@ -266,12 +266,14 @@ virDomainClockOffsetTypeFromString;
|
|||||||
virDomainClockOffsetTypeToString;
|
virDomainClockOffsetTypeToString;
|
||||||
virDomainConfigFile;
|
virDomainConfigFile;
|
||||||
virDomainControllerDefFree;
|
virDomainControllerDefFree;
|
||||||
|
virDomainControllerFind;
|
||||||
virDomainControllerInsert;
|
virDomainControllerInsert;
|
||||||
virDomainControllerInsertPreAlloced;
|
virDomainControllerInsertPreAlloced;
|
||||||
virDomainControllerModelSCSITypeFromString;
|
virDomainControllerModelSCSITypeFromString;
|
||||||
virDomainControllerModelSCSITypeToString;
|
virDomainControllerModelSCSITypeToString;
|
||||||
virDomainControllerModelUSBTypeFromString;
|
virDomainControllerModelUSBTypeFromString;
|
||||||
virDomainControllerModelUSBTypeToString;
|
virDomainControllerModelUSBTypeToString;
|
||||||
|
virDomainControllerRemove;
|
||||||
virDomainControllerTypeToString;
|
virDomainControllerTypeToString;
|
||||||
virDomainCpuPlacementModeTypeFromString;
|
virDomainCpuPlacementModeTypeFromString;
|
||||||
virDomainCpuPlacementModeTypeToString;
|
virDomainCpuPlacementModeTypeToString;
|
||||||
|
@ -5535,6 +5535,7 @@ qemuDomainAttachDeviceConfig(virDomainDefPtr vmdef,
|
|||||||
virDomainNetDefPtr net;
|
virDomainNetDefPtr net;
|
||||||
virDomainHostdevDefPtr hostdev;
|
virDomainHostdevDefPtr hostdev;
|
||||||
virDomainLeaseDefPtr lease;
|
virDomainLeaseDefPtr lease;
|
||||||
|
virDomainControllerDefPtr controller;
|
||||||
|
|
||||||
switch (dev->type) {
|
switch (dev->type) {
|
||||||
case VIR_DOMAIN_DEVICE_DISK:
|
case VIR_DOMAIN_DEVICE_DISK:
|
||||||
@ -5607,6 +5608,23 @@ qemuDomainAttachDeviceConfig(virDomainDefPtr vmdef,
|
|||||||
dev->data.lease = NULL;
|
dev->data.lease = NULL;
|
||||||
break;
|
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:
|
default:
|
||||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
_("persistent attach of device is not supported"));
|
_("persistent attach of device is not supported"));
|
||||||
@ -5624,6 +5642,8 @@ qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef,
|
|||||||
virDomainNetDefPtr net, det_net;
|
virDomainNetDefPtr net, det_net;
|
||||||
virDomainHostdevDefPtr hostdev, det_hostdev;
|
virDomainHostdevDefPtr hostdev, det_hostdev;
|
||||||
virDomainLeaseDefPtr lease, det_lease;
|
virDomainLeaseDefPtr lease, det_lease;
|
||||||
|
virDomainControllerDefPtr cont, det_cont;
|
||||||
|
int idx;
|
||||||
|
|
||||||
switch (dev->type) {
|
switch (dev->type) {
|
||||||
case VIR_DOMAIN_DEVICE_DISK:
|
case VIR_DOMAIN_DEVICE_DISK:
|
||||||
@ -5650,8 +5670,6 @@ qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case VIR_DOMAIN_DEVICE_HOSTDEV: {
|
case VIR_DOMAIN_DEVICE_HOSTDEV: {
|
||||||
int idx;
|
|
||||||
|
|
||||||
hostdev = dev->data.hostdev;
|
hostdev = dev->data.hostdev;
|
||||||
if ((idx = virDomainHostdevFind(vmdef, hostdev, &det_hostdev)) < 0) {
|
if ((idx = virDomainHostdevFind(vmdef, hostdev, &det_hostdev)) < 0) {
|
||||||
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
||||||
@ -5674,6 +5692,19 @@ qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef,
|
|||||||
virDomainLeaseDefFree(det_lease);
|
virDomainLeaseDefFree(det_lease);
|
||||||
break;
|
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:
|
default:
|
||||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
_("persistent detach of device is not supported"));
|
_("persistent detach of device is not supported"));
|
||||||
|
@ -308,22 +308,18 @@ int qemuDomainAttachPciControllerDevice(struct qemud_driver *driver,
|
|||||||
virDomainObjPtr vm,
|
virDomainObjPtr vm,
|
||||||
virDomainControllerDefPtr controller)
|
virDomainControllerDefPtr controller)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
const char* type = virDomainControllerTypeToString(controller->type);
|
const char* type = virDomainControllerTypeToString(controller->type);
|
||||||
char *devstr = NULL;
|
char *devstr = NULL;
|
||||||
qemuDomainObjPrivatePtr priv = vm->privateData;
|
qemuDomainObjPrivatePtr priv = vm->privateData;
|
||||||
bool releaseaddr = false;
|
bool releaseaddr = false;
|
||||||
|
|
||||||
for (i = 0 ; i < vm->def->ncontrollers ; i++) {
|
if (virDomainControllerFind(vm->def, controller->type, controller->idx) > 0) {
|
||||||
if ((vm->def->controllers[i]->type == controller->type) &&
|
|
||||||
(vm->def->controllers[i]->idx == controller->idx)) {
|
|
||||||
virReportError(VIR_ERR_OPERATION_FAILED,
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
||||||
_("target %s:%d already exists"),
|
_("target %s:%d already exists"),
|
||||||
type, controller->idx);
|
type, controller->idx);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
|
if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
|
||||||
if (qemuDomainPCIAddressEnsureAddr(priv->pciaddrs, &controller->info) < 0)
|
if (qemuDomainPCIAddressEnsureAddr(priv->pciaddrs, &controller->info) < 0)
|
||||||
@ -1875,19 +1871,13 @@ int qemuDomainDetachPciControllerDevice(struct qemud_driver *driver,
|
|||||||
virDomainObjPtr vm,
|
virDomainObjPtr vm,
|
||||||
virDomainDeviceDefPtr dev)
|
virDomainDeviceDefPtr dev)
|
||||||
{
|
{
|
||||||
int i, ret = -1;
|
int idx, ret = -1;
|
||||||
virDomainControllerDefPtr detach = NULL;
|
virDomainControllerDefPtr detach = NULL;
|
||||||
qemuDomainObjPrivatePtr priv = vm->privateData;
|
qemuDomainObjPrivatePtr priv = vm->privateData;
|
||||||
|
|
||||||
for (i = 0 ; i < vm->def->ncontrollers ; i++) {
|
if ((idx = virDomainControllerFind(vm->def,
|
||||||
if ((vm->def->controllers[i]->type == dev->data.controller->type) &&
|
dev->data.controller->type,
|
||||||
(vm->def->controllers[i]->idx == dev->data.controller->idx)) {
|
dev->data.controller->idx)) < 0) {
|
||||||
detach = vm->def->controllers[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!detach) {
|
|
||||||
virReportError(VIR_ERR_OPERATION_FAILED,
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
||||||
_("disk controller %s:%d not found"),
|
_("disk controller %s:%d not found"),
|
||||||
virDomainControllerTypeToString(dev->data.controller->type),
|
virDomainControllerTypeToString(dev->data.controller->type),
|
||||||
@ -1895,6 +1885,8 @@ int qemuDomainDetachPciControllerDevice(struct qemud_driver *driver,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
detach = vm->def->controllers[idx];
|
||||||
|
|
||||||
if (!virDomainDeviceAddressIsValid(&detach->info,
|
if (!virDomainDeviceAddressIsValid(&detach->info,
|
||||||
VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)) {
|
VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)) {
|
||||||
virReportError(VIR_ERR_OPERATION_FAILED, "%s",
|
virReportError(VIR_ERR_OPERATION_FAILED, "%s",
|
||||||
@ -1935,27 +1927,14 @@ int qemuDomainDetachPciControllerDevice(struct qemud_driver *driver,
|
|||||||
}
|
}
|
||||||
qemuDomainObjExitMonitorWithDriver(driver, vm);
|
qemuDomainObjExitMonitorWithDriver(driver, vm);
|
||||||
|
|
||||||
if (vm->def->ncontrollers > 1) {
|
virDomainControllerRemove(vm->def, idx);
|
||||||
memmove(vm->def->controllers + i,
|
virDomainControllerDefFree(detach);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE) &&
|
if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE) &&
|
||||||
qemuDomainPCIAddressReleaseSlot(priv->pciaddrs,
|
qemuDomainPCIAddressReleaseSlot(priv->pciaddrs,
|
||||||
detach->info.addr.pci.slot) < 0)
|
detach->info.addr.pci.slot) < 0)
|
||||||
VIR_WARN("Unable to release PCI address on controller");
|
VIR_WARN("Unable to release PCI address on controller");
|
||||||
|
|
||||||
virDomainControllerDefFree(detach);
|
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
Loading…
Reference in New Issue
Block a user