[libvirt] [PATCHv3 15/19] blockjob: manage qemu block-commit monitor command
Laine Stump
laine at laine.org
Thu Oct 18 18:44:44 UTC 2012
On 10/17/2012 06:30 PM, Eric Blake wrote:
> qemu 1.3 will be adding a 'block-commit' monitor command, per
> qemu.git commit ed61fc1. It matches nicely to the libvirt API
> virDomainBlockCommit.
>
> * src/qemu/qemu_capabilities.h (QEMU_CAPS_BLOCK_COMMIT): New bit.
> * src/qemu/qemu_capabilities.c (qemuCapsProbeQMPCommands): Set it.
> * src/qemu/qemu_monitor.h (qemuMonitorBlockCommit): New prototype.
> * src/qemu/qemu_monitor_json.h (qemuMonitorJSONBlockCommit):
> Likewise.
> * src/qemu/qemu_monitor.c (qemuMonitorBlockCommit): Implement it.
> * src/qemu/qemu_monitor_json.c (qemuMonitorJSONBlockCommit):
> Likewise.
> (qemuMonitorJSONHandleBlockJobImpl)
> (qemuMonitorJSONGetBlockJobInfoOne): Handle new event type.
> ---
>
> v3: use long long for JSON speed argument
>
> src/qemu/qemu_capabilities.c | 3 +++
> src/qemu/qemu_capabilities.h | 1 +
> src/qemu/qemu_monitor.c | 30 ++++++++++++++++++++++++++++++
> src/qemu/qemu_monitor.h | 7 +++++++
> src/qemu/qemu_monitor_json.c | 34 ++++++++++++++++++++++++++++++++++
> src/qemu/qemu_monitor_json.h | 7 +++++++
> src/qemu/qemu_process.c | 15 +++++++++------
> 7 files changed, 91 insertions(+), 6 deletions(-)
>
> diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
> index fb0fe54..73a12f1 100644
> --- a/src/qemu/qemu_capabilities.c
> +++ b/src/qemu/qemu_capabilities.c
> @@ -187,6 +187,7 @@ VIR_ENUM_IMPL(qemuCaps, QEMU_CAPS_LAST,
> "reboot-timeout", /* 110 */
> "dump-guest-core",
> "seamless-migration",
> + "block-commit",
> );
>
> struct _qemuCaps {
> @@ -1881,6 +1882,8 @@ qemuCapsProbeQMPCommands(qemuCapsPtr caps,
> qemuCapsSet(caps, QEMU_CAPS_SPICE);
> else if (STREQ(name, "query-kvm"))
> qemuCapsSet(caps, QEMU_CAPS_KVM);
> + else if (STREQ(name, "block-commit"))
> + qemuCapsSet(caps, QEMU_CAPS_BLOCK_COMMIT);
> VIR_FREE(name);
> }
> VIR_FREE(commands);
> diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
> index 5d343c1..6939c45 100644
> --- a/src/qemu/qemu_capabilities.h
> +++ b/src/qemu/qemu_capabilities.h
> @@ -150,6 +150,7 @@ enum qemuCapsFlags {
> QEMU_CAPS_REBOOT_TIMEOUT = 110, /* -boot reboot-timeout */
> QEMU_CAPS_DUMP_GUEST_CORE = 111, /* dump-guest-core-parameter */
> QEMU_CAPS_SEAMLESS_MIGRATION = 112, /* seamless-migration for SPICE */
> + QEMU_CAPS_BLOCK_COMMIT = 113, /* block-commit */
>
> QEMU_CAPS_LAST, /* this must always be the last item */
> };
> diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
> index 4313451..2d9c44c 100644
> --- a/src/qemu/qemu_monitor.c
> +++ b/src/qemu/qemu_monitor.c
> @@ -2796,6 +2796,36 @@ qemuMonitorTransaction(qemuMonitorPtr mon, virJSONValuePtr actions)
> return ret;
> }
>
> +/* Start a block-commit block job. bandwidth is in MB/sec. */
> +int
> +qemuMonitorBlockCommit(qemuMonitorPtr mon, const char *device,
> + const char *top, const char *base,
> + unsigned long bandwidth)
> +{
> + int ret = -1;
> + unsigned long long speed;
> +
> + VIR_DEBUG("mon=%p, device=%s, top=%s, base=%s, bandwidth=%ld",
> + mon, device, NULLSTR(top), NULLSTR(base), bandwidth);
> +
> + /* Convert bandwidth MiB to bytes */
> + speed = bandwidth;
> + if (speed > ULLONG_MAX / 1024 / 1024) {
> + virReportError(VIR_ERR_OVERFLOW,
> + _("bandwidth must be less than %llu"),
> + ULLONG_MAX / 1024 / 1024);
> + return -1;
> + }
> + speed <<= 20;
> +
> + if (mon->json)
> + ret = qemuMonitorJSONBlockCommit(mon, device, top, base, speed);
> + else
> + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> + _("block-commit requires JSON monitor"));
> + return ret;
> +}
> +
> int qemuMonitorArbitraryCommand(qemuMonitorPtr mon,
> const char *cmd,
> char **reply,
> diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
> index f33b94c..8856d9f 100644
> --- a/src/qemu/qemu_monitor.h
> +++ b/src/qemu/qemu_monitor.h
> @@ -524,6 +524,13 @@ int qemuMonitorDiskSnapshot(qemuMonitorPtr mon,
> int qemuMonitorTransaction(qemuMonitorPtr mon, virJSONValuePtr actions)
> ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
>
> +int qemuMonitorBlockCommit(qemuMonitorPtr mon,
> + const char *device,
> + const char *top,
> + const char *base,
> + unsigned long bandwidth)
> + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
> +
> int qemuMonitorArbitraryCommand(qemuMonitorPtr mon,
> const char *cmd,
> char **reply,
> diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
> index 2daf8ea..d1ce9cc 100644
> --- a/src/qemu/qemu_monitor_json.c
> +++ b/src/qemu/qemu_monitor_json.c
> @@ -805,6 +805,8 @@ qemuMonitorJSONHandleBlockJobImpl(qemuMonitorPtr mon,
>
> if (STREQ(type_str, "stream"))
> type = VIR_DOMAIN_BLOCK_JOB_TYPE_PULL;
> + else if (STREQ(type_str, "commit"))
> + type = VIR_DOMAIN_BLOCK_JOB_TYPE_COMMIT;
>
> switch ((virConnectDomainEventBlockJobStatus) event) {
> case VIR_DOMAIN_BLOCK_JOB_COMPLETED:
> @@ -3278,6 +3280,36 @@ cleanup:
> return ret;
> }
>
> +/* speed is in bytes/sec */
> +int
> +qemuMonitorJSONBlockCommit(qemuMonitorPtr mon, const char *device,
> + const char *top, const char *base,
> + unsigned long long speed)
> +{
> + int ret = -1;
> + virJSONValuePtr cmd;
> + virJSONValuePtr reply = NULL;
> +
> + cmd = qemuMonitorJSONMakeCommand("block-commit",
> + "s:device", device,
> + "U:speed", speed,
> + "s:top", top,
> + base ? "s:base" : NULL, base,
> + NULL);
> + if (!cmd)
> + return -1;
> +
> + if ((ret = qemuMonitorJSONCommand(mon, cmd, &reply)) < 0)
> + goto cleanup;
> + ret = qemuMonitorJSONCheckError(cmd, reply);
> +
> +cleanup:
> + virJSONValueFree(cmd);
> + virJSONValueFree(reply);
> + return ret;
> +}
> +
> +
> int qemuMonitorJSONArbitraryCommand(qemuMonitorPtr mon,
> const char *cmd_str,
> char **reply_str,
> @@ -3394,6 +3426,8 @@ static int qemuMonitorJSONGetBlockJobInfoOne(virJSONValuePtr entry,
> }
> if (STREQ(type, "stream"))
> info->type = VIR_DOMAIN_BLOCK_JOB_TYPE_PULL;
> + else if (STREQ(type, "commit"))
> + info->type = VIR_DOMAIN_BLOCK_JOB_TYPE_COMMIT;
> else
> info->type = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN;
>
> diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
> index 63b84c6..61127a7 100644
> --- a/src/qemu/qemu_monitor_json.h
> +++ b/src/qemu/qemu_monitor_json.h
> @@ -235,6 +235,13 @@ int qemuMonitorJSONDiskSnapshot(qemuMonitorPtr mon,
> bool reuse);
> int qemuMonitorJSONTransaction(qemuMonitorPtr mon, virJSONValuePtr actions);
>
> +int qemuMonitorJSONBlockCommit(qemuMonitorPtr mon,
> + const char *device,
> + const char *top,
> + const char *base,
> + unsigned long long bandwidth)
> + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
> +
> int qemuMonitorJSONArbitraryCommand(qemuMonitorPtr mon,
> const char *cmd_str,
> char **reply_str,
> diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
> index 0e98c8b..3a087e2 100644
> --- a/src/qemu/qemu_process.c
> +++ b/src/qemu/qemu_process.c
> @@ -909,12 +909,15 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
> if (disk) {
> path = disk->src;
> event = virDomainEventBlockJobNewFromObj(vm, path, type, status);
> - /* XXX If we completed a block pull, then recompute the cached
> - * backing chain to match. Better would be storing the chain
> - * ourselves rather than reprobing, but this requires
> - * modifying domain_conf and our XML to fully track the chain
> - * across libvirtd restarts. */
> - if (type == VIR_DOMAIN_BLOCK_JOB_TYPE_PULL &&
> + /* XXX If we completed a block pull or commit, then recompute
> + * the cached backing chain to match. Better would be storing
> + * the chain ourselves rather than reprobing, but this
> + * requires modifying domain_conf and our XML to fully track
> + * the chain across libvirtd restarts. For that matter, if
> + * qemu gains support for committing the active layer, we have
> + * to update disk->src. */
> + if ((type == VIR_DOMAIN_BLOCK_JOB_TYPE_PULL ||
> + type == VIR_DOMAIN_BLOCK_JOB_TYPE_COMMIT) &&
> status == VIR_DOMAIN_BLOCK_JOB_COMPLETED)
> qemuDomainDetermineDiskChain(driver, disk, true);
> }
ACK.
More information about the libvir-list
mailing list