mirror of
https://github.com/libvirt/libvirt.git
synced 2025-02-25 18:55:26 -06:00
blockjob: split out block info monitor handling
Another layer of overly-multiplexed code that deserves to be
split into obviously separate paths for query vs. modify.
This continues the cleanup started in commit cefe0ba
.
In the process, make some tweaks to simplify the logic when
parsing the JSON reply. There should be no user-visible
semantic changes.
* src/qemu/qemu_monitor.h (qemuMonitorBlockJob): Drop parameter.
(qemuMonitorBlockJobInfo): New prototype.
(BLOCK_JOB_INFO): Drop enum.
* src/qemu/qemu_monitor_json.h (qemuMonitorJSONBlockJob)
(qemuMonitorJSONBlockJobInfo): Likewise.
* src/qemu/qemu_monitor.c (qemuMonitorBlockJob): Split...
(qemuMonitorBlockJobInfo): ...into second function.
* src/qemu/qemu_monitor_json.c (qemuMonitorJSONBlockJob): Move
block info portions...
(qemuMonitorJSONGetBlockJobInfo): ...here, and rename...
(qemuMonitorJSONBlockJobInfo): ...and export.
(qemuMonitorJSONGetBlockJobInfoOne): Alter return semantics.
* src/qemu/qemu_driver.c (qemuDomainBlockPivot)
(qemuDomainBlockJobImpl, qemuDomainGetBlockJobInfo): Adjust
callers.
* src/qemu/qemu_migration.c (qemuMigrationDriveMirror)
(qemuMigrationCancelDriveMirror): Likewise.
Signed-off-by: Eric Blake <eblake@redhat.com>
This commit is contained in:
parent
de0aeafe9c
commit
ced813652b
@ -14857,8 +14857,7 @@ qemuDomainBlockPivot(virConnectPtr conn,
|
||||
/* Probe the status, if needed. */
|
||||
if (!disk->mirrorState) {
|
||||
qemuDomainObjEnterMonitor(driver, vm);
|
||||
rc = qemuMonitorBlockJob(priv->mon, device, NULL, NULL, 0, &info,
|
||||
BLOCK_JOB_INFO, true);
|
||||
rc = qemuMonitorBlockJobInfo(priv->mon, device, &info);
|
||||
qemuDomainObjExitMonitor(driver, vm);
|
||||
if (rc < 0)
|
||||
goto cleanup;
|
||||
@ -15125,7 +15124,7 @@ qemuDomainBlockJobImpl(virDomainObjPtr vm,
|
||||
|
||||
qemuDomainObjEnterMonitor(driver, vm);
|
||||
ret = qemuMonitorBlockJob(priv->mon, device, basePath, backingPath,
|
||||
bandwidth, NULL, mode, async);
|
||||
bandwidth, mode, async);
|
||||
qemuDomainObjExitMonitor(driver, vm);
|
||||
if (ret < 0) {
|
||||
if (mode == BLOCK_JOB_ABORT && disk->mirror)
|
||||
@ -15169,8 +15168,7 @@ qemuDomainBlockJobImpl(virDomainObjPtr vm,
|
||||
virDomainBlockJobInfo dummy;
|
||||
|
||||
qemuDomainObjEnterMonitor(driver, vm);
|
||||
ret = qemuMonitorBlockJob(priv->mon, device, NULL, NULL, 0,
|
||||
&dummy, BLOCK_JOB_INFO, async);
|
||||
ret = qemuMonitorBlockJobInfo(priv->mon, device, &dummy);
|
||||
qemuDomainObjExitMonitor(driver, vm);
|
||||
|
||||
if (ret <= 0)
|
||||
@ -15277,8 +15275,7 @@ qemuDomainGetBlockJobInfo(virDomainPtr dom, const char *path,
|
||||
disk = vm->def->disks[idx];
|
||||
|
||||
qemuDomainObjEnterMonitor(driver, vm);
|
||||
ret = qemuMonitorBlockJob(priv->mon, device, NULL, NULL, 0,
|
||||
info, BLOCK_JOB_INFO, true);
|
||||
ret = qemuMonitorBlockJobInfo(priv->mon, device, info);
|
||||
qemuDomainObjExitMonitor(driver, vm);
|
||||
if (ret < 0)
|
||||
goto endjob;
|
||||
|
@ -1307,8 +1307,7 @@ qemuMigrationDriveMirror(virQEMUDriverPtr driver,
|
||||
_("canceled by client"));
|
||||
goto error;
|
||||
}
|
||||
mon_ret = qemuMonitorBlockJob(priv->mon, diskAlias, NULL, NULL, 0,
|
||||
&info, BLOCK_JOB_INFO, true);
|
||||
mon_ret = qemuMonitorBlockJobInfo(priv->mon, diskAlias, &info);
|
||||
qemuDomainObjExitMonitor(driver, vm);
|
||||
|
||||
if (mon_ret < 0)
|
||||
@ -1361,7 +1360,7 @@ qemuMigrationDriveMirror(virQEMUDriverPtr driver,
|
||||
if (qemuDomainObjEnterMonitorAsync(driver, vm,
|
||||
QEMU_ASYNC_JOB_MIGRATION_OUT) == 0) {
|
||||
if (qemuMonitorBlockJob(priv->mon, diskAlias, NULL, NULL, 0,
|
||||
NULL, BLOCK_JOB_ABORT, true) < 0) {
|
||||
BLOCK_JOB_ABORT, true) < 0) {
|
||||
VIR_WARN("Unable to cancel block-job on '%s'", diskAlias);
|
||||
}
|
||||
qemuDomainObjExitMonitor(driver, vm);
|
||||
@ -1428,7 +1427,7 @@ qemuMigrationCancelDriveMirror(qemuMigrationCookiePtr mig,
|
||||
goto cleanup;
|
||||
|
||||
if (qemuMonitorBlockJob(priv->mon, diskAlias, NULL, NULL, 0,
|
||||
NULL, BLOCK_JOB_ABORT, true) < 0)
|
||||
BLOCK_JOB_ABORT, true) < 0)
|
||||
VIR_WARN("Unable to stop block job on %s", diskAlias);
|
||||
qemuDomainObjExitMonitor(driver, vm);
|
||||
}
|
||||
|
@ -3360,22 +3360,22 @@ int qemuMonitorScreendump(qemuMonitorPtr mon,
|
||||
}
|
||||
|
||||
/* bandwidth is in MiB/sec */
|
||||
int qemuMonitorBlockJob(qemuMonitorPtr mon,
|
||||
const char *device,
|
||||
const char *base,
|
||||
const char *backingName,
|
||||
unsigned long bandwidth,
|
||||
virDomainBlockJobInfoPtr info,
|
||||
qemuMonitorBlockJobCmd mode,
|
||||
bool modern)
|
||||
int
|
||||
qemuMonitorBlockJob(qemuMonitorPtr mon,
|
||||
const char *device,
|
||||
const char *base,
|
||||
const char *backingName,
|
||||
unsigned long bandwidth,
|
||||
qemuMonitorBlockJobCmd mode,
|
||||
bool modern)
|
||||
{
|
||||
int ret = -1;
|
||||
unsigned long long speed;
|
||||
|
||||
VIR_DEBUG("mon=%p, device=%s, base=%s, backingName=%s, bandwidth=%luM, "
|
||||
"info=%p, mode=%o, modern=%d",
|
||||
"mode=%o, modern=%d",
|
||||
mon, device, NULLSTR(base), NULLSTR(backingName),
|
||||
bandwidth, info, mode, modern);
|
||||
bandwidth, mode, modern);
|
||||
|
||||
/* Convert bandwidth MiB to bytes - unfortunately the JSON QMP protocol is
|
||||
* limited to LLONG_MAX also for unsigned values */
|
||||
@ -3390,13 +3390,32 @@ int qemuMonitorBlockJob(qemuMonitorPtr mon,
|
||||
|
||||
if (mon->json)
|
||||
ret = qemuMonitorJSONBlockJob(mon, device, base, backingName,
|
||||
speed, info, mode, modern);
|
||||
speed, mode, modern);
|
||||
else
|
||||
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
||||
_("block jobs require JSON monitor"));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
qemuMonitorBlockJobInfo(qemuMonitorPtr mon,
|
||||
const char *device,
|
||||
virDomainBlockJobInfoPtr info)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
VIR_DEBUG("mon=%p, device=%s, info=%p", mon, device, info);
|
||||
|
||||
if (mon->json)
|
||||
ret = qemuMonitorJSONBlockJobInfo(mon, device, info);
|
||||
else
|
||||
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
||||
_("block jobs require JSON monitor"));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int qemuMonitorSetBlockIoThrottle(qemuMonitorPtr mon,
|
||||
const char *device,
|
||||
virDomainBlockIoTuneInfoPtr info)
|
||||
|
@ -685,7 +685,6 @@ int qemuMonitorSendKey(qemuMonitorPtr mon,
|
||||
|
||||
typedef enum {
|
||||
BLOCK_JOB_ABORT,
|
||||
BLOCK_JOB_INFO,
|
||||
BLOCK_JOB_SPEED,
|
||||
BLOCK_JOB_PULL,
|
||||
} qemuMonitorBlockJobCmd;
|
||||
@ -695,11 +694,15 @@ int qemuMonitorBlockJob(qemuMonitorPtr mon,
|
||||
const char *base,
|
||||
const char *backingName,
|
||||
unsigned long bandwidth,
|
||||
virDomainBlockJobInfoPtr info,
|
||||
qemuMonitorBlockJobCmd mode,
|
||||
bool modern)
|
||||
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
|
||||
|
||||
int qemuMonitorBlockJobInfo(qemuMonitorPtr mon,
|
||||
const char *device,
|
||||
virDomainBlockJobInfoPtr info)
|
||||
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
|
||||
|
||||
int qemuMonitorOpenGraphics(qemuMonitorPtr mon,
|
||||
const char *protocol,
|
||||
int fd,
|
||||
|
@ -3684,9 +3684,11 @@ int qemuMonitorJSONScreendump(qemuMonitorPtr mon,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qemuMonitorJSONGetBlockJobInfoOne(virJSONValuePtr entry,
|
||||
const char *device,
|
||||
virDomainBlockJobInfoPtr info)
|
||||
/* Returns -1 on error, 0 if not the right device, 1 if info was populated. */
|
||||
static int
|
||||
qemuMonitorJSONGetBlockJobInfoOne(virJSONValuePtr entry,
|
||||
const char *device,
|
||||
virDomainBlockJobInfoPtr info)
|
||||
{
|
||||
const char *this_dev;
|
||||
const char *type;
|
||||
@ -3698,7 +3700,7 @@ static int qemuMonitorJSONGetBlockJobInfoOne(virJSONValuePtr entry,
|
||||
return -1;
|
||||
}
|
||||
if (!STREQ(this_dev, device))
|
||||
return -1;
|
||||
return 0;
|
||||
|
||||
type = virJSONValueObjectGetString(entry, "type");
|
||||
if (!type) {
|
||||
@ -3733,54 +3735,65 @@ static int qemuMonitorJSONGetBlockJobInfoOne(virJSONValuePtr entry,
|
||||
_("entry was missing 'len'"));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** qemuMonitorJSONGetBlockJobInfo:
|
||||
* Parse Block Job information.
|
||||
* The reply is a JSON array of objects, one per active job.
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
static int qemuMonitorJSONGetBlockJobInfo(virJSONValuePtr reply,
|
||||
const char *device,
|
||||
virDomainBlockJobInfoPtr info)
|
||||
int
|
||||
qemuMonitorJSONBlockJobInfo(qemuMonitorPtr mon,
|
||||
const char *device,
|
||||
virDomainBlockJobInfoPtr info)
|
||||
{
|
||||
virJSONValuePtr cmd = NULL;
|
||||
virJSONValuePtr reply = NULL;
|
||||
virJSONValuePtr data;
|
||||
int nr_results;
|
||||
size_t i;
|
||||
int ret = -1;
|
||||
|
||||
if (!info)
|
||||
cmd = qemuMonitorJSONMakeCommand("query-block-jobs", NULL);
|
||||
if (!cmd)
|
||||
return -1;
|
||||
if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if ((data = virJSONValueObjectGet(reply, "return")) == NULL) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("reply was missing return data"));
|
||||
return -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (data->type != VIR_JSON_TYPE_ARRAY) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("unrecognized format of block job information"));
|
||||
return -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ((nr_results = virJSONValueArraySize(data)) < 0) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("unable to determine array size"));
|
||||
return -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
for (i = 0; i < nr_results; i++) {
|
||||
for (i = ret = 0; i < nr_results && ret == 0; i++) {
|
||||
virJSONValuePtr entry = virJSONValueArrayGet(data, i);
|
||||
if (!entry) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("missing array element"));
|
||||
return -1;
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
if (qemuMonitorJSONGetBlockJobInfoOne(entry, device, info) == 0)
|
||||
return 1;
|
||||
ret = qemuMonitorJSONGetBlockJobInfoOne(entry, device, info);
|
||||
}
|
||||
|
||||
return 0;
|
||||
cleanup:
|
||||
virJSONValueFree(cmd);
|
||||
virJSONValueFree(reply);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@ -3791,7 +3804,6 @@ qemuMonitorJSONBlockJob(qemuMonitorPtr mon,
|
||||
const char *base,
|
||||
const char *backingName,
|
||||
unsigned long long speed,
|
||||
virDomainBlockJobInfoPtr info,
|
||||
qemuMonitorBlockJobCmd mode,
|
||||
bool modern)
|
||||
{
|
||||
@ -3833,11 +3845,6 @@ qemuMonitorJSONBlockJob(qemuMonitorPtr mon,
|
||||
NULL);
|
||||
break;
|
||||
|
||||
case BLOCK_JOB_INFO:
|
||||
cmd_name = "query-block-jobs";
|
||||
cmd = qemuMonitorJSONMakeCommand(cmd_name, NULL);
|
||||
break;
|
||||
|
||||
case BLOCK_JOB_SPEED:
|
||||
cmd_name = modern ? "block-job-set-speed" : "block_job_set_speed";
|
||||
cmd = qemuMonitorJSONMakeCommand(cmd_name,
|
||||
@ -3888,9 +3895,6 @@ qemuMonitorJSONBlockJob(qemuMonitorPtr mon,
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == 0 && mode == BLOCK_JOB_INFO)
|
||||
ret = qemuMonitorJSONGetBlockJobInfo(reply, device, info);
|
||||
|
||||
virJSONValueFree(cmd);
|
||||
virJSONValueFree(reply);
|
||||
return ret;
|
||||
|
@ -285,11 +285,15 @@ int qemuMonitorJSONBlockJob(qemuMonitorPtr mon,
|
||||
const char *base,
|
||||
const char *backingName,
|
||||
unsigned long long speed,
|
||||
virDomainBlockJobInfoPtr info,
|
||||
qemuMonitorBlockJobCmd mode,
|
||||
bool modern)
|
||||
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
|
||||
|
||||
int qemuMonitorJSONBlockJobInfo(qemuMonitorPtr mon,
|
||||
const char *device,
|
||||
virDomainBlockJobInfoPtr info)
|
||||
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
|
||||
|
||||
int qemuMonitorJSONSetLink(qemuMonitorPtr mon,
|
||||
const char *name,
|
||||
virDomainNetInterfaceLinkState state);
|
||||
|
Loading…
Reference in New Issue
Block a user