126 lines
4.6 KiB
Diff
126 lines
4.6 KiB
Diff
|
commit 326ecb78145cfeb7706ef0dcd521b19d934950e7
|
||
|
Author: Daniel P. Berrange <berrange@redhat.com>
|
||
|
Date: Mon Jul 6 15:58:55 2009 +0100
|
||
|
|
||
|
Fix PCI device hotplug/unplug with newer QEMU
|
||
|
|
||
|
* src/qemu_driver.c: Try new monitor syntax for hotplug first. If
|
||
|
that fails fallback to old KVM specific syntax
|
||
|
|
||
|
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
|
||
|
index 2e55045..5a0ab12 100644
|
||
|
--- a/src/qemu_driver.c
|
||
|
+++ b/src/qemu_driver.c
|
||
|
@@ -4004,6 +4004,7 @@ static int qemudDomainAttachPciDiskDevice(virConnectPtr conn,
|
||
|
char *cmd, *reply, *s;
|
||
|
char *safe_path;
|
||
|
const char* type = virDomainDiskBusTypeToString(dev->data.disk->bus);
|
||
|
+ int tryOldSyntax = 0;
|
||
|
|
||
|
for (i = 0 ; i < vm->def->ndisks ; i++) {
|
||
|
if (STREQ(vm->def->disks[i]->dst, dev->data.disk->dst)) {
|
||
|
@@ -4018,14 +4019,15 @@ static int qemudDomainAttachPciDiskDevice(virConnectPtr conn,
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
+try_command:
|
||
|
safe_path = qemudEscapeMonitorArg(dev->data.disk->src);
|
||
|
if (!safe_path) {
|
||
|
virReportOOMError(conn);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
- ret = virAsprintf(&cmd, "pci_add 0 storage file=%s,if=%s",
|
||
|
- safe_path, type);
|
||
|
+ ret = virAsprintf(&cmd, "pci_add %s storage file=%s,if=%s",
|
||
|
+ (tryOldSyntax ? "0": "pci_addr=auto"), safe_path, type);
|
||
|
VIR_FREE(safe_path);
|
||
|
if (ret == -1) {
|
||
|
virReportOOMError(conn);
|
||
|
@@ -4041,17 +4043,27 @@ static int qemudDomainAttachPciDiskDevice(virConnectPtr conn,
|
||
|
|
||
|
DEBUG ("%s: pci_add reply: %s", vm->def->name, reply);
|
||
|
/* If the command succeeds qemu prints:
|
||
|
- * OK bus 0... */
|
||
|
-#define PCI_ATTACH_OK_MSG "OK bus 0, slot "
|
||
|
- if ((s=strstr(reply, PCI_ATTACH_OK_MSG))) {
|
||
|
- char* dummy = s;
|
||
|
- s += strlen(PCI_ATTACH_OK_MSG);
|
||
|
+ * OK bus 0, slot XXX...
|
||
|
+ * or
|
||
|
+ * OK domain 0, bus 0, slot XXX
|
||
|
+ */
|
||
|
+ if ((s = strstr(reply, "OK ")) &&
|
||
|
+ (s = strstr(s, "slot "))) {
|
||
|
+ char *dummy = s;
|
||
|
+ s += strlen("slot ");
|
||
|
|
||
|
if (virStrToLong_i ((const char*)s, &dummy, 10, &dev->data.disk->slotnum) == -1)
|
||
|
VIR_WARN("%s", _("Unable to parse slot number\n"));
|
||
|
+ /* XXX not neccessarily always going to end up in domain 0 / bus 0 :-( */
|
||
|
+ /* XXX this slotnum is not persistant across restarts :-( */
|
||
|
+ } else if (!tryOldSyntax && strstr(reply, "invalid char in expression")) {
|
||
|
+ VIR_FREE(reply);
|
||
|
+ VIR_FREE(cmd);
|
||
|
+ tryOldSyntax = 1;
|
||
|
+ goto try_command;
|
||
|
} else {
|
||
|
qemudReportError (conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
|
||
|
- _("adding %s disk failed"), type);
|
||
|
+ _("adding %s disk failed: %s"), type, reply);
|
||
|
VIR_FREE(reply);
|
||
|
VIR_FREE(cmd);
|
||
|
return -1;
|
||
|
@@ -4268,6 +4280,7 @@ static int qemudDomainDetachPciDiskDevice(virConnectPtr conn,
|
||
|
char *cmd = NULL;
|
||
|
char *reply = NULL;
|
||
|
virDomainDiskDefPtr detach = NULL;
|
||
|
+ int tryOldSyntax = 0;
|
||
|
|
||
|
for (i = 0 ; i < vm->def->ndisks ; i++) {
|
||
|
if (STREQ(vm->def->disks[i]->dst, dev->data.disk->dst)) {
|
||
|
@@ -4289,9 +4302,17 @@ static int qemudDomainDetachPciDiskDevice(virConnectPtr conn,
|
||
|
goto cleanup;
|
||
|
}
|
||
|
|
||
|
- if (virAsprintf(&cmd, "pci_del 0 %d", detach->slotnum) < 0) {
|
||
|
- virReportOOMError(conn);
|
||
|
- goto cleanup;
|
||
|
+try_command:
|
||
|
+ if (tryOldSyntax) {
|
||
|
+ if (virAsprintf(&cmd, "pci_del 0 %d", detach->slotnum) < 0) {
|
||
|
+ virReportOOMError(conn);
|
||
|
+ goto cleanup;
|
||
|
+ }
|
||
|
+ } else {
|
||
|
+ if (virAsprintf(&cmd, "pci_del pci_addr=0:0:%d", detach->slotnum) < 0) {
|
||
|
+ virReportOOMError(conn);
|
||
|
+ goto cleanup;
|
||
|
+ }
|
||
|
}
|
||
|
|
||
|
if (qemudMonitorCommand(vm, cmd, &reply) < 0) {
|
||
|
@@ -4301,12 +4322,19 @@ static int qemudDomainDetachPciDiskDevice(virConnectPtr conn,
|
||
|
}
|
||
|
|
||
|
DEBUG ("%s: pci_del reply: %s",vm->def->name, reply);
|
||
|
+
|
||
|
+ if (!tryOldSyntax &&
|
||
|
+ strstr(reply, "extraneous characters")) {
|
||
|
+ tryOldSyntax = 1;
|
||
|
+ goto try_command;
|
||
|
+ }
|
||
|
/* If the command fails due to a wrong slot qemu prints: invalid slot,
|
||
|
* nothing is printed on success */
|
||
|
- if (strstr(reply, "invalid slot")) {
|
||
|
+ if (strstr(reply, "invalid slot") ||
|
||
|
+ strstr(reply, "Invalid pci address")) {
|
||
|
qemudReportError (conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
|
||
|
- _("failed to detach disk %s: invalid slot %d"),
|
||
|
- detach->dst, detach->slotnum);
|
||
|
+ _("failed to detach disk %s: invalid slot %d: %s"),
|
||
|
+ detach->dst, detach->slotnum, reply);
|
||
|
goto cleanup;
|
||
|
}
|
||
|
|