mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-07 17:28:15 +00: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. */
|
/* Probe the status, if needed. */
|
||||||
if (!disk->mirrorState) {
|
if (!disk->mirrorState) {
|
||||||
qemuDomainObjEnterMonitor(driver, vm);
|
qemuDomainObjEnterMonitor(driver, vm);
|
||||||
rc = qemuMonitorBlockJob(priv->mon, device, NULL, NULL, 0, &info,
|
rc = qemuMonitorBlockJobInfo(priv->mon, device, &info);
|
||||||
BLOCK_JOB_INFO, true);
|
|
||||||
qemuDomainObjExitMonitor(driver, vm);
|
qemuDomainObjExitMonitor(driver, vm);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@ -15125,7 +15124,7 @@ qemuDomainBlockJobImpl(virDomainObjPtr vm,
|
|||||||
|
|
||||||
qemuDomainObjEnterMonitor(driver, vm);
|
qemuDomainObjEnterMonitor(driver, vm);
|
||||||
ret = qemuMonitorBlockJob(priv->mon, device, basePath, backingPath,
|
ret = qemuMonitorBlockJob(priv->mon, device, basePath, backingPath,
|
||||||
bandwidth, NULL, mode, async);
|
bandwidth, mode, async);
|
||||||
qemuDomainObjExitMonitor(driver, vm);
|
qemuDomainObjExitMonitor(driver, vm);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
if (mode == BLOCK_JOB_ABORT && disk->mirror)
|
if (mode == BLOCK_JOB_ABORT && disk->mirror)
|
||||||
@ -15169,8 +15168,7 @@ qemuDomainBlockJobImpl(virDomainObjPtr vm,
|
|||||||
virDomainBlockJobInfo dummy;
|
virDomainBlockJobInfo dummy;
|
||||||
|
|
||||||
qemuDomainObjEnterMonitor(driver, vm);
|
qemuDomainObjEnterMonitor(driver, vm);
|
||||||
ret = qemuMonitorBlockJob(priv->mon, device, NULL, NULL, 0,
|
ret = qemuMonitorBlockJobInfo(priv->mon, device, &dummy);
|
||||||
&dummy, BLOCK_JOB_INFO, async);
|
|
||||||
qemuDomainObjExitMonitor(driver, vm);
|
qemuDomainObjExitMonitor(driver, vm);
|
||||||
|
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
@ -15277,8 +15275,7 @@ qemuDomainGetBlockJobInfo(virDomainPtr dom, const char *path,
|
|||||||
disk = vm->def->disks[idx];
|
disk = vm->def->disks[idx];
|
||||||
|
|
||||||
qemuDomainObjEnterMonitor(driver, vm);
|
qemuDomainObjEnterMonitor(driver, vm);
|
||||||
ret = qemuMonitorBlockJob(priv->mon, device, NULL, NULL, 0,
|
ret = qemuMonitorBlockJobInfo(priv->mon, device, info);
|
||||||
info, BLOCK_JOB_INFO, true);
|
|
||||||
qemuDomainObjExitMonitor(driver, vm);
|
qemuDomainObjExitMonitor(driver, vm);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto endjob;
|
goto endjob;
|
||||||
|
@ -1307,8 +1307,7 @@ qemuMigrationDriveMirror(virQEMUDriverPtr driver,
|
|||||||
_("canceled by client"));
|
_("canceled by client"));
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
mon_ret = qemuMonitorBlockJob(priv->mon, diskAlias, NULL, NULL, 0,
|
mon_ret = qemuMonitorBlockJobInfo(priv->mon, diskAlias, &info);
|
||||||
&info, BLOCK_JOB_INFO, true);
|
|
||||||
qemuDomainObjExitMonitor(driver, vm);
|
qemuDomainObjExitMonitor(driver, vm);
|
||||||
|
|
||||||
if (mon_ret < 0)
|
if (mon_ret < 0)
|
||||||
@ -1361,7 +1360,7 @@ qemuMigrationDriveMirror(virQEMUDriverPtr driver,
|
|||||||
if (qemuDomainObjEnterMonitorAsync(driver, vm,
|
if (qemuDomainObjEnterMonitorAsync(driver, vm,
|
||||||
QEMU_ASYNC_JOB_MIGRATION_OUT) == 0) {
|
QEMU_ASYNC_JOB_MIGRATION_OUT) == 0) {
|
||||||
if (qemuMonitorBlockJob(priv->mon, diskAlias, NULL, NULL, 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);
|
VIR_WARN("Unable to cancel block-job on '%s'", diskAlias);
|
||||||
}
|
}
|
||||||
qemuDomainObjExitMonitor(driver, vm);
|
qemuDomainObjExitMonitor(driver, vm);
|
||||||
@ -1428,7 +1427,7 @@ qemuMigrationCancelDriveMirror(qemuMigrationCookiePtr mig,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if (qemuMonitorBlockJob(priv->mon, diskAlias, NULL, NULL, 0,
|
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);
|
VIR_WARN("Unable to stop block job on %s", diskAlias);
|
||||||
qemuDomainObjExitMonitor(driver, vm);
|
qemuDomainObjExitMonitor(driver, vm);
|
||||||
}
|
}
|
||||||
|
@ -3360,22 +3360,22 @@ int qemuMonitorScreendump(qemuMonitorPtr mon,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* bandwidth is in MiB/sec */
|
/* bandwidth is in MiB/sec */
|
||||||
int qemuMonitorBlockJob(qemuMonitorPtr mon,
|
int
|
||||||
const char *device,
|
qemuMonitorBlockJob(qemuMonitorPtr mon,
|
||||||
const char *base,
|
const char *device,
|
||||||
const char *backingName,
|
const char *base,
|
||||||
unsigned long bandwidth,
|
const char *backingName,
|
||||||
virDomainBlockJobInfoPtr info,
|
unsigned long bandwidth,
|
||||||
qemuMonitorBlockJobCmd mode,
|
qemuMonitorBlockJobCmd mode,
|
||||||
bool modern)
|
bool modern)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
unsigned long long speed;
|
unsigned long long speed;
|
||||||
|
|
||||||
VIR_DEBUG("mon=%p, device=%s, base=%s, backingName=%s, bandwidth=%luM, "
|
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),
|
mon, device, NULLSTR(base), NULLSTR(backingName),
|
||||||
bandwidth, info, mode, modern);
|
bandwidth, mode, modern);
|
||||||
|
|
||||||
/* Convert bandwidth MiB to bytes - unfortunately the JSON QMP protocol is
|
/* Convert bandwidth MiB to bytes - unfortunately the JSON QMP protocol is
|
||||||
* limited to LLONG_MAX also for unsigned values */
|
* limited to LLONG_MAX also for unsigned values */
|
||||||
@ -3390,13 +3390,32 @@ int qemuMonitorBlockJob(qemuMonitorPtr mon,
|
|||||||
|
|
||||||
if (mon->json)
|
if (mon->json)
|
||||||
ret = qemuMonitorJSONBlockJob(mon, device, base, backingName,
|
ret = qemuMonitorJSONBlockJob(mon, device, base, backingName,
|
||||||
speed, info, mode, modern);
|
speed, mode, modern);
|
||||||
else
|
else
|
||||||
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
||||||
_("block jobs require JSON monitor"));
|
_("block jobs require JSON monitor"));
|
||||||
return ret;
|
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,
|
int qemuMonitorSetBlockIoThrottle(qemuMonitorPtr mon,
|
||||||
const char *device,
|
const char *device,
|
||||||
virDomainBlockIoTuneInfoPtr info)
|
virDomainBlockIoTuneInfoPtr info)
|
||||||
|
@ -685,7 +685,6 @@ int qemuMonitorSendKey(qemuMonitorPtr mon,
|
|||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
BLOCK_JOB_ABORT,
|
BLOCK_JOB_ABORT,
|
||||||
BLOCK_JOB_INFO,
|
|
||||||
BLOCK_JOB_SPEED,
|
BLOCK_JOB_SPEED,
|
||||||
BLOCK_JOB_PULL,
|
BLOCK_JOB_PULL,
|
||||||
} qemuMonitorBlockJobCmd;
|
} qemuMonitorBlockJobCmd;
|
||||||
@ -695,11 +694,15 @@ int qemuMonitorBlockJob(qemuMonitorPtr mon,
|
|||||||
const char *base,
|
const char *base,
|
||||||
const char *backingName,
|
const char *backingName,
|
||||||
unsigned long bandwidth,
|
unsigned long bandwidth,
|
||||||
virDomainBlockJobInfoPtr info,
|
|
||||||
qemuMonitorBlockJobCmd mode,
|
qemuMonitorBlockJobCmd mode,
|
||||||
bool modern)
|
bool modern)
|
||||||
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
|
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,
|
int qemuMonitorOpenGraphics(qemuMonitorPtr mon,
|
||||||
const char *protocol,
|
const char *protocol,
|
||||||
int fd,
|
int fd,
|
||||||
|
@ -3684,9 +3684,11 @@ int qemuMonitorJSONScreendump(qemuMonitorPtr mon,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int qemuMonitorJSONGetBlockJobInfoOne(virJSONValuePtr entry,
|
/* Returns -1 on error, 0 if not the right device, 1 if info was populated. */
|
||||||
const char *device,
|
static int
|
||||||
virDomainBlockJobInfoPtr info)
|
qemuMonitorJSONGetBlockJobInfoOne(virJSONValuePtr entry,
|
||||||
|
const char *device,
|
||||||
|
virDomainBlockJobInfoPtr info)
|
||||||
{
|
{
|
||||||
const char *this_dev;
|
const char *this_dev;
|
||||||
const char *type;
|
const char *type;
|
||||||
@ -3698,7 +3700,7 @@ static int qemuMonitorJSONGetBlockJobInfoOne(virJSONValuePtr entry,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (!STREQ(this_dev, device))
|
if (!STREQ(this_dev, device))
|
||||||
return -1;
|
return 0;
|
||||||
|
|
||||||
type = virJSONValueObjectGetString(entry, "type");
|
type = virJSONValueObjectGetString(entry, "type");
|
||||||
if (!type) {
|
if (!type) {
|
||||||
@ -3733,54 +3735,65 @@ static int qemuMonitorJSONGetBlockJobInfoOne(virJSONValuePtr entry,
|
|||||||
_("entry was missing 'len'"));
|
_("entry was missing 'len'"));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** qemuMonitorJSONGetBlockJobInfo:
|
/**
|
||||||
* Parse Block Job information.
|
* qemuMonitorJSONBlockJobInfo:
|
||||||
* The reply is a JSON array of objects, one per active job.
|
* 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,
|
int
|
||||||
const char *device,
|
qemuMonitorJSONBlockJobInfo(qemuMonitorPtr mon,
|
||||||
virDomainBlockJobInfoPtr info)
|
const char *device,
|
||||||
|
virDomainBlockJobInfoPtr info)
|
||||||
{
|
{
|
||||||
|
virJSONValuePtr cmd = NULL;
|
||||||
|
virJSONValuePtr reply = NULL;
|
||||||
virJSONValuePtr data;
|
virJSONValuePtr data;
|
||||||
int nr_results;
|
int nr_results;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
if (!info)
|
cmd = qemuMonitorJSONMakeCommand("query-block-jobs", NULL);
|
||||||
|
if (!cmd)
|
||||||
return -1;
|
return -1;
|
||||||
|
if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
if ((data = virJSONValueObjectGet(reply, "return")) == NULL) {
|
if ((data = virJSONValueObjectGet(reply, "return")) == NULL) {
|
||||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
_("reply was missing return data"));
|
_("reply was missing return data"));
|
||||||
return -1;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data->type != VIR_JSON_TYPE_ARRAY) {
|
if (data->type != VIR_JSON_TYPE_ARRAY) {
|
||||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
_("unrecognized format of block job information"));
|
_("unrecognized format of block job information"));
|
||||||
return -1;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((nr_results = virJSONValueArraySize(data)) < 0) {
|
if ((nr_results = virJSONValueArraySize(data)) < 0) {
|
||||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
_("unable to determine array size"));
|
_("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);
|
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"));
|
||||||
return -1;
|
ret = -1;
|
||||||
|
goto cleanup;
|
||||||
}
|
}
|
||||||
if (qemuMonitorJSONGetBlockJobInfoOne(entry, device, info) == 0)
|
ret = qemuMonitorJSONGetBlockJobInfoOne(entry, device, info);
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
cleanup:
|
||||||
|
virJSONValueFree(cmd);
|
||||||
|
virJSONValueFree(reply);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3791,7 +3804,6 @@ qemuMonitorJSONBlockJob(qemuMonitorPtr mon,
|
|||||||
const char *base,
|
const char *base,
|
||||||
const char *backingName,
|
const char *backingName,
|
||||||
unsigned long long speed,
|
unsigned long long speed,
|
||||||
virDomainBlockJobInfoPtr info,
|
|
||||||
qemuMonitorBlockJobCmd mode,
|
qemuMonitorBlockJobCmd mode,
|
||||||
bool modern)
|
bool modern)
|
||||||
{
|
{
|
||||||
@ -3833,11 +3845,6 @@ qemuMonitorJSONBlockJob(qemuMonitorPtr mon,
|
|||||||
NULL);
|
NULL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BLOCK_JOB_INFO:
|
|
||||||
cmd_name = "query-block-jobs";
|
|
||||||
cmd = qemuMonitorJSONMakeCommand(cmd_name, NULL);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BLOCK_JOB_SPEED:
|
case BLOCK_JOB_SPEED:
|
||||||
cmd_name = modern ? "block-job-set-speed" : "block_job_set_speed";
|
cmd_name = modern ? "block-job-set-speed" : "block_job_set_speed";
|
||||||
cmd = qemuMonitorJSONMakeCommand(cmd_name,
|
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(cmd);
|
||||||
virJSONValueFree(reply);
|
virJSONValueFree(reply);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -285,11 +285,15 @@ int qemuMonitorJSONBlockJob(qemuMonitorPtr mon,
|
|||||||
const char *base,
|
const char *base,
|
||||||
const char *backingName,
|
const char *backingName,
|
||||||
unsigned long long speed,
|
unsigned long long speed,
|
||||||
virDomainBlockJobInfoPtr info,
|
|
||||||
qemuMonitorBlockJobCmd mode,
|
qemuMonitorBlockJobCmd mode,
|
||||||
bool modern)
|
bool modern)
|
||||||
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
|
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,
|
int qemuMonitorJSONSetLink(qemuMonitorPtr mon,
|
||||||
const char *name,
|
const char *name,
|
||||||
virDomainNetInterfaceLinkState state);
|
virDomainNetInterfaceLinkState state);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user