All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kevin Wolf <kwolf@redhat.com>
To: Eric Blake <eblake@redhat.com>
Cc: qemu-devel@nongnu.org, qemu-block@nongnu.org, mreitz@redhat.com
Subject: Re: [Qemu-devel] [PATCH 06/10] qemu-img: Prepare for locked images
Date: Mon, 11 Jan 2016 17:22:48 +0100	[thread overview]
Message-ID: <20160111162248.GG9454@noname.redhat.com> (raw)
In-Reply-To: <5679BB6A.6080902@redhat.com>

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

Am 22.12.2015 um 22:06 hat Eric Blake geschrieben:
> 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.

Yes, I think libvirt will need it as well.

That's the whole reason why I consider your input so important for this
series. If a crashed qemu can leave locked images around, libvirt needs
to know how to deal with it. I don't think it's hard to implement at
least something basic, but ideally it should be there before the qemu
release that introduces the locks.

> >  /*
> > 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)

Right, thanks for catching that.

> >  
> > +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).

Just a typo (the underscore is only in the help message).

> > +++ 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).

The reason here is that only qcow2 supports locks (and therefore the
lock override). Any other image format would result in an "unknown
option" error.

> > +            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.

I think this might be from before I introduced the error class, and I
wanted to return the original error instead of a potential "unknown
option" error that is introduced here. But I think we can assume that
any driver that returns ERROR_CLASS_IMAGE_FILE_LOCKED also supports the
image override option.

So it seems to me that I should now favour the later error.

> > +            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.

Hm. Yes. I did it this way to avoid the override-lock=on message, which
isn't helpful in a qemu-img context. Maybe I can somehow drop/replace
the hint of the errp and then use that?

> > +            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.

I don't think we assume any specific terminal size and line breaks in
the wrong place are probably worse than no line breaks at all.

> > +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.

I think the old syntax is friendlier for human users; or at least for
the less experienced ones.

> > +++ 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?

From an earlier patch that forgot to update the docs. Should I make that
a separate patch?

> >  
> > +@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.

Kevin

[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]

  parent reply	other threads:[~2016-01-11 16:23 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
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 [this message]
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=20160111162248.GG9454@noname.redhat.com \
    --to=kwolf@redhat.com \
    --cc=eblake@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.