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;
}
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,
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,
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",
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) {
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"),
*/
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;
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,
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) {
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)
/* 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;
}
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,