diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index ea0c1c09513684b0ff348c927d3216a6f2b6ee2f..7a361789d9ec8cc1020f2a53bd6f4df134dc46ce 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -16083,7 +16083,7 @@ qemuDomainBlockPivot(virQEMUDriverPtr driver, { int ret = -1, rc; qemuDomainObjPrivatePtr priv = vm->privateData; - virDomainBlockJobInfo info; + qemuMonitorBlockJobInfo info; virStorageSourcePtr oldsrc = NULL; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); @@ -16097,7 +16097,7 @@ qemuDomainBlockPivot(virQEMUDriverPtr driver, /* Probe the status, if needed. */ if (!disk->mirrorState) { qemuDomainObjEnterMonitor(driver, vm); - rc = qemuMonitorBlockJobInfo(priv->mon, device, &info, NULL); + rc = qemuMonitorGetBlockJobInfo(priv->mon, disk->info.alias, &info); if (qemuDomainObjExitMonitor(driver, vm) < 0) goto cleanup; if (rc < 0) @@ -16430,16 +16430,16 @@ qemuDomainBlockJobAbort(virDomainPtr dom, static int -qemuDomainGetBlockJobInfo(virDomainPtr dom, const char *path, - virDomainBlockJobInfoPtr info, unsigned int flags) +qemuDomainGetBlockJobInfo(virDomainPtr dom, + const char *path, + virDomainBlockJobInfoPtr info, + unsigned int flags) { virQEMUDriverPtr driver = dom->conn->privateData; virDomainObjPtr vm; - char *device = NULL; - int idx; virDomainDiskDefPtr disk; int ret = -1; - unsigned long long bandwidth; + qemuMonitorBlockJobInfo rawInfo; virCheckFlags(VIR_DOMAIN_BLOCK_JOB_INFO_BANDWIDTH_BYTES, -1); @@ -16462,31 +16462,34 @@ qemuDomainGetBlockJobInfo(virDomainPtr dom, const char *path, if (qemuDomainSupportsBlockJobs(vm, NULL) < 0) goto endjob; - if (!(device = qemuDiskPathToAlias(vm, path, &idx))) + if (!(disk = virDomainDiskByName(vm->def, path, true))) goto endjob; - disk = vm->def->disks[idx]; qemuDomainObjEnterMonitor(driver, vm); - ret = qemuMonitorBlockJobInfo(qemuDomainGetMonitor(vm), device, info, - &bandwidth); + ret = qemuMonitorGetBlockJobInfo(qemuDomainGetMonitor(vm), + disk->info.alias, &rawInfo); if (qemuDomainObjExitMonitor(driver, vm) < 0) ret = -1; if (ret < 0) goto endjob; + info->cur = rawInfo.cur; + info->end = rawInfo.end; + + info->type = rawInfo.type; if (info->type == VIR_DOMAIN_BLOCK_JOB_TYPE_COMMIT && disk->mirrorJob == VIR_DOMAIN_BLOCK_JOB_TYPE_ACTIVE_COMMIT) info->type = disk->mirrorJob; - if (bandwidth) { - if (!(flags & VIR_DOMAIN_BLOCK_JOB_INFO_BANDWIDTH_BYTES)) - bandwidth = VIR_DIV_UP(bandwidth, 1024 * 1024); - info->bandwidth = bandwidth; - if (info->bandwidth != bandwidth) { - virReportError(VIR_ERR_OVERFLOW, - _("bandwidth %llu cannot be represented in result"), - bandwidth); - goto endjob; - } + + if (rawInfo.bandwidth && + !(flags & VIR_DOMAIN_BLOCK_JOB_INFO_BANDWIDTH_BYTES)) + rawInfo.bandwidth = VIR_DIV_UP(rawInfo.bandwidth, 1024 * 1024); + info->bandwidth = rawInfo.bandwidth; + if (info->bandwidth != rawInfo.bandwidth) { + virReportError(VIR_ERR_OVERFLOW, + _("bandwidth %llu cannot be represented in result"), + rawInfo.bandwidth); + goto endjob; } /* Snoop block copy operations, so future cancel operations can diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index e545740732409e7dbd149f4be4542c7631507fb9..451397053111622891569167c2a82a0ce46f34f4 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -3214,17 +3214,40 @@ qemuMonitorBlockJobSetSpeed(qemuMonitorPtr mon, } +virHashTablePtr +qemuMonitorGetAllBlockJobInfo(qemuMonitorPtr mon) +{ + QEMU_CHECK_MONITOR_JSON_NULL(mon); + return qemuMonitorJSONGetAllBlockJobInfo(mon); +} + + +/** + * qemuMonitorGetBlockJobInfo: + * Parse Block Job information, and populate info for the named device. + * Return 1 if info available, 0 if device has no block job, and -1 on error. + */ int -qemuMonitorBlockJobInfo(qemuMonitorPtr mon, - const char *device, - virDomainBlockJobInfoPtr info, - unsigned long long *bandwidth) +qemuMonitorGetBlockJobInfo(qemuMonitorPtr mon, + const char *alias, + qemuMonitorBlockJobInfoPtr info) { - VIR_DEBUG("device=%s, info=%p, bandwidth=%p", device, info, bandwidth); + virHashTablePtr all; + qemuMonitorBlockJobInfoPtr data; + int ret = 0; - QEMU_CHECK_MONITOR_JSON(mon); + VIR_DEBUG("alias=%s, info=%p", alias, info); + + if (!(all = qemuMonitorGetAllBlockJobInfo(mon))) + return -1; - return qemuMonitorJSONBlockJobInfo(mon, device, info, bandwidth); + if ((data = virHashLookup(all, alias))) { + *info = *data; + ret = 1; + } + + virHashFree(all); + return ret; } diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index d30b514e851570363d105061e72ce7c4759bd254..96f47e826bbd8a390eecf59d0d3f236567eb30ac 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -774,10 +774,19 @@ int qemuMonitorBlockJobSetSpeed(qemuMonitorPtr mon, unsigned long long bandwidth, bool modern); -int qemuMonitorBlockJobInfo(qemuMonitorPtr mon, - const char *device, - virDomainBlockJobInfoPtr info, - unsigned long long *bandwidth) +typedef struct _qemuMonitorBlockJobInfo qemuMonitorBlockJobInfo; +typedef qemuMonitorBlockJobInfo *qemuMonitorBlockJobInfoPtr; +struct _qemuMonitorBlockJobInfo { + int type; /* virDomainBlockJobType */ + unsigned long long bandwidth; /* in bytes/s */ + virDomainBlockJobCursor cur; + virDomainBlockJobCursor end; +}; + +virHashTablePtr qemuMonitorGetAllBlockJobInfo(qemuMonitorPtr mon); +int qemuMonitorGetBlockJobInfo(qemuMonitorPtr mon, + const char *device, + qemuMonitorBlockJobInfoPtr info) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); int qemuMonitorOpenGraphics(qemuMonitorPtr mon, diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 13c57d2cc4b8b760ecb518c2129e6d127d543bff..5b227cd151fe3bf00a7cafbdae2145092d5cd923 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -4124,29 +4124,30 @@ int qemuMonitorJSONScreendump(qemuMonitorPtr mon, return ret; } -/* Returns -1 on error, 0 if not the right device, 1 if info was - * populated. However, rather than populate info->bandwidth (which - * might overflow on 32-bit machines), bandwidth is tracked optionally - * on the side. */ + static int -qemuMonitorJSONGetBlockJobInfoOne(virJSONValuePtr entry, - const char *device, - virDomainBlockJobInfoPtr info, - unsigned long long *bandwidth) +qemuMonitorJSONParseBlockJobInfo(virHashTablePtr blockJobs, + virJSONValuePtr entry) { - const char *this_dev; + qemuMonitorBlockJobInfoPtr info = NULL; + const char *device; const char *type; - if ((this_dev = virJSONValueObjectGetString(entry, "device")) == NULL) { + if (!(device = virJSONValueObjectGetString(entry, "device"))) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("entry was missing 'device'")); return -1; } - if (!STREQ(this_dev, device)) - return 0; + if (STRPREFIX(device, QEMU_DRIVE_HOST_PREFIX)) + device += strlen(QEMU_DRIVE_HOST_PREFIX); - type = virJSONValueObjectGetString(entry, "type"); - if (!type) { + if (VIR_ALLOC(info) < 0 || + virHashAddEntry(blockJobs, device, info) < 0) { + VIR_FREE(info); + return -1; + } + + if (!(type = virJSONValueObjectGetString(entry, "type"))) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("entry was missing 'type'")); return -1; @@ -4160,8 +4161,7 @@ qemuMonitorJSONGetBlockJobInfoOne(virJSONValuePtr entry, else info->type = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN; - if (bandwidth && - virJSONValueObjectGetNumberUlong(entry, "speed", bandwidth) < 0) { + if (virJSONValueObjectGetNumberUlong(entry, "speed", &info->bandwidth) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("entry was missing 'speed'")); return -1; @@ -4178,30 +4178,23 @@ qemuMonitorJSONGetBlockJobInfoOne(virJSONValuePtr entry, _("entry was missing 'len'")); return -1; } - return 1; + + return 0; } -/** - * qemuMonitorJSONBlockJobInfo: - * Parse Block Job information, and populate info for the named device. - * Return 1 if info available, 0 if device has no block job, and -1 on error. - */ -int -qemuMonitorJSONBlockJobInfo(qemuMonitorPtr mon, - const char *device, - virDomainBlockJobInfoPtr info, - unsigned long long *bandwidth) +virHashTablePtr +qemuMonitorJSONGetAllBlockJobInfo(qemuMonitorPtr mon) { virJSONValuePtr cmd = NULL; virJSONValuePtr reply = NULL; virJSONValuePtr data; int nr_results; size_t i; - int ret = -1; + virHashTablePtr blockJobs = NULL; cmd = qemuMonitorJSONMakeCommand("query-block-jobs", NULL); if (!cmd) - return -1; + return NULL; if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0) goto cleanup; @@ -4223,22 +4216,29 @@ qemuMonitorJSONBlockJobInfo(qemuMonitorPtr mon, goto cleanup; } - for (i = ret = 0; i < nr_results && ret == 0; i++) { + if (!(blockJobs = virHashCreate(nr_results, virHashValueFree))) + goto cleanup; + + for (i = 0; i < nr_results; i++) { virJSONValuePtr entry = virJSONValueArrayGet(data, i); if (!entry) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("missing array element")); - ret = -1; - goto cleanup; + goto error; } - ret = qemuMonitorJSONGetBlockJobInfoOne(entry, device, info, - bandwidth); + if (qemuMonitorJSONParseBlockJobInfo(blockJobs, entry) < 0) + goto error; } cleanup: virJSONValueFree(cmd); virJSONValueFree(reply); - return ret; + return blockJobs; + + error: + virHashFree(blockJobs); + blockJobs = NULL; + goto cleanup; } diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index fb77930cd8fed25e64df9c547034d97dc51a2bf9..c0ee4ce8951897ecef87188093efb3a089a3ec05 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -316,11 +316,8 @@ int qemuMonitorJSONBlockJobSetSpeed(qemuMonitorPtr mon, bool modern) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); -int qemuMonitorJSONBlockJobInfo(qemuMonitorPtr mon, - const char *device, - virDomainBlockJobInfoPtr info, - unsigned long long *bandwidth) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); +virHashTablePtr qemuMonitorJSONGetAllBlockJobInfo(qemuMonitorPtr mon) + ATTRIBUTE_NONNULL(1); int qemuMonitorJSONSetLink(qemuMonitorPtr mon, const char *name,