2022-03-03 22:43:44 +03:00
|
|
|
/*
|
|
|
|
* snapshot_access block driver
|
|
|
|
*
|
|
|
|
* Copyright (c) 2022 Virtuozzo International GmbH.
|
|
|
|
*
|
|
|
|
* Author:
|
|
|
|
* Sementsov-Ogievskiy Vladimir <vsementsov@virtuozzo.com>
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "qemu/osdep.h"
|
|
|
|
|
|
|
|
#include "sysemu/block-backend.h"
|
|
|
|
#include "qemu/cutils.h"
|
|
|
|
#include "block/block_int.h"
|
|
|
|
|
|
|
|
static coroutine_fn int
|
|
|
|
snapshot_access_co_preadv_part(BlockDriverState *bs,
|
|
|
|
int64_t offset, int64_t bytes,
|
|
|
|
QEMUIOVector *qiov, size_t qiov_offset,
|
|
|
|
BdrvRequestFlags flags)
|
|
|
|
{
|
|
|
|
if (flags) {
|
|
|
|
return -ENOTSUP;
|
|
|
|
}
|
|
|
|
|
|
|
|
return bdrv_co_preadv_snapshot(bs->file, offset, bytes, qiov, qiov_offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int coroutine_fn
|
|
|
|
snapshot_access_co_block_status(BlockDriverState *bs,
|
|
|
|
bool want_zero, int64_t offset,
|
|
|
|
int64_t bytes, int64_t *pnum,
|
|
|
|
int64_t *map, BlockDriverState **file)
|
|
|
|
{
|
|
|
|
return bdrv_co_snapshot_block_status(bs->file->bs, want_zero, offset,
|
|
|
|
bytes, pnum, map, file);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int coroutine_fn snapshot_access_co_pdiscard(BlockDriverState *bs,
|
|
|
|
int64_t offset, int64_t bytes)
|
|
|
|
{
|
|
|
|
return bdrv_co_pdiscard_snapshot(bs->file->bs, offset, bytes);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int coroutine_fn
|
|
|
|
snapshot_access_co_pwrite_zeroes(BlockDriverState *bs,
|
|
|
|
int64_t offset, int64_t bytes,
|
|
|
|
BdrvRequestFlags flags)
|
|
|
|
{
|
|
|
|
return -ENOTSUP;
|
|
|
|
}
|
|
|
|
|
|
|
|
static coroutine_fn int
|
|
|
|
snapshot_access_co_pwritev_part(BlockDriverState *bs,
|
|
|
|
int64_t offset, int64_t bytes,
|
|
|
|
QEMUIOVector *qiov, size_t qiov_offset,
|
|
|
|
BdrvRequestFlags flags)
|
|
|
|
{
|
|
|
|
return -ENOTSUP;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void snapshot_access_refresh_filename(BlockDriverState *bs)
|
|
|
|
{
|
|
|
|
pstrcpy(bs->exact_filename, sizeof(bs->exact_filename),
|
|
|
|
bs->file->bs->filename);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int snapshot_access_open(BlockDriverState *bs, QDict *options, int flags,
|
|
|
|
Error **errp)
|
|
|
|
{
|
block: Manipulate bs->file / bs->backing pointers in .attach/.detach
bs->file and bs->backing are a kind of duplication of part of
bs->children. But very useful diplication, so let's not drop them at
all:)
We should manage bs->file and bs->backing in same place, where we
manage bs->children, to keep them in sync.
Moreover, generic io paths are unprepared to BdrvChild without a bs, so
it's double good to clear bs->file / bs->backing when we detach the
child.
Detach is simple: if we detach bs->file or bs->backing child, just
set corresponding field to NULL.
Attach is a bit more complicated. But we still can precisely detect
should we set one of bs->file / bs->backing or not:
- if role is BDRV_CHILD_COW, we definitely deal with bs->backing
- else, if role is BDRV_CHILD_FILTERED (it must be also
BDRV_CHILD_PRIMARY), it's a filtered child. Use
bs->drv->filtered_child_is_backing to chose the pointer field to
modify.
- else, if role is BDRV_CHILD_PRIMARY, we deal with bs->file
- in all other cases, it's neither bs->backing nor bs->file. It's some
other child and we shouldn't care
OK. This change brings one more good thing: we can (and should) get rid
of all indirect pointers in the block-graph-change transactions:
bdrv_attach_child_common() stores BdrvChild** into transaction to clear
it on abort.
bdrv_attach_child_common() has two callers: bdrv_attach_child_noperm()
just pass-through this feature, bdrv_root_attach_child() doesn't need
the feature.
Look at bdrv_attach_child_noperm() callers:
- bdrv_attach_child() doesn't need the feature
- bdrv_set_file_or_backing_noperm() uses the feature to manage
bs->file and bs->backing, we don't want it anymore
- bdrv_append() uses the feature to manage bs->backing, again we
don't want it anymore
So, we should drop this stuff! Great!
We could probably keep BdrvChild** argument to keep the int return
value, but it seems not worth the complexity.
Finally, we now set .file / .backing automatically in generic code and
want to restring setting them by hand outside of .attach/.detach.
So, this patch cleanups all remaining places where they were set.
To find such places I use:
git grep '\->file ='
git grep '\->backing ='
git grep '&.*\<backing\>'
git grep '&.*\<file\>'
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
Message-Id: <20220726201134.924743-14-vsementsov@yandex-team.ru>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2022-07-26 23:11:32 +03:00
|
|
|
bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
|
|
|
|
BDRV_CHILD_DATA | BDRV_CHILD_PRIMARY,
|
|
|
|
false, errp);
|
2022-03-03 22:43:44 +03:00
|
|
|
if (!bs->file) {
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
bs->total_sectors = bs->file->bs->total_sectors;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void snapshot_access_child_perm(BlockDriverState *bs, BdrvChild *c,
|
|
|
|
BdrvChildRole role,
|
|
|
|
BlockReopenQueue *reopen_queue,
|
|
|
|
uint64_t perm, uint64_t shared,
|
|
|
|
uint64_t *nperm, uint64_t *nshared)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Currently, we don't need any permissions. If bs->file provides
|
|
|
|
* snapshot-access API, we can use it.
|
|
|
|
*/
|
|
|
|
*nperm = 0;
|
|
|
|
*nshared = BLK_PERM_ALL;
|
|
|
|
}
|
|
|
|
|
|
|
|
BlockDriver bdrv_snapshot_access_drv = {
|
|
|
|
.format_name = "snapshot-access",
|
|
|
|
|
|
|
|
.bdrv_open = snapshot_access_open,
|
|
|
|
|
|
|
|
.bdrv_co_preadv_part = snapshot_access_co_preadv_part,
|
|
|
|
.bdrv_co_pwritev_part = snapshot_access_co_pwritev_part,
|
|
|
|
.bdrv_co_pwrite_zeroes = snapshot_access_co_pwrite_zeroes,
|
|
|
|
.bdrv_co_pdiscard = snapshot_access_co_pdiscard,
|
|
|
|
.bdrv_co_block_status = snapshot_access_co_block_status,
|
|
|
|
|
|
|
|
.bdrv_refresh_filename = snapshot_access_refresh_filename,
|
|
|
|
|
|
|
|
.bdrv_child_perm = snapshot_access_child_perm,
|
|
|
|
};
|
|
|
|
|
|
|
|
static void snapshot_access_init(void)
|
|
|
|
{
|
|
|
|
bdrv_register(&bdrv_snapshot_access_drv);
|
|
|
|
}
|
|
|
|
|
|
|
|
block_init(snapshot_access_init);
|