[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
signature.asc
Description: OpenPGP digital signature
- Re: [Qemu-devel] [PATCH v6 15/42] block: Re-evaluate backing file handling in reopen, (continued)
- [Qemu-devel] [PATCH v6 16/42] block: Flush all children in generic code, Max Reitz, 2019/08/09
- [Qemu-devel] [PATCH v6 17/42] block: Use CAFs in bdrv_refresh_limits(), Max Reitz, 2019/08/09
- [Qemu-devel] [PATCH v6 18/42] block: Use CAFs in bdrv_refresh_filename(), Max Reitz, 2019/08/09
- [Qemu-devel] [PATCH v6 19/42] block: Use CAF in bdrv_co_rw_vmstate(), Max Reitz, 2019/08/09
- [Qemu-devel] [PATCH v6 20/42] block/snapshot: Fix fallback, Max Reitz, 2019/08/09
- [Qemu-devel] [PATCH v6 21/42] block: Use CAFs for debug breakpoints, Max Reitz, 2019/08/09
- [Qemu-devel] [PATCH v6 22/42] block: Fix bdrv_get_allocated_file_size's fallback, Max Reitz, 2019/08/09
[Qemu-devel] [PATCH v6 23/42] blockdev: Use CAF in external_snapshot_prepare(), Max Reitz, 2019/08/09
[Qemu-devel] [PATCH v6 24/42] block: Use child access functions for QAPI queries, Max Reitz, 2019/08/09
[Qemu-devel] [PATCH v6 26/42] backup: Deal with filters, Max Reitz, 2019/08/09