qemu-block
[Top][All Lists]
Advanced

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

Re: [PATCH v7 17/47] block: Re-evaluate backing file handling in reopen


From: Max Reitz
Subject: Re: [PATCH v7 17/47] block: Re-evaluate backing file handling in reopen
Date: Thu, 16 Jul 2020 17:04:50 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.10.0

On 10.07.20 21:42, Andrey Shinkevich wrote:
> On 25.06.2020 18:21, Max Reitz wrote:
>> Reopening a node's backing child needs a bit of special handling because
>> the "backing" child has different defaults than all other children
>> (among other things).  Adding filter support here is a bit more
>> difficult than just using the child access functions.  In fact, we often
>> have to directly use bs->backing because these functions are about the
>> "backing" child (which may or may not be the COW backing file).
>>
>> Signed-off-by: Max Reitz <mreitz@redhat.com>
>> ---
>>   block.c | 46 ++++++++++++++++++++++++++++++++++++++--------
>>   1 file changed, 38 insertions(+), 8 deletions(-)
>>
>> diff --git a/block.c b/block.c
>> index 712230ef5c..8131d0b5eb 100644
>> --- a/block.c
>> +++ b/block.c
>> @@ -4026,26 +4026,56 @@ static int
>> bdrv_reopen_parse_backing(BDRVReopenState *reopen_state,
>>           }
>>       }
>>   +    /*
>> +     * Ensure that @bs can really handle backing files, because we are
>> +     * about to give it one (or swap the existing one)
>> +     */
>> +    if (bs->drv->is_filter) {
>> +        /* Filters always have a file or a backing child */
>> +        if (!bs->backing) {
>> +            error_setg(errp, "'%s' is a %s filter node that does not
>> support a "
>> +                       "backing child", bs->node_name,
>> bs->drv->format_name);
>> +            return -EINVAL;
>> +        }
>> +    } else if (!bs->drv->supports_backing) {
>> +        error_setg(errp, "Driver '%s' of node '%s' does not support
>> backing "
>> +                   "files", bs->drv->format_name, bs->node_name);
>> +        return -EINVAL;
>> +    }
>> +
>>       /*
>>        * Find the "actual" backing file by skipping all links that point
>>        * to an implicit node, if any (e.g. a commit filter node).
>> +     * We cannot use any of the bdrv_skip_*() functions here because
>> +     * those return the first explicit node, while we are looking for
>> +     * its overlay here.
>>        */
>>       overlay_bs = bs;
>> -    while (backing_bs(overlay_bs) && backing_bs(overlay_bs)->implicit) {
>> -        overlay_bs = backing_bs(overlay_bs);
>> +    while (bdrv_filter_or_cow_bs(overlay_bs) &&
>> +           bdrv_filter_or_cow_bs(overlay_bs)->implicit)
>> +    {
>> +        overlay_bs = bdrv_filter_or_cow_bs(overlay_bs);
>>       }
> 
> I believe that little optimization would work properly:
> 
> 
> for (BlockDriverState *below_bs = bdrv_filter_or_cow_bs(overlay_bs);
>        below_bs && below_bs->implicit;
>        below_bs = bdrv_filter_or_cow_bs(overlay_bs)) {
>          overlay_bs = below_bs;
> }

Looks good, thanks.

>>         /* If we want to replace the backing file we need some extra
>> checks */
>> -    if (new_backing_bs != backing_bs(overlay_bs)) {
>> +    if (new_backing_bs != bdrv_filter_or_cow_bs(overlay_bs)) {
>>           /* Check for implicit nodes between bs and its backing file */
>>           if (bs != overlay_bs) {
>>               error_setg(errp, "Cannot change backing link if '%s' has "
>>                          "an implicit backing file", bs->node_name);
>>               return -EPERM;
>>           }
>> -        /* Check if the backing link that we want to replace is
>> frozen */
>> -        if (bdrv_is_backing_chain_frozen(overlay_bs,
>> backing_bs(overlay_bs),
>> -                                         errp)) {
>> +        /*
>> +         * Check if the backing link that we want to replace is frozen.
>> +         * Note that
>> +         * bdrv_filter_or_cow_child(overlay_bs) == overlay_bs->backing,
>> +         * because we know that overlay_bs == bs, and that @bs
>> +         * either is a filter that uses ->backing or a COW format BDS
>> +         * with bs->drv->supports_backing == true.
>> +         */
>> +        if (bdrv_is_backing_chain_frozen(overlay_bs,
>> +                                        
>> child_bs(overlay_bs->backing), errp))
> What would be wrong with bdrv_filter_or_cow_bs(overlay_bs) here?

As the comment says, it’s the same thing.

I prefer ->backing here, because this function is about reopening the
->backing child.

>> +        {
>>               return -EPERM;
>>           }
>>           reopen_state->replace_backing_bs = true;
>> @@ -4196,7 +4226,7 @@ int bdrv_reopen_prepare(BDRVReopenState
>> *reopen_state, BlockReopenQueue *queue,
>>        * its metadata. Otherwise the 'backing' option can be omitted.
>>        */
>>       if (drv->supports_backing && reopen_state->backing_missing &&
>> -        (backing_bs(reopen_state->bs) ||
>> reopen_state->bs->backing_file[0])) {
> = BlockDriverState*
>> +        (reopen_state->bs->backing ||
>> reopen_state->bs->backing_file[0])) {
> 
> = BdrvChild*
> 
> Are we OK with that?

Sure, the question is whether it’s non-NULL, and BdrvChild.bs is always
non-NULL.

Max

Attachment: signature.asc
Description: OpenPGP digital signature


reply via email to

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