[libvirt] [PATCH v3 1/5] blockjob: allow omitted arguments to QMP block-commit

Peter Krempa pkrempa at redhat.com
Thu Jun 19 08:51:30 UTC 2014


On 06/19/14 01:22, Eric Blake wrote:
> We are about to turn on support for active block commit.  Although
> qemu 2.0 was the first version to mostly support it, that version
> mis-handles 0-length files, and doesn't have anything available for
> easy probing.  But qemu 2.1 fixed bugs, and made life simpler by
> letting the 'top' argument be optional.  Unless someone begs for
> active commit with qemu 2.0, for now we are just going to enable
> it only by probing for qemu 2.1 behavior (anyone backporting active
> commit can also backport the optional argument behavior).
> 
> Although all our actual uses of block-commit supply arguments for
> both base and top, we can omit both arguments and use a bogus
> device string to trigger an interesting behavior in qemu.  All QMP
> commands first do argument validation, failing with GenericError
> if a mandatory argument is missing.  Once that passes, the code
> in the specific command gets to do further checking, and the qemu
> developers made sure that if device is the only supplied argument,
> then the block-commit code will look up the device first, with a
> failure of DeviceNotFound, before attempting any further argument
> validation (most other validations fail with GenericError).  Thus,
> the category of error class can reliably be used to decipher
> whether the top argument was optional, which in turn implies a
> working active commit.  Since we expect our bogus device string to
> trigger an error either way, the code is written to return a
> distinct return value without spamming the logs.
> 
> * src/qemu/qemu_monitor.h (qemuMonitorBlockCommit): Allow NULL for
> top and base, for probing purposes.
> * src/qemu/qemu_monitor.c (qemuMonitorBlockCommit): Likewise.
> * src/qemu/qemu_monitor_json.h (qemuMonitorJSONBlockCommit):
> Likewise.
> * src/qemu/qemu_monitor_json.c (qemuMonitorJSONBlockCommit):
> Likewise, with special return values based on probe.
> * tests/qemumonitorjsontest.c (mymain): Enable...
> (testQemuMonitorJSONqemuMonitorJSONBlockCommit2): ...a new test.
> 
> Signed-off-by: Eric Blake <eblake at redhat.com>
> ---
>  src/qemu/qemu_monitor.c      |  2 +-
>  src/qemu/qemu_monitor.h      |  3 +--
>  src/qemu/qemu_monitor_json.c | 20 ++++++++++++++++--
>  src/qemu/qemu_monitor_json.h |  3 +--
>  tests/qemumonitorjsontest.c  | 49 ++++++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 70 insertions(+), 7 deletions(-)
> 

...

> diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
> index bedd959..0e4262d 100644
> --- a/src/qemu/qemu_monitor_json.c
> +++ b/src/qemu/qemu_monitor_json.c
> @@ -3467,14 +3467,30 @@ qemuMonitorJSONBlockCommit(qemuMonitorPtr mon, const char *device,
>      cmd = qemuMonitorJSONMakeCommand("block-commit",
>                                       "s:device", device,
>                                       "U:speed", speed,
> -                                     "s:top", top,
> -                                     "s:base", base,
> +                                     "S:top", top,
> +                                     "S:base", base,
>                                       NULL);
>      if (!cmd)
>          return -1;
> 
>      if ((ret = qemuMonitorJSONCommand(mon, cmd, &reply)) < 0)
>          goto cleanup;
> +    if (!top && !base) {
> +        /* Normally we always specify top and base; but omitting them
> +         * allows for probing whether qemu is new enough to support
> +         * live commit.  */
> +        if (qemuMonitorJSONHasError(reply, "DeviceNotFound")) {
> +            VIR_DEBUG("block-commit supports active commit");
> +            ret = -2;
> +        } else {
> +            /* This is a false negative for qemu 2.0; but probably not
> +             * worth the additional complexity to worry about it */
> +            VIR_DEBUG("block-commit requires 'top' parameter, "
> +                      "assuming it lacks active commit");
> +            ret = -3;

I think those return values should be documented in the comment for
qemuMonitorBlockCommit so that we avoid possible confusion.

> +        }
> +        goto cleanup;
> +    }
>      ret = qemuMonitorJSONCheckError(cmd, reply);
> 
>   cleanup:

> diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c
> index 2099dc8..faa968f 100644
> --- a/tests/qemumonitorjsontest.c
> +++ b/tests/qemumonitorjsontest.c
> @@ -1992,6 +1992,54 @@ testQemuMonitorJSONqemuMonitorJSONSendKeyHoldtime(const void *data)
>  }
> 
>  static int
> +testQemuMonitorJSONqemuMonitorJSONBlockCommit2(const void *data)
> +{
> +    virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
> +    qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt);
> +    int ret = -1;
> +    const char *error1 =
> +        "{"
> +        "  \"error\": {"
> +        "    \"class\": \"DeviceNotFound\","
> +        "    \"desc\": \"Device 'bogus' not found\""
> +        "  }"
> +        "}";
> +    const char *error2 =
> +        "{"
> +        "  \"error\": {"
> +        "    \"class\": \"GenericError\","
> +        "    \"desc\": \"Parameter 'top' is missing\""
> +        "  }"
> +        "}";
> +
> +    if (!test)
> +        return -1;
> +
> +    if (qemuMonitorTestAddItemParams(test, "block-commit", error1,
> +                                     "device", "\"bogus\"",
> +                                     NULL, NULL) < 0)
> +        goto cleanup;
> +
> +    if (qemuMonitorBlockCommit(qemuMonitorTestGetMonitor(test),
> +                               "bogus", NULL, NULL, 0) != -2)
> +        goto cleanup;
> +
> +    if (qemuMonitorTestAddItemParams(test, "block-commit", error2,
> +                                     "device", "\"bogus\"",
> +                                     NULL, NULL) < 0)
> +        goto cleanup;
> +
> +    if (qemuMonitorBlockCommit(qemuMonitorTestGetMonitor(test),
> +                               "bogus", NULL, NULL, 0) != -3)
> +        goto cleanup;

If these ever fail it will be hard to diagnose but not really worth
doing anything about it.

> +
> +    ret = 0;
> + cleanup:
> +    qemuMonitorTestFree(test);
> +    return ret;
> +}
> +
> +static int
>  testQemuMonitorJSONqemuMonitorJSONGetDumpGuestMemoryCapability(const void *data)
>  {
>      virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;

ACK when you document the possible return values.

Peter

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 901 bytes
Desc: OpenPGP digital signature
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20140619/bebf45da/attachment-0001.sig>


More information about the libvir-list mailing list