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