From 8540dadbe9c131a2a0edef440d561e98b396e197 Mon Sep 17 00:00:00 2001 From: Wolfgang Mauerer Date: Tue, 2 Mar 2010 09:40:51 +0100 Subject: [PATCH] Use device_del to remove SCSI controllers when the underlying qemu supports the drive/device model and the controller has been added this way. * src/qemu/qemu_driver.c: use qemuMonitorDelDevice() when detaching PCI controller and if supported * src/qemu/qemu_monitor.[ch]: add new qemuMonitorDelDevice() function * src/qemu/qemu_monitor_json.[ch]: JSON backend for DelDevice command * src/qemu/qemu_monitor_text.[ch]: Text backend for DelDevice command --- src/qemu/qemu_driver.c | 31 ++++++++++++++++++++++------ src/qemu/qemu_monitor.c | 13 ++++++++++++ src/qemu/qemu_monitor.h | 3 +++ src/qemu/qemu_monitor_json.c | 24 ++++++++++++++++++++++ src/qemu/qemu_monitor_json.h | 3 +++ src/qemu/qemu_monitor_text.c | 40 ++++++++++++++++++++++++++++++++++++ src/qemu/qemu_monitor_text.h | 3 +++ 7 files changed, 111 insertions(+), 6 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 8960ef8925..d683b1cb6b 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -6230,7 +6230,8 @@ cleanup: static int qemudDomainDetachPciControllerDevice(struct qemud_driver *driver, virDomainObjPtr vm, - virDomainDeviceDefPtr dev) + virDomainDeviceDefPtr dev, + unsigned long long qemuCmdFlags) { int i, ret = -1; virDomainControllerDefPtr detach = NULL; @@ -6259,11 +6260,23 @@ static int qemudDomainDetachPciControllerDevice(struct qemud_driver *driver, goto cleanup; } + if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) { + if (qemuAssignDeviceControllerAlias(detach) < 0) + goto cleanup; + } + qemuDomainObjEnterMonitorWithDriver(driver, vm); - if (qemuMonitorRemovePCIDevice(priv->mon, - &detach->info.addr.pci) < 0) { - qemuDomainObjExitMonitor(vm); - goto cleanup; + if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) { + if (qemuMonitorDelDevice(priv->mon, detach->info.alias)) { + qemuDomainObjExitMonitor(vm); + goto cleanup; + } + } else { + if (qemuMonitorRemovePCIDevice(priv->mon, + &detach->info.addr.pci) < 0) { + qemuDomainObjExitMonitor(vm); + goto cleanup; + } } qemuDomainObjExitMonitorWithDriver(driver, vm); @@ -6513,6 +6526,7 @@ static int qemudDomainDetachDevice(virDomainPtr dom, const char *xml) { struct qemud_driver *driver = dom->conn->privateData; virDomainObjPtr vm; + unsigned long long qemuCmdFlags; virDomainDeviceDefPtr dev = NULL; int ret = -1; @@ -6540,6 +6554,10 @@ static int qemudDomainDetachDevice(virDomainPtr dom, if (dev == NULL) goto endjob; + if (qemudExtractVersionInfo(vm->def->emulator, + NULL, + &qemuCmdFlags) < 0) + goto endjob; if (dev->type == VIR_DOMAIN_DEVICE_DISK && dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_DISK && @@ -6549,7 +6567,8 @@ static int qemudDomainDetachDevice(virDomainPtr dom, ret = qemudDomainDetachNetDevice(driver, vm, dev); } else if (dev->type == VIR_DOMAIN_DEVICE_CONTROLLER) { if (dev->data.controller->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI) { - ret = qemudDomainDetachPciControllerDevice(driver, vm, dev); + ret = qemudDomainDetachPciControllerDevice(driver, vm, dev, + qemuCmdFlags); } else { qemuReportError(VIR_ERR_NO_SUPPORT, _("disk controller bus '%s' cannot be hotunplugged."), diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index b88532c7cf..a4d2b890e2 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -1318,6 +1318,19 @@ int qemuMonitorGetAllPCIAddresses(qemuMonitorPtr mon, return ret; } +int qemuMonitorDelDevice(qemuMonitorPtr mon, + const char *devicestr) +{ + DEBUG("mon=%p, fd=%d device(del)=%s", mon, mon->fd, devicestr); + int ret; + + if (mon->json) + ret = qemuMonitorJSONDelDevice(mon, devicestr); + else + ret = qemuMonitorTextDelDevice(mon, devicestr); + return ret; +} + int qemuMonitorAddDevice(qemuMonitorPtr mon, const char *devicestr) diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 0ac39574fc..3e552360e2 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -290,6 +290,9 @@ int qemuMonitorGetAllPCIAddresses(qemuMonitorPtr mon, int qemuMonitorAddDevice(qemuMonitorPtr mon, const char *devicestr); +int qemuMonitorDelDevice(qemuMonitorPtr mon, + const char *devicestr); + int qemuMonitorAddDrive(qemuMonitorPtr mon, const char *drivestr); diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 7b45594c5e..3a94dd0bbe 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -1835,6 +1835,30 @@ int qemuMonitorJSONGetAllPCIAddresses(qemuMonitorPtr mon ATTRIBUTE_UNUSED, } +int qemuMonitorJSONDelDevice(qemuMonitorPtr mon, + const char *devicestr) +{ + int ret; + virJSONValuePtr cmd; + virJSONValuePtr reply = NULL; + + cmd = qemuMonitorJSONMakeCommand("device_del", + "s:config", devicestr, + NULL); + if (!cmd) + return -1; + + ret = qemuMonitorJSONCommand(mon, cmd, &reply); + + if (ret == 0) + ret = qemuMonitorJSONCheckError(cmd, reply); + + virJSONValueFree(cmd); + virJSONValueFree(reply); + return ret; +} + + int qemuMonitorJSONAddDevice(qemuMonitorPtr mon, const char *devicestr) { diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index c6a6d5141a..70a8dae6cb 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -161,6 +161,9 @@ int qemuMonitorJSONGetAllPCIAddresses(qemuMonitorPtr mon, int qemuMonitorJSONAddDevice(qemuMonitorPtr mon, const char *devicestr); +int qemuMonitorJSONDelDevice(qemuMonitorPtr mon, + const char *devicestr); + int qemuMonitorJSONAddDrive(qemuMonitorPtr mon, const char *drivestr); diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index e7b4b1fe61..7604ae824f 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -2058,6 +2058,46 @@ error: #undef SKIP_TO +int qemuMonitorTextDelDevice(qemuMonitorPtr mon, + const char *devicestr) +{ + char *cmd = NULL; + char *reply = NULL; + char *safedev; + int ret = -1; + + if (!(safedev = qemuMonitorEscapeArg(devicestr))) { + virReportOOMError(); + goto cleanup; + } + + if (virAsprintf(&cmd, "device_del %s", safedev) < 0) { + virReportOOMError(); + goto cleanup; + } + + if (qemuMonitorCommand(mon, cmd, &reply) < 0) { + qemuReportError(VIR_ERR_OPERATION_FAILED, + _("cannot detach %s device"), devicestr); + goto cleanup; + } + + if (STRNEQ(reply, "")) { + qemuReportError(VIR_ERR_OPERATION_FAILED, + _("detaching %s device failed: %s"), devicestr, reply); + goto cleanup; + } + + ret = 0; + +cleanup: + VIR_FREE(cmd); + VIR_FREE(reply); + VIR_FREE(safedev); + return ret; +} + + int qemuMonitorTextAddDevice(qemuMonitorPtr mon, const char *devicestr) { diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h index 1937e99957..9dcb0c2e6c 100644 --- a/src/qemu/qemu_monitor_text.h +++ b/src/qemu/qemu_monitor_text.h @@ -163,6 +163,9 @@ int qemuMonitorTextGetAllPCIAddresses(qemuMonitorPtr mon, int qemuMonitorTextAddDevice(qemuMonitorPtr mon, const char *devicestr); +int qemuMonitorTextDelDevice(qemuMonitorPtr mon, + const char *devicestr); + int qemuMonitorTextAddDrive(qemuMonitorPtr mon, const char *drivestr);