mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-07 17:28:15 +00:00
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: Jiri Denemark <jdenemar@redhat.com>
This commit is contained in:
parent
40cd0290dc
commit
3a18bd2d7a
@ -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
|
||||
|
@ -3214,17 +3214,40 @@ qemuMonitorBlockJobSetSpeed(qemuMonitorPtr mon,
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
qemuMonitorBlockJobInfo(qemuMonitorPtr mon,
|
||||
const char *device,
|
||||
virDomainBlockJobInfoPtr info,
|
||||
unsigned long long *bandwidth)
|
||||
virHashTablePtr
|
||||
qemuMonitorGetAllBlockJobInfo(qemuMonitorPtr mon)
|
||||
{
|
||||
VIR_DEBUG("device=%s, info=%p, bandwidth=%p", device, info, bandwidth);
|
||||
QEMU_CHECK_MONITOR_JSON_NULL(mon);
|
||||
return qemuMonitorJSONGetAllBlockJobInfo(mon);
|
||||
}
|
||||
|
||||
QEMU_CHECK_MONITOR_JSON(mon);
|
||||
|
||||
return qemuMonitorJSONBlockJobInfo(mon, device, info, bandwidth);
|
||||
/**
|
||||
* 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
|
||||
qemuMonitorGetBlockJobInfo(qemuMonitorPtr mon,
|
||||
const char *alias,
|
||||
qemuMonitorBlockJobInfoPtr info)
|
||||
{
|
||||
virHashTablePtr all;
|
||||
qemuMonitorBlockJobInfoPtr data;
|
||||
int ret = 0;
|
||||
|
||||
VIR_DEBUG("alias=%s, info=%p", alias, info);
|
||||
|
||||
if (!(all = qemuMonitorGetAllBlockJobInfo(mon)))
|
||||
return -1;
|
||||
|
||||
if ((data = virHashLookup(all, alias))) {
|
||||
*info = *data;
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
virHashFree(all);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user