qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH 4/5] block: Accept node-name arguments for block


From: Jeff Cody
Subject: Re: [Qemu-devel] [PATCH 4/5] block: Accept node-name arguments for block-commit
Date: Thu, 15 May 2014 14:04:03 -0400
User-agent: Mutt/1.5.21 (2010-09-15)

On Thu, May 15, 2014 at 09:42:07AM -0600, Eric Blake wrote:
> On 05/14/2014 09:20 PM, Jeff Cody wrote:
> > This modifies the block operation block-commit so that it will
> > accept node-name arguments for either 'top' or 'base' BDS.
> > 
> > The filename and node-name are mutually exclusive to each other;
> > i.e.:
> >     "top" and "top-node-name" are mutually exclusive (enforced)
> >     "base" and "base-node-name" are mutually exclusive (enforced)
> 
> Hmm - we have a bug in existing commands for NOT forcing mutual
> exclusion even though the schema says they are exclusive.  

Those are a slightly different scenario, however.  In this patch, we
are dealing with a filename string, and a node-name string.  There is
more of a 1:1 relationship between those two (both identify a
particular image).  The other existing commands, however, deal with a
device name string (identifying a drive chain) or a node-name string
(identifying a particular image).

That said, I think the other commands should be modified to enforce
the documentation, but it doesn't really relate to this patch.

> For example,
> qmp_block_passwd() blindly calls:
> 
>     bs = bdrv_lookup_bs(has_device ? device : NULL,
>                         has_node_name ? node_name : NULL,
>                         &local_err);
> 
> and _that_ function blindly favors device name over node name, rather
> than erroring out if both are supplied.  

I find this an odd function to begin with, because node_name uniquely
identifies any given BDS from any chain.  Device name will uniquely
identify a whole chain, by returning its top-most BDS.

The function seems confused.


> I think we should fix that
> first - I'd rather that bdrv_lookup_bs either errors out if both names
> are supplied (rather than making each caller repeat the work), or that
> it checks that if both names are supplied then it resolves to the same bs.
> 

I disagree on this part, at least partially.  It think it needs to be
changed, but I don't think it needs to be part of this series.  I
think that can be a separate series, to address that across the other
QAPI commands that accept node-name and device name


