qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Eric Blake <eblake@redhat.com>
To: Kevin Wolf <kwolf@redhat.com>, qemu-block@nongnu.org
Cc: qemu-devel@nongnu.org, mreitz@redhat.com
Subject: Re: [Qemu-devel] [PATCH 06/10] qemu-img: Prepare for locked images
Date: Tue, 22 Dec 2015 14:06:50 -0700	[thread overview]
Message-ID: <5679BB6A.6080902@redhat.com> (raw)
In-Reply-To: <1450802786-20893-7-git-send-email-kwolf@redhat.com>

[-- Attachment #1: Type: text/plain, Size: 7589 bytes --]

On 12/22/2015 09:46 AM, Kevin Wolf wrote:
> This patch extends qemu-img for working with locked images. It prints a
> helpful error message when trying to access a locked image read-write,
> and adds a 'qemu-img force-unlock' command as well as a 'qemu-img check
> -r all --force' option in order to override a lock left behind after a
> qemu crash.
> 
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> ---
>  include/block/block.h |  1 +
>  include/qapi/error.h  |  1 +
>  qapi/common.json      |  3 +-
>  qemu-img-cmds.hx      | 10 ++++--
>  qemu-img.c            | 96 +++++++++++++++++++++++++++++++++++++++++++--------
>  qemu-img.texi         | 20 ++++++++++-
>  6 files changed, 113 insertions(+), 18 deletions(-)
> 

> +++ b/include/qapi/error.h
> @@ -102,6 +102,7 @@ typedef enum ErrorClass {
>      ERROR_CLASS_DEVICE_NOT_ACTIVE = QAPI_ERROR_CLASS_DEVICENOTACTIVE,
>      ERROR_CLASS_DEVICE_NOT_FOUND = QAPI_ERROR_CLASS_DEVICENOTFOUND,
>      ERROR_CLASS_KVM_MISSING_CAP = QAPI_ERROR_CLASS_KVMMISSINGCAP,
> +    ERROR_CLASS_IMAGE_FILE_LOCKED = QAPI_ERROR_CLASS_IMAGEFILELOCKED,
>  } ErrorClass;

Wow - a new ErrorClass.  It's been a while since we could justify one of
these, but I think you might have found a case.

>  
>  /*
> diff --git a/qapi/common.json b/qapi/common.json
> index 9353a7b..1bf6e46 100644
> --- a/qapi/common.json
> +++ b/qapi/common.json
> @@ -27,7 +27,8 @@
>  { 'enum': 'QapiErrorClass',
>    # Keep this in sync with ErrorClass in error.h
>    'data': [ 'GenericError', 'CommandNotFound', 'DeviceEncrypted',
> -            'DeviceNotActive', 'DeviceNotFound', 'KVMMissingCap' ] }
> +            'DeviceNotActive', 'DeviceNotFound', 'KVMMissingCap',
> +            'ImageFileLocked' ] }

Missing documentation of the new value; should be something like:

# @ImageFileLocked: the requested operation attempted to write to an
#    image locked for writing by another process (since 2.6)

>  
> +DEF("force-unlock", img_force_unlock,
> +    "force_unlock [-f fmt] filename")

So is it force-unlock or force_unlock?  It's our first two-word command
on the qemu-img CLI, but I strongly prefer '-' (hitting the shift key
mid-word is a bother for CLI usage).

> +++ b/qemu-img.c
> @@ -47,6 +47,7 @@ typedef struct img_cmd_t {
>  enum {
>      OPTION_OUTPUT = 256,
>      OPTION_BACKING_CHAIN = 257,
> +    OPTION_FORCE = 258,
>  };

May conflict with Daniel's proposed patches; I'm sure you two can sort
out the problems.

> @@ -206,12 +207,34 @@ static BlockBackend *img_open(const char *id, const char *filename,
>      Error *local_err = NULL;
>      QDict *options = NULL;
>  
> +    options = qdict_new();
>      if (fmt) {
> -        options = qdict_new();
>          qdict_put(options, "driver", qstring_from_str(fmt));
>      }
> +    QINCREF(options);
>  
>      blk = blk_new_open(id, filename, NULL, options, flags, &local_err);
> +    if (!blk && error_get_class(local_err) == ERROR_CLASS_IMAGE_FILE_LOCKED) {
> +        if (force) {
> +            qdict_put(options, BDRV_OPT_OVERRIDE_LOCK, qstring_from_str("on"));

I guess it's safer to try without override and then re-issue with it,
only when needed, rather than treating 'force' as blindly turning on
override even when it is not needed to avoid the need for reissuing
commands.  And probably not observable to the user which of the two
approaches you use (same end results).

> +            blk = blk_new_open(id, filename, NULL, options, flags, NULL);

Can't the second attempt still fail, for some other reason?  I think
passing NULL for errp is risky here.  I guess you're saved by the fact
that blk_new_open() should always return NULL if an error would have
been set, and that you want to favor reporting the original failure
(with the class ERROR_CLASS_IMAGE_FILE_LOCKED) rather than the
second-attempt failure.

> +            if (blk) {
> +                error_free(local_err);
> +            }
> +        } else {
> +            error_report("The image file '%s' is locked and cannot be "
> +                         "opened for write access as this may cause image "
> +                         "corruption.", filename);

This completely discards the information in local_err.  Of course, I
don't know what information you are proposing to store for the actual
advisory lock extension header.  But let's suppose it were to include
hostname+pid information on who claimed the lock, rather than just a
single lock bit.  That additional information in local_err may well be
worth reporting here rather than just discarding it all.

> +            error_report("If it is locked in error (e.g. because "
> +                         "of an unclean shutdown) and you are sure that no "
> +                         "other processes are working on the image file, you "
> +                         "can use 'qemu-img force-unlock' or the --force flag "
> +                         "for 'qemu-img check' in order to override this "
> +                         "check.");

Long line; I don't know if we want to insert intermediate line breaks.
Markus may have more opinions on what this should look like.

> +static int img_force_unlock(int argc, char **argv)
> +{
> +    BlockBackend *blk;
> +    const char *format = NULL;
> +    const char *filename;
> +    char c;
> +
> +    for (;;) {
> +        c = getopt(argc, argv, "hf:");
> +        if (c == -1) {
> +            break;
> +        }
> +        switch (c) {
> +        case '?':
> +        case 'h':
> +            help();
> +            break;
> +        case 'f':
> +            format = optarg;
> +            break;

Depending on what we decide for Daniel's patches, you may not even want
a -f here, but always treat this as a new-style command that only takes
QemuOpts style parsing of a positional parameter.  Right now, I'm
leaning towards his v3 design (all older sub-commands gain a boolean
flag that says whether the positional parameters are literal filenames
or specific QemuOpts strings), but since your subcommand is new, we
don't have to cater to the older style.

> +++ b/qemu-img.texi
> @@ -117,7 +117,7 @@ Skip the creation of the target volume
>  Command description:
>  
>  @table @option
> -@item check [-f @var{fmt}] [--output=@var{ofmt}] [-r [leaks | all]] [-T @var{src_cache}] @var{filename}
> +@item check [-q] [-f @var{fmt}] [--force] [--output=@var{ofmt}] [-r [leaks | all]] [-T @var{src_cache}] @var{filename}

Where did -q come from?

>  
> +@item force-unlock [-f @var{fmt}] @var{filename}

Okay - most of your patch used the sane spelling; it was just the one
spot I found that used force_unlock incorrectly.

> +
> +Read-write disk images can generally be safely opened only from a single
> +process at the same time. In order to protect against corruption from
> +neglecting to follow this rule, qcow2 images are automatically flagged as
> +in use when they are opened and the flag is removed again on a clean
> +shutdown.
> +
> +However, in cases of an unclean shutdown, the image might be still marked as in
> +use so that any further read-write access is prohibited. You can use the
> +@code{force-unlock} command to manually remove the in-use flag then.
> +

Looks reasonable.  I do think I found enough things, though, that it
will require a v2 (perhaps rebased on some other patches) before I give R-b.

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

  parent reply	other threads:[~2015-12-22 21:07 UTC|newest]

Thread overview: 99+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-12-22 16:46 [Qemu-devel] [PATCH 00/10] qcow2: Implement image locking Kevin Wolf
2015-12-22 16:46 ` [Qemu-devel] [PATCH 01/10] qcow2: Write feature table only for v3 images Kevin Wolf
2015-12-22 20:20   ` Eric Blake
2016-01-11 15:20     ` Kevin Wolf
2015-12-22 16:46 ` [Qemu-devel] [PATCH 02/10] qcow2: Write full header on image creation Kevin Wolf
2015-12-22 20:25   ` Eric Blake
2015-12-22 16:46 ` [Qemu-devel] [PATCH 03/10] block: Assert no write requests under BDRV_O_INCOMING Kevin Wolf
2015-12-22 20:27   ` Eric Blake
2015-12-22 16:46 ` [Qemu-devel] [PATCH 04/10] block: Fix error path in bdrv_invalidate_cache() Kevin Wolf
2015-12-22 20:31   ` Eric Blake
2015-12-22 16:46 ` [Qemu-devel] [PATCH 05/10] block: Inactivate BDS when migration completes Kevin Wolf
2015-12-22 20:43   ` Eric Blake
2016-01-05 20:21     ` [Qemu-devel] [Qemu-block] " John Snow
2016-01-13 14:25       ` Kevin Wolf
2016-01-13 16:35         ` Eric Blake
2015-12-22 16:46 ` [Qemu-devel] [PATCH 06/10] qemu-img: Prepare for locked images Kevin Wolf
2015-12-22 16:57   ` Daniel P. Berrange
2015-12-22 17:00     ` Kevin Wolf
2015-12-22 21:06   ` Eric Blake [this message]
2016-01-11 15:49     ` Markus Armbruster
2016-01-11 16:05       ` Kevin Wolf
2016-01-12 15:20         ` Markus Armbruster
2016-01-12 17:36           ` Kevin Wolf
2016-01-13  8:44             ` Markus Armbruster
2016-01-13 14:19               ` Kevin Wolf
2016-01-14 13:07                 ` Markus Armbruster
2016-01-14 14:19                   ` Kevin Wolf
2016-01-11 16:22     ` Kevin Wolf
2015-12-22 21:41   ` Eric Blake
2015-12-22 16:46 ` [Qemu-devel] [PATCH 07/10] qcow2: Implement .bdrv_inactivate Kevin Wolf
2015-12-22 21:17   ` Eric Blake
2016-01-11 15:34     ` Kevin Wolf
2015-12-22 16:46 ` [Qemu-devel] [PATCH 08/10] qcow2: Fix BDRV_O_INCOMING handling in qcow2_invalidate_cache() Kevin Wolf
2015-12-22 21:22   ` Eric Blake
2015-12-22 16:46 ` [Qemu-devel] [PATCH 09/10] qcow2: Make image inaccessible after failed qcow2_invalidate_cache() Kevin Wolf
2015-12-22 21:24   ` Eric Blake
2015-12-22 16:46 ` [Qemu-devel] [PATCH 10/10] qcow2: Add image locking Kevin Wolf
2015-12-22 22:04   ` Eric Blake
2015-12-23  3:14 ` [Qemu-devel] [PATCH 00/10] qcow2: Implement " Fam Zheng
2015-12-23  7:35   ` [Qemu-devel] [Qemu-block] " Denis V. Lunev
2015-12-23  7:46     ` [Qemu-devel] [PATCH RFC 0/5] generic image locking and crash recovery Denis V. Lunev
2015-12-23  7:46       ` [Qemu-devel] [PATCH 1/5] block: added lock image option and callback Denis V. Lunev
2015-12-23 23:48         ` Eric Blake
2016-01-11 17:31         ` Kevin Wolf
2016-01-11 17:58           ` Daniel P. Berrange
2016-01-11 18:35             ` Kevin Wolf
2016-01-13  8:52               ` Markus Armbruster
2016-01-13  9:12                 ` Denis V. Lunev
2016-01-13  9:50                   ` Daniel P. Berrange
2016-01-13  9:51               ` Daniel P. Berrange
2016-01-12  5:38           ` Denis V. Lunev
2016-01-12 10:10             ` Kevin Wolf
2016-01-12 11:33               ` Fam Zheng
2016-01-12 12:24                 ` Denis V. Lunev
2016-01-12 12:28                 ` Kevin Wolf
2016-01-12 13:17                   ` Fam Zheng
2016-01-12 13:24                     ` Daniel P. Berrange
2016-01-13  0:08                       ` Fam Zheng
2016-01-12 15:59                 ` Denis V. Lunev
2016-01-13  0:10                   ` Fam Zheng
2016-01-13 16:44                     ` Eric Blake
2016-01-14  7:23                       ` Denis V. Lunev
2015-12-23  7:46       ` [Qemu-devel] [PATCH 2/5] block: implemented bdrv_lock_image for raw file Denis V. Lunev
2015-12-23 12:40         ` Daniel P. Berrange
2015-12-23  7:46       ` [Qemu-devel] [PATCH 3/5] block: added check image option and callback bdrv_is_opened_unclean Denis V. Lunev
2015-12-23  9:09         ` Fam Zheng
2015-12-23  9:14           ` Denis V. Lunev
2015-12-23  7:46       ` [Qemu-devel] [PATCH 4/5] qcow2: implemented bdrv_is_opened_unclean Denis V. Lunev
2016-01-11 17:37         ` Kevin Wolf
2015-12-23  7:46       ` [Qemu-devel] [PATCH 5/5] block/paralels: added paralles implementation for bdrv_is_opened_unclean Denis V. Lunev
2015-12-23  8:09       ` [Qemu-devel] [PATCH RFC 0/5] generic image locking and crash recovery Fam Zheng
2015-12-23  8:36         ` Denis V. Lunev
2015-12-23 10:47   ` [Qemu-devel] [PATCH 00/10] qcow2: Implement image locking Daniel P. Berrange
2015-12-23 12:15     ` [Qemu-devel] [Qemu-block] " Roman Kagan
2015-12-23 12:29       ` Daniel P. Berrange
2015-12-23 12:41         ` Denis V. Lunev
2015-12-23 12:46           ` Daniel P. Berrange
2015-12-23 12:34       ` Daniel P. Berrange
2015-12-23 12:47         ` Denis V. Lunev
2015-12-23 12:56           ` Daniel P. Berrange
2016-01-11 17:14     ` [Qemu-devel] " Kevin Wolf
2016-01-11 17:54       ` Daniel P. Berrange
2016-01-13  8:56       ` Markus Armbruster
2016-01-13  9:11         ` [Qemu-devel] [Qemu-block] " Denis V. Lunev
2015-12-23 23:19   ` [Qemu-devel] " Max Reitz
2015-12-24  5:41     ` [Qemu-devel] [Qemu-block] " Denis V. Lunev
2015-12-24  5:42       ` Denis V. Lunev
2016-01-04 17:02       ` Max Reitz
2016-01-11 16:47       ` Kevin Wolf
2016-01-11 17:56         ` Daniel P. Berrange
2015-12-23 14:57 ` [Qemu-devel] " Vasiliy Tolstov
2015-12-23 15:08   ` [Qemu-devel] [Qemu-block] " Denis V. Lunev
2015-12-23 15:11     ` Vasiliy Tolstov
2016-01-11 16:25       ` Kevin Wolf
2015-12-23 15:09   ` Denis V. Lunev
2015-12-24  5:43 ` Denis V. Lunev
2016-01-11 16:33   ` Kevin Wolf
2016-01-11 16:38     ` Denis V. Lunev
2016-01-14 14:01 ` Max Reitz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5679BB6A.6080902@redhat.com \
    --to=eblake@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=mreitz@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).