提交 3a18bd2d 编写于 作者: J Jiri Denemark

qemu: Refactor qemuMonitorBlockJobInfo

"query-block-jobs" QMP command returns all running block jobs at once,
while qemuMonitorBlockJobInfo would only report one. This is not very
nice in case we need to check several block jobs. This patch refactors
the monitor code to always parse all block jobs and store them in a
hash.
Signed-off-by: NJiri Denemark <jdenemar@redhat.com>
上级 40cd0290
...@@ -16083,7 +16083,7 @@ qemuDomainBlockPivot(virQEMUDriverPtr driver, ...@@ -16083,7 +16083,7 @@ qemuDomainBlockPivot(virQEMUDriverPtr driver,
{ {
int ret = -1, rc; int ret = -1, rc;
qemuDomainObjPrivatePtr priv = vm->privateData; qemuDomainObjPrivatePtr priv = vm->privateData;
virDomainBlockJobInfo info; qemuMonitorBlockJobInfo info;
virStorageSourcePtr oldsrc = NULL; virStorageSourcePtr oldsrc = NULL;
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
...@@ -16097,7 +16097,7 @@ qemuDomainBlockPivot(virQEMUDriverPtr driver, ...@@ -16097,7 +16097,7 @@ qemuDomainBlockPivot(virQEMUDriverPtr driver,
/* Probe the status, if needed. */ /* Probe the status, if needed. */
if (!disk->mirrorState) { if (!disk->mirrorState) {
qemuDomainObjEnterMonitor(driver, vm); qemuDomainObjEnterMonitor(driver, vm);
rc = qemuMonitorBlockJobInfo(priv->mon, device, &info, NULL); rc = qemuMonitorGetBlockJobInfo(priv->mon, disk->info.alias, &info);
if (qemuDomainObjExitMonitor(driver, vm) < 0) if (qemuDomainObjExitMonitor(driver, vm) < 0)
goto cleanup; goto cleanup;
if (rc < 0) if (rc < 0)
...@@ -16430,16 +16430,16 @@ qemuDomainBlockJobAbort(virDomainPtr dom, ...@@ -16430,16 +16430,16 @@ qemuDomainBlockJobAbort(virDomainPtr dom,
static int static int
qemuDomainGetBlockJobInfo(virDomainPtr dom, const char *path, qemuDomainGetBlockJobInfo(virDomainPtr dom,
virDomainBlockJobInfoPtr info, unsigned int flags) const char *path,
virDomainBlockJobInfoPtr info,
unsigned int flags)
{ {
virQEMUDriverPtr driver = dom->conn->privateData; virQEMUDriverPtr driver = dom->conn->privateData;
virDomainObjPtr vm; virDomainObjPtr vm;
char *device = NULL;
int idx;
virDomainDiskDefPtr disk; virDomainDiskDefPtr disk;
int ret = -1; int ret = -1;
unsigned long long bandwidth; qemuMonitorBlockJobInfo rawInfo;
virCheckFlags(VIR_DOMAIN_BLOCK_JOB_INFO_BANDWIDTH_BYTES, -1); virCheckFlags(VIR_DOMAIN_BLOCK_JOB_INFO_BANDWIDTH_BYTES, -1);
...@@ -16462,31 +16462,34 @@ qemuDomainGetBlockJobInfo(virDomainPtr dom, const char *path, ...@@ -16462,31 +16462,34 @@ qemuDomainGetBlockJobInfo(virDomainPtr dom, const char *path,
if (qemuDomainSupportsBlockJobs(vm, NULL) < 0) if (qemuDomainSupportsBlockJobs(vm, NULL) < 0)
goto endjob; goto endjob;
if (!(device = qemuDiskPathToAlias(vm, path, &idx))) if (!(disk = virDomainDiskByName(vm->def, path, true)))
goto endjob; goto endjob;
disk = vm->def->disks[idx];
qemuDomainObjEnterMonitor(driver, vm); qemuDomainObjEnterMonitor(driver, vm);
ret = qemuMonitorBlockJobInfo(qemuDomainGetMonitor(vm), device, info, ret = qemuMonitorGetBlockJobInfo(qemuDomainGetMonitor(vm),
&bandwidth); disk->info.alias, &rawInfo);
if (qemuDomainObjExitMonitor(driver, vm) < 0) if (qemuDomainObjExitMonitor(driver, vm) < 0)
ret = -1; ret = -1;
if (ret < 0) if (ret < 0)
goto endjob; goto endjob;
info->cur = rawInfo.cur;
info->end = rawInfo.end;
info->type = rawInfo.type;
if (info->type == VIR_DOMAIN_BLOCK_JOB_TYPE_COMMIT && if (info->type == VIR_DOMAIN_BLOCK_JOB_TYPE_COMMIT &&
disk->mirrorJob == VIR_DOMAIN_BLOCK_JOB_TYPE_ACTIVE_COMMIT) disk->mirrorJob == VIR_DOMAIN_BLOCK_JOB_TYPE_ACTIVE_COMMIT)
info->type = disk->mirrorJob; info->type = disk->mirrorJob;
if (bandwidth) {
if (!(flags & VIR_DOMAIN_BLOCK_JOB_INFO_BANDWIDTH_BYTES)) if (rawInfo.bandwidth &&
bandwidth = VIR_DIV_UP(bandwidth, 1024 * 1024); !(flags & VIR_DOMAIN_BLOCK_JOB_INFO_BANDWIDTH_BYTES))
info->bandwidth = bandwidth; rawInfo.bandwidth = VIR_DIV_UP(rawInfo.bandwidth, 1024 * 1024);
if (info->bandwidth != bandwidth) { info->bandwidth = rawInfo.bandwidth;
virReportError(VIR_ERR_OVERFLOW, if (info->bandwidth != rawInfo.bandwidth) {
_("bandwidth %llu cannot be represented in result"), virReportError(VIR_ERR_OVERFLOW,
bandwidth); _("bandwidth %llu cannot be represented in result"),
goto endjob; rawInfo.bandwidth);
} goto endjob;
} }
/* Snoop block copy operations, so future cancel operations can /* Snoop block copy operations, so future cancel operations can
......
...@@ -3214,17 +3214,40 @@ qemuMonitorBlockJobSetSpeed(qemuMonitorPtr mon, ...@@ -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 int
qemuMonitorBlockJobInfo(qemuMonitorPtr mon, qemuMonitorGetBlockJobInfo(qemuMonitorPtr mon,
const char *device, const char *alias,
virDomainBlockJobInfoPtr info, qemuMonitorBlockJobInfoPtr info)
unsigned long long *bandwidth)
{ {
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;
} }
......
...@@ -774,10 +774,19 @@ int qemuMonitorBlockJobSetSpeed(qemuMonitorPtr mon, ...@@ -774,10 +774,19 @@ int qemuMonitorBlockJobSetSpeed(qemuMonitorPtr mon,
unsigned long long bandwidth, unsigned long long bandwidth,
bool modern); bool modern);
int qemuMonitorBlockJobInfo(qemuMonitorPtr mon, typedef struct _qemuMonitorBlockJobInfo qemuMonitorBlockJobInfo;
const char *device, typedef qemuMonitorBlockJobInfo *qemuMonitorBlockJobInfoPtr;
virDomainBlockJobInfoPtr info, struct _qemuMonitorBlockJobInfo {
unsigned long long *bandwidth) 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); ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
int qemuMonitorOpenGraphics(qemuMonitorPtr mon, int qemuMonitorOpenGraphics(qemuMonitorPtr mon,
......
...@@ -4124,29 +4124,30 @@ int qemuMonitorJSONScreendump(qemuMonitorPtr mon, ...@@ -4124,29 +4124,30 @@ int qemuMonitorJSONScreendump(qemuMonitorPtr mon,
return ret; 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 static int
qemuMonitorJSONGetBlockJobInfoOne(virJSONValuePtr entry, qemuMonitorJSONParseBlockJobInfo(virHashTablePtr blockJobs,
const char *device, virJSONValuePtr entry)
virDomainBlockJobInfoPtr info,
unsigned long long *bandwidth)
{ {
const char *this_dev; qemuMonitorBlockJobInfoPtr info = NULL;
const char *device;
const char *type; const char *type;
if ((this_dev = virJSONValueObjectGetString(entry, "device")) == NULL) { if (!(device = virJSONValueObjectGetString(entry, "device"))) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("entry was missing 'device'")); _("entry was missing 'device'"));
return -1; return -1;
} }
if (!STREQ(this_dev, device)) if (STRPREFIX(device, QEMU_DRIVE_HOST_PREFIX))
return 0; device += strlen(QEMU_DRIVE_HOST_PREFIX);
type = virJSONValueObjectGetString(entry, "type"); if (VIR_ALLOC(info) < 0 ||
if (!type) { virHashAddEntry(blockJobs, device, info) < 0) {
VIR_FREE(info);
return -1;
}
if (!(type = virJSONValueObjectGetString(entry, "type"))) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("entry was missing 'type'")); _("entry was missing 'type'"));
return -1; return -1;
...@@ -4160,8 +4161,7 @@ qemuMonitorJSONGetBlockJobInfoOne(virJSONValuePtr entry, ...@@ -4160,8 +4161,7 @@ qemuMonitorJSONGetBlockJobInfoOne(virJSONValuePtr entry,
else else
info->type = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN; info->type = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN;
if (bandwidth && if (virJSONValueObjectGetNumberUlong(entry, "speed", &info->bandwidth) < 0) {
virJSONValueObjectGetNumberUlong(entry, "speed", bandwidth) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("entry was missing 'speed'")); _("entry was missing 'speed'"));
return -1; return -1;
...@@ -4178,30 +4178,23 @@ qemuMonitorJSONGetBlockJobInfoOne(virJSONValuePtr entry, ...@@ -4178,30 +4178,23 @@ qemuMonitorJSONGetBlockJobInfoOne(virJSONValuePtr entry,
_("entry was missing 'len'")); _("entry was missing 'len'"));
return -1; return -1;
} }
return 1;
return 0;
} }
/** virHashTablePtr
* qemuMonitorJSONBlockJobInfo: qemuMonitorJSONGetAllBlockJobInfo(qemuMonitorPtr mon)
* 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)
{ {
virJSONValuePtr cmd = NULL; virJSONValuePtr cmd = NULL;
virJSONValuePtr reply = NULL; virJSONValuePtr reply = NULL;
virJSONValuePtr data; virJSONValuePtr data;
int nr_results; int nr_results;
size_t i; size_t i;
int ret = -1; virHashTablePtr blockJobs = NULL;
cmd = qemuMonitorJSONMakeCommand("query-block-jobs", NULL); cmd = qemuMonitorJSONMakeCommand("query-block-jobs", NULL);
if (!cmd) if (!cmd)
return -1; return NULL;
if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0) if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
goto cleanup; goto cleanup;
...@@ -4223,22 +4216,29 @@ qemuMonitorJSONBlockJobInfo(qemuMonitorPtr mon, ...@@ -4223,22 +4216,29 @@ qemuMonitorJSONBlockJobInfo(qemuMonitorPtr mon,
goto cleanup; 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); virJSONValuePtr entry = virJSONValueArrayGet(data, i);
if (!entry) { if (!entry) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("missing array element")); _("missing array element"));
ret = -1; goto error;
goto cleanup;
} }
ret = qemuMonitorJSONGetBlockJobInfoOne(entry, device, info, if (qemuMonitorJSONParseBlockJobInfo(blockJobs, entry) < 0)
bandwidth); goto error;
} }
cleanup: cleanup:
virJSONValueFree(cmd); virJSONValueFree(cmd);
virJSONValueFree(reply); virJSONValueFree(reply);
return ret; return blockJobs;
error:
virHashFree(blockJobs);
blockJobs = NULL;
goto cleanup;
} }
......
...@@ -316,11 +316,8 @@ int qemuMonitorJSONBlockJobSetSpeed(qemuMonitorPtr mon, ...@@ -316,11 +316,8 @@ int qemuMonitorJSONBlockJobSetSpeed(qemuMonitorPtr mon,
bool modern) bool modern)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
int qemuMonitorJSONBlockJobInfo(qemuMonitorPtr mon, virHashTablePtr qemuMonitorJSONGetAllBlockJobInfo(qemuMonitorPtr mon)
const char *device, ATTRIBUTE_NONNULL(1);
virDomainBlockJobInfoPtr info,
unsigned long long *bandwidth)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
int qemuMonitorJSONSetLink(qemuMonitorPtr mon, int qemuMonitorJSONSetLink(qemuMonitorPtr mon,
const char *name, const char *name,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册