The current code for parsing pci_add replies ignores the the domain and bus numbers. Re-write the code to rectify that. Also, since pci_add is used for NIC hotplug as well ask disk hotplug, re-factor the code into a separate function. * src/qemu_driver.c: add qemudParsePciAddReply() function which can handle parsing domain and bus numbers --- src/qemu_driver.c | 111 +++++++++++++++++++++++++++++++++++++++-------------- 1 files changed, 82 insertions(+), 29 deletions(-) diff --git a/src/qemu_driver.c b/src/qemu_driver.c index 4cc78f5..27bda12 100644 --- a/src/qemu_driver.c +++ b/src/qemu_driver.c @@ -4340,15 +4340,83 @@ static int qemudDomainChangeEjectableMedia(virConnectPtr conn, return 0; } +static int +qemudParsePciAddReply(virDomainObjPtr vm, + const char *reply, + int *domain, + int *bus, + int *slot) +{ + char *s, *e; + + DEBUG("%s: pci_add reply: %s", vm->def->name, reply); + + /* If the command succeeds qemu prints: + * OK bus 0, slot XXX... + * or + * OK domain 0, bus 0, slot XXX + */ + if (!(s = strstr(reply, "OK "))) + return -1; + + s += 3; + + if (STRPREFIX(s, "domain ")) { + s += strlen("domain "); + + if (virStrToLong_i(s, &e, 10, domain) == -1) { + VIR_WARN(_("Unable to parse domain number '%s'\n"), s); + return -1; + } + + if (!STRPREFIX(e, ", ")) { + VIR_WARN(_("Expected ', ' parsing pci_add reply '%s'\n"), s); + return -1; + } + s = e + 2; + } + + if (!STRPREFIX(s, "bus ")) { + VIR_WARN(_("Expected 'bus ' parsing pci_add reply '%s'\n"), s); + return -1; + } + s += strlen("bus "); + + if (virStrToLong_i(s, &e, 10, bus) == -1) { + VIR_WARN(_("Unable to parse bus number '%s'\n"), s); + return -1; + } + + if (!STRPREFIX(e, ", ")) { + VIR_WARN(_("Expected ', ' parsing pci_add reply '%s'\n"), s); + return -1; + } + s = e + 2; + + if (!STRPREFIX(s, "slot ")) { + VIR_WARN(_("Expected 'slot ' parsing pci_add reply '%s'\n"), s); + return -1; + } + s += strlen("slot "); + + if (virStrToLong_i(s, &e, 10, slot) == -1) { + VIR_WARN(_("Unable to parse slot number '%s'\n"), s); + return -1; + } + + return 0; +} + static int qemudDomainAttachPciDiskDevice(virConnectPtr conn, virDomainObjPtr vm, virDomainDeviceDefPtr dev) { int ret, i; - char *cmd, *reply, *s; + char *cmd, *reply; char *safe_path; const char* type = virDomainDiskBusTypeToString(dev->data.disk->bus); int tryOldSyntax = 0; + int domain, bus, slot; for (i = 0 ; i < vm->def->ndisks ; i++) { if (STREQ(vm->def->disks[i]->dst, dev->data.disk->dst)) { @@ -4387,46 +4455,31 @@ try_command: VIR_FREE(cmd); - DEBUG ("%s: pci_add reply: %s", vm->def->name, reply); - /* If the command succeeds qemu prints: - * 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; - int domain, bus, slot; - - s += strlen("slot "); - - /* XXX not neccessarily always going to end up in domain 0 / bus 0 :-( */ - domain = bus = 0; - if (virStrToLong_i ((const char*)s, &dummy, 10, &slot) == -1) - VIR_WARN("%s", _("Unable to parse slot number\n")); - else if (virAsprintf(&dev->data.disk->pci_addr, "%.4x:%.2x:%.2x", - domain, bus, slot) < 0) { - virReportOOMError(conn); + if (qemudParsePciAddReply(vm, reply, &domain, &bus, &slot) < 0) { + if (!tryOldSyntax && strstr(reply, "invalid char in expression")) { VIR_FREE(reply); - return -1; + tryOldSyntax = 1; + goto try_command; } - } else if (!tryOldSyntax && strstr(reply, "invalid char in expression")) { - VIR_FREE(reply); - tryOldSyntax = 1; - goto try_command; - } else { + qemudReportError (conn, dom, NULL, VIR_ERR_OPERATION_FAILED, _("adding %s disk failed: %s"), type, reply); VIR_FREE(reply); return -1; } + VIR_FREE(reply); + + if (virAsprintf(&dev->data.disk->pci_addr, "%.4x:%.2x:%.2x", + domain, bus, slot) < 0) { + virReportOOMError(conn); + return -1; + } + vm->def->disks[vm->def->ndisks++] = dev->data.disk; qsort(vm->def->disks, vm->def->ndisks, sizeof(*vm->def->disks), virDomainDiskQSort); - VIR_FREE(reply); - return 0; } -- 1.6.2.5 -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list