> Hmm - if I have device "foo" with chain "base <- top", would
> bdrv_lookup_bs("foo", "base") be okay ("base" is a node-name that
> resides within "device"'s chain) or an error ("base" resolves to a
> different bs than "device")?  Again, all the more reason to have a
> common function decide the semantics we want, then all other clients
> automatically pick up on those semantics.
>
> > 
> > The preferred and recommended method now of using block-commit
> > is to specify the BDS to operate on via their node-name arguments.
> > 
> > This also adds an explicit check that base_bs is in the chain of
> > top_bs, because if they are referenced by their unique node-name
> > arguments, the discovery process does not intrinsically verify
> > they are in the same chain.
> 
> I like this addition.
> 
> > 
> > Signed-off-by: Jeff Cody <address@hidden>
> > ---
> >  blockdev.c       | 35 +++++++++++++++++++++++++++++++++--
> >  qapi-schema.json | 35 ++++++++++++++++++++++++++---------
> >  qmp-commands.hx  | 29 ++++++++++++++++++++++-------
> >  3 files changed, 81 insertions(+), 18 deletions(-)
> > 
> 
> 
> 
> >  
> > -    if (top) {
> > +    /* Find the 'top' image file for the commit */
> > +    if (has_top_node_name) {
> > +        top_bs = bdrv_lookup_bs(NULL, top_node_name, &local_err);
> 
> Hmm.  Shouldn't you ALSO verify that 'top_bs' belongs to the chain owned
> by 'device'?  Later on, you verify that 'base_bs' belongs to 'top_bs',
> but if I pass node names, those names could have found a top unrelated
> to 'device'; and base related to that top.
>

It is not needed - it is not relevant for the active commit case (the
current check will catch that, since top_bs == bs).  And for the
non-active commit case, commit_start() will return an error if
'top_bs' is not in 'bs', so the case of 'base_bs' or 'top_bs' not
being in 'device' is already covered.

> Maybe that gives more weight to my idea of possibly allowing
> bdrv_lookup_bs(device, top_node_name), where the lookup succeeds even
> when device and top_node_name resolve to different bs, but where
> top_node_name is a node in the chain of device.
> 
> > 
> > -    if (has_base && base) {
> > +    /* Find the 'base' image file for the commit */
> > +    if (has_base_node_name) {
> > +        base_bs = bdrv_lookup_bs(NULL, base_node_name, &local_err);
> > +        if (local_err) {
> > +            error_propagate(errp, local_err);
> > +            return;
> > +        }
> > +    } else if (has_base && base) {
> 
> Here, it doesn't matter whether you pass device or NULL for the device
> name...
> 

This conditional is just to determine if we are finding the backing
image referenced by the string "base" or just using the default
bottom-most base image.

> >  
> > +    /* Verify that 'base' is in the same chain as 'top' */
> > +    if (!bdrv_is_in_chain(top_bs, base_bs)) {
> > +        error_setg(errp, "'base' and 'top' are not in the same chain");
> > +        return;
> 
> ...because this check is still mandatory to prove that a user with chain:
> base <- sn1 <- sn2 <- active
> 
> is not calling 'device':'active', 'top-node-name':'sn1',
> 'base-node-name':'sn2' (all that bdrv_lookup_bs can do is verify that
> base-node-name belongs to device, not that it _also_ belongs to top_bs).
> 
> 
> > -# @base:   #optional The file name of the backing image to write data into.
> > -#                    If not specified, this is the deepest backing image
> > +# For 'base', either @base or @base-node-name may be set but not both. If
> > +# neither is specified, this is the deepest backing image
> 
> I like how you factored th is out up front...
> 
> >  #
> > -# @top:    #optional The file name of the backing image within the image 
> > chain,
> > -#                    which contains the topmost data to be committed down. 
> > If
> > -#                    not specified, this is the active layer.
> > +# @base:          #optional The file name of the backing image to write 
> > data
> > +#                           into.
> > +#
> > +# @base-node-name #optional The name of the block driver state node of the
> > +#                           backing image to write data into.
> > +#                           (Since 2.1)
> > +#
> > +# For 'top', either @top or @top-node-name must be set but not both.
> 
> ...but here, you were not consistent.  I'd add "If neither is specified,
> this is the active image" here...
>

OK, thanks.

> > +#
> > +# @top:           #optional The file name of the backing image within the 
> > image
> > +#                           chain, which contains the topmost data to be
> > +#                           committed down. If not specified, this is the
> > +#                           active layer.
> 
> ...and drop the second sentence from here.
>

OK, thanks.

> > +#
> > +# @top-node-name: #optional The block driver state node name of the backing
> > +#                           image within the image chain, which contains 
> > the
> > +#                           topmost data to be committed down.
> > +#                           (Since 2.1)
> >  #
> >  #                    If top == base, that is an error.
> >  #                    If top == active, the job will not be completed by 
> > itself,
> > @@ -2120,17 +2135,19 @@
> >  #
> >  # Returns: Nothing on success
> >  #          If commit or stream is already active on this device, 
> > DeviceInUse
> > -#          If @device does not exist, DeviceNotFound
> > +#          If @device does not exist or cannot be determined, 
> > DeviceNotFound
> >  #          If image commit is not supported by this device, NotSupported
> > -#          If @base or @top is invalid, a generic error is returned
> > +#          If @base, @top, @base-node-name, @top-node-name invalid, 
> > GenericError
> >  #          If @speed is invalid, InvalidParameter
> > +#          If both @base and @base-node-name are specified, GenericError
> > +#          If both @top and @top-node-name are specified, GenericError
> 
> These last two are arguably sub-conditions of the earlier statement
> about @top and @top-node-name being invalid (since being invalid can
> include when both strings are used at once).  It wouldn't hurt my
> feelings to reduce the docs by two lines.
> 

OK.  I called it out explicitly, since it is currently different
behavior from the other functions.

> >  # Since: 1.3
> >  #
> >  ##
> >  { 'command': 'block-commit',
> > -  'data': { 'device': 'str', '*base': 'str', '*top': 'str',
> > -            '*speed': 'int' } }
> > +  'data': { 'device': 'str', '*base': 'str', '*base-node-name': 'str',
> > +            '*top': 'str', '*top-node-name': 'str', '*speed': 'int' } }
> 
> I'm okay with keeping 'device' mandatory, even though technically the
> use of a node-name could imply which device is intended.  That is, as
> long as the code correctly errors out when device and top-node-name
> don't resolve to the same chain :)
> 

I had thought about making it optional, but I do think it is better as
mandatory - it makes sure the user knows which chain they are
operating on, so it acts as a (small) check against user mistakes.

> 
> > +
> > +For 'top', either top or top-node-name must be set but not both.
> > +
> > +- "top":            The file name of the backing image within the image 
> > chain,
> > +                    which contains the topmost data to be committed down. 
> > If
> > +                    not specified, this is the active layer.
> > +                    (json-string, optional)
> 
> Same blurb about hoisting the 'not specified => active' sentence to the
> common text, rather than leaving it in the 'top' text.
> 

OK, thanks.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]