qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [PATCH v6 20/42] block/snapshot: Fix fallback


From: Max Reitz
Subject: Re: [Qemu-devel] [PATCH v6 20/42] block/snapshot: Fix fallback
Date: Mon, 12 Aug 2019 15:06:59 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.8.0

On 10.08.19 18:34, Vladimir Sementsov-Ogievskiy wrote:
> 09.08.2019 19:13, Max Reitz wrote:
>> If the top node's driver does not provide snapshot functionality and we
>> want to fall back to a node down the chain, we need to snapshot all
>> non-COW children.  For simplicity's sake, just do not fall back if there
>> is more than one such child.
>>
>> bdrv_snapshot_goto() becomes a bit weird because we may have to redirect
>> the actual child pointer, so it only works if the fallback child is
>> bs->file or bs->backing (and then we have to find out which it is).
>>
>> Suggested-by: Vladimir Sementsov-Ogievskiy <address@hidden>
>> Signed-off-by: Max Reitz <address@hidden>
>> ---
>>   block/snapshot.c | 100 +++++++++++++++++++++++++++++++++++++----------
>>   1 file changed, 79 insertions(+), 21 deletions(-)
>>
>> diff --git a/block/snapshot.c b/block/snapshot.c
>> index f2f48f926a..35403c167f 100644
>> --- a/block/snapshot.c
>> +++ b/block/snapshot.c
>> @@ -146,6 +146,32 @@ bool bdrv_snapshot_find_by_id_and_name(BlockDriverState 
>> *bs,
>>       return ret;
>>   }
>>   
>> +/**
>> + * Return the child BDS to which we can fall back if the given BDS
>> + * does not support snapshots.
>> + * Return NULL if there is no BDS to (safely) fall back to.
>> + */
>> +static BlockDriverState *bdrv_snapshot_fallback(BlockDriverState *bs)
>> +{
>> +    BlockDriverState *child_bs = NULL;
>> +    BdrvChild *child;
>> +
>> +    QLIST_FOREACH(child, &bs->children, next) {
>> +        if (child == bdrv_filtered_cow_child(bs)) {
>> +            /* Ignore: COW children need not be included in snapshots */
>> +            continue;
>> +        }
>> +
>> +        if (child_bs) {
>> +            /* Cannot fall back to a single child if there are multiple */
>> +            return NULL;
>> +        }
>> +        child_bs = child->bs;
>> +    }
>> +
>> +    return child_bs;
>> +}
>> +
>>   int bdrv_can_snapshot(BlockDriverState *bs)
>>   {
>>       BlockDriver *drv = bs->drv;
>> @@ -154,8 +180,9 @@ int bdrv_can_snapshot(BlockDriverState *bs)
>>       }
>>   
>>       if (!drv->bdrv_snapshot_create) {
>> -        if (bs->file != NULL) {
>> -            return bdrv_can_snapshot(bs->file->bs);
>> +        BlockDriverState *fallback_bs = bdrv_snapshot_fallback(bs);
>> +        if (fallback_bs) {
>> +            return bdrv_can_snapshot(fallback_bs);
>>           }
>>           return 0;
>>       }
>> @@ -167,14 +194,15 @@ int bdrv_snapshot_create(BlockDriverState *bs,
>>                            QEMUSnapshotInfo *sn_info)
>>   {
>>       BlockDriver *drv = bs->drv;
>> +    BlockDriverState *fallback_bs = bdrv_snapshot_fallback(bs);
>>       if (!drv) {
>>           return -ENOMEDIUM;
>>       }
>>       if (drv->bdrv_snapshot_create) {
>>           return drv->bdrv_snapshot_create(bs, sn_info);
>>       }
>> -    if (bs->file) {
>> -        return bdrv_snapshot_create(bs->file->bs, sn_info);
>> +    if (fallback_bs) {
>> +        return bdrv_snapshot_create(fallback_bs, sn_info);
>>       }
>>       return -ENOTSUP;
>>   }
>> @@ -184,6 +212,7 @@ int bdrv_snapshot_goto(BlockDriverState *bs,
>>                          Error **errp)
>>   {
>>       BlockDriver *drv = bs->drv;
>> +    BlockDriverState *fallback_bs;
>>       int ret, open_ret;
>>   
>>       if (!drv) {
>> @@ -204,39 +233,66 @@ int bdrv_snapshot_goto(BlockDriverState *bs,
>>           return ret;
>>       }
>>   
>> -    if (bs->file) {
>> -        BlockDriverState *file;
>> -        QDict *options = qdict_clone_shallow(bs->options);
>> +    fallback_bs = bdrv_snapshot_fallback(bs);
>> +    if (fallback_bs) {
>> +        QDict *options;
>>           QDict *file_options;
>>           Error *local_err = NULL;
>> +        bool is_backing_child;
>> +        BdrvChild **child_pointer;
>> +
>> +        /*
>> +         * We need a pointer to the fallback child pointer, so let us
>> +         * see whether the child is referenced by a field in the BDS
>> +         * object.
>> +         */
>> +        if (fallback_bs == bs->file->bs) {
>> +            is_backing_child = false;
>> +            child_pointer = &bs->file;
>> +        } else if (fallback_bs == bs->backing->bs) {
>> +            is_backing_child = true;
>> +            child_pointer = &bs->backing;
>> +        } else {
>> +            /*
>> +             * The fallback child is not referenced by a field in the
>> +             * BDS object.  We cannot go on then.
>> +             */
>> +            error_setg(errp, "Block driver does not support snapshots");
>> +            return -ENOTSUP;
>> +        }
>> +
> 
> Hmm.. Should not this check be included into bdrv_snapshot_fallback(), to
> work only with file and backing?

I was under the impression that this was just special code for what
turned out to be bdrv_snapshot_load_tmp() now, because it seems so
weird.  (So I thought just making the restriction here wouldn’t really
be a limit.)

I was wrong.  This is used when applying snapshots, so it is important.
 If we make a restriction here, we should have it in all fallback code, yes.

> And could we allow fallback only for filters? Is there real usecase except 
> filters?
> Or may be, drop fallback at all?

raw isn’t a filter driver.  And rbd as a protocol supports snapshotting.
 Hence the fallback code, I presume.

Max

Attachment: signature.asc
Description: OpenPGP digital signature


reply via email to

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