diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 4b608397ac..b4870beb11 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -155,34 +155,38 @@ qemuDomainCheckEjectableMedia(struct qemud_driver *driver, virDomainObjPtr vm) { qemuDomainObjPrivatePtr priv = vm->privateData; + virHashTablePtr table; int ret = -1; int i; + qemuDomainObjEnterMonitor(driver, vm); + table = qemuMonitorGetBlockInfo(priv->mon); + qemuDomainObjExitMonitor(driver, vm); + + if (!table) + goto cleanup; + for (i = 0; i < vm->def->ndisks; i++) { virDomainDiskDefPtr disk = vm->def->disks[i]; - struct qemuDomainDiskInfo info; + struct qemuDomainDiskInfo *info; if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK || disk->device == VIR_DOMAIN_DISK_DEVICE_LUN) { continue; } - memset(&info, 0, sizeof(info)); - - qemuDomainObjEnterMonitor(driver, vm); - if (qemuMonitorGetBlockInfo(priv->mon, disk->info.alias, &info) < 0) { - qemuDomainObjExitMonitor(driver, vm); + info = qemuMonitorBlockInfoLookup(table, disk->info.alias); + if (!info) goto cleanup; - } - qemuDomainObjExitMonitor(driver, vm); - if (info.tray_open && disk->src) + if (info->tray_open && disk->src) VIR_FREE(disk->src); } ret = 0; cleanup: + virHashFree(table); return ret; } diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index ad7e2a554d..dda0521731 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -1227,24 +1227,51 @@ int qemuMonitorGetMemoryStats(qemuMonitorPtr mon, return ret; } -int qemuMonitorGetBlockInfo(qemuMonitorPtr mon, - const char *devname, - struct qemuDomainDiskInfo *info) +virHashTablePtr +qemuMonitorGetBlockInfo(qemuMonitorPtr mon) { int ret; + virHashTablePtr table; + + VIR_DEBUG("mon=%p", mon); - VIR_DEBUG("mon=%p dev=%p info=%p", mon, devname, info); if (!mon) { qemuReportError(VIR_ERR_INVALID_ARG, "%s", _("monitor must not be NULL")); - return -1; + return NULL; } + if (!(table = virHashCreate(32, (virHashDataFree) free))) + return NULL; + if (mon->json) - ret = qemuMonitorJSONGetBlockInfo(mon, devname, info); + ret = qemuMonitorJSONGetBlockInfo(mon, table); else - ret = qemuMonitorTextGetBlockInfo(mon, devname, info); - return ret; + ret = qemuMonitorTextGetBlockInfo(mon, table); + + if (ret < 0) { + virHashFree(table); + return NULL; + } + + return table; +} + +struct qemuDomainDiskInfo * +qemuMonitorBlockInfoLookup(virHashTablePtr blockInfo, + const char *devname) +{ + struct qemuDomainDiskInfo *info; + + VIR_DEBUG("blockInfo=%p dev=%s", blockInfo, NULLSTR(devname)); + + if (!(info = virHashLookup(blockInfo, devname))) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, + _("cannot find info for device '%s'"), + NULLSTR(devname)); + } + + return info; } int qemuMonitorGetBlockStatsInfo(qemuMonitorPtr mon, diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 88ce303dd9..a9471fe85e 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -235,9 +235,12 @@ int qemuMonitorGetBalloonInfo(qemuMonitorPtr mon, int qemuMonitorGetMemoryStats(qemuMonitorPtr mon, virDomainMemoryStatPtr stats, unsigned int nr_stats); -int qemuMonitorGetBlockInfo(qemuMonitorPtr mon, - const char *devname, - struct qemuDomainDiskInfo *info); + +virHashTablePtr qemuMonitorGetBlockInfo(qemuMonitorPtr mon); +struct qemuDomainDiskInfo * +qemuMonitorBlockInfoLookup(virHashTablePtr blockInfo, + const char *devname); + int qemuMonitorGetBlockStatsInfo(qemuMonitorPtr mon, const char *dev_name, long long *rd_req, diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 11fdc0d792..0bd9f46240 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -1357,11 +1357,9 @@ cleanup: int qemuMonitorJSONGetBlockInfo(qemuMonitorPtr mon, - const char *devname, - struct qemuDomainDiskInfo *info) + virHashTablePtr table) { - int ret = 0; - bool found = false; + int ret; int i; virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("query-block", @@ -1389,6 +1387,7 @@ int qemuMonitorJSONGetBlockInfo(qemuMonitorPtr mon, for (i = 0; i < virJSONValueArraySize(devices); i++) { virJSONValuePtr dev = virJSONValueArrayGet(devices, i); + struct qemuDomainDiskInfo *info; const char *thisdev; if (!dev || dev->type != VIR_JSON_TYPE_OBJECT) { @@ -1406,10 +1405,16 @@ int qemuMonitorJSONGetBlockInfo(qemuMonitorPtr mon, if (STRPREFIX(thisdev, QEMU_DRIVE_HOST_PREFIX)) thisdev += strlen(QEMU_DRIVE_HOST_PREFIX); - if (STRNEQ(thisdev, devname)) - continue; + if (VIR_ALLOC(info) < 0) { + virReportOOMError(); + goto cleanup; + } + + if (virHashAddEntry(table, thisdev, info) < 0) { + VIR_FREE(info); + goto cleanup; + } - found = true; if (virJSONValueObjectGetBoolean(dev, "removable", &info->removable) < 0) { qemuReportError(VIR_ERR_INTERNAL_ERROR, _("cannot read %s value"), @@ -1429,15 +1434,6 @@ int qemuMonitorJSONGetBlockInfo(qemuMonitorPtr mon, */ ignore_value(virJSONValueObjectGetBoolean(dev, "tray-open", &info->tray_open)); - - break; - } - - if (!found) { - qemuReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot find info for device '%s'"), - devname); - goto cleanup; } ret = 0; diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index 5991790b82..d221e59661 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -63,8 +63,7 @@ int qemuMonitorJSONGetMemoryStats(qemuMonitorPtr mon, virDomainMemoryStatPtr stats, unsigned int nr_stats); int qemuMonitorJSONGetBlockInfo(qemuMonitorPtr mon, - const char *devname, - struct qemuDomainDiskInfo *info); + virHashTablePtr table); int qemuMonitorJSONGetBlockStatsInfo(qemuMonitorPtr mon, const char *dev_name, long long *rd_req, diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index 2c68be8efd..a33d192c2d 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -772,14 +772,14 @@ int qemuMonitorTextGetMemoryStats(qemuMonitorPtr mon, int qemuMonitorTextGetBlockInfo(qemuMonitorPtr mon, - const char *devname, - struct qemuDomainDiskInfo *info) + virHashTablePtr table) { + struct qemuDomainDiskInfo *info; char *reply = NULL; int ret = -1; char *dummy; - const char *p, *eol; - int devnamelen = strlen(devname); + char *p, *eol; + char *dev; int tmp; if (qemuMonitorHMPCommand(mon, "info block", &reply) < 0) { @@ -805,16 +805,22 @@ int qemuMonitorTextGetBlockInfo(qemuMonitorPtr mon, if (STRPREFIX(p, QEMU_DRIVE_HOST_PREFIX)) p += strlen(QEMU_DRIVE_HOST_PREFIX); - if (STREQLEN(p, devname, devnamelen) && - p[devnamelen] == ':' && p[devnamelen+1] == ' ') { + eol = strchr(p, '\n'); + if (!eol) + eol = p + strlen(p) - 1; - eol = strchr(p, '\n'); - if (!eol) - eol = p + strlen(p); + dev = p; + p = strchr(p, ':'); + if (p && p < eol && *(p + 1) == ' ') { + if (VIR_ALLOC(info) < 0) { + virReportOOMError(); + goto cleanup; + } - p += devnamelen + 2; /* Skip to first label. */ + *p = '\0'; + p += 2; - while (*p) { + while (p < eol) { if (STRPREFIX(p, "removable=")) { p += strlen("removable="); if (virStrToLong_i(p, &dummy, 10, &tmp) == -1) @@ -839,24 +845,25 @@ int qemuMonitorTextGetBlockInfo(qemuMonitorPtr mon, /* skip to next label */ p = strchr(p, ' '); - if (!p || p >= eol) break; + if (!p) + break; p++; } - ret = 0; - goto cleanup; + if (virHashAddEntry(table, dev, info) < 0) + goto cleanup; + else + info = NULL; } - /* skip to next line */ - p = strchr(p, '\n'); - if (!p) break; - p++; + /* skip to the next line */ + p = eol + 1; } - qemuReportError(VIR_ERR_INVALID_ARG, - _("no info for device '%s'"), devname); + ret = 0; cleanup: + VIR_FREE(info); VIR_FREE(reply); return ret; } diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h index 47a946d292..050c30e418 100644 --- a/src/qemu/qemu_monitor_text.h +++ b/src/qemu/qemu_monitor_text.h @@ -59,8 +59,7 @@ int qemuMonitorTextGetMemoryStats(qemuMonitorPtr mon, virDomainMemoryStatPtr stats, unsigned int nr_stats); int qemuMonitorTextGetBlockInfo(qemuMonitorPtr mon, - const char *devname, - struct qemuDomainDiskInfo *info); + virHashTablePtr table); int qemuMonitorTextGetBlockStatsInfo(qemuMonitorPtr mon, const char *dev_name, long long *rd_req,