Message ID | 1601383109-110988-3-git-send-email-andrey.shinkevich@virtuozzo.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Apply COR-filter to the block-stream permanently | expand |
29.09.2020 15:38, Andrey Shinkevich wrote: > Provide API for the COR-filter insertion/removal. > Also, drop the filter child permissions for an inactive state when the > filter node is being removed. > > Signed-off-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com> > --- > block/copy-on-read.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++ > block/copy-on-read.h | 35 ++++++++++++++++++++++ > 2 files changed, 119 insertions(+) > create mode 100644 block/copy-on-read.h > > diff --git a/block/copy-on-read.c b/block/copy-on-read.c > index cb03e0f..3c8231f 100644 > --- a/block/copy-on-read.c > +++ b/block/copy-on-read.c > @@ -23,11 +23,21 @@ > #include "qemu/osdep.h" > #include "block/block_int.h" > #include "qemu/module.h" > +#include "qapi/error.h" > +#include "qapi/qmp/qdict.h" > +#include "block/copy-on-read.h" > + > + > +typedef struct BDRVStateCOR { > + bool active; > +} BDRVStateCOR; > > > static int cor_open(BlockDriverState *bs, QDict *options, int flags, > Error **errp) > { > + BDRVStateCOR *state = bs->opaque; > + > bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, > BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, > false, errp); > @@ -42,6 +52,13 @@ static int cor_open(BlockDriverState *bs, QDict *options, int flags, > ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) & > bs->file->bs->supported_zero_flags); > > + state->active = true; > + > + /* > + * We don't need to call bdrv_child_refresh_perms() now as the permissions > + * will be updated later when the filter node gets its parent. > + */ > + > return 0; > } > > @@ -57,6 +74,17 @@ static void cor_child_perm(BlockDriverState *bs, BdrvChild *c, > uint64_t perm, uint64_t shared, > uint64_t *nperm, uint64_t *nshared) > { > + BDRVStateCOR *s = bs->opaque; > + > + if (!s->active) { > + /* > + * While the filter is being removed > + */ > + *nperm = 0; > + *nshared = BLK_PERM_ALL; > + return; > + } > + > *nperm = perm & PERM_PASSTHROUGH; > *nshared = (shared & PERM_PASSTHROUGH) | PERM_UNCHANGED; > > @@ -135,6 +163,7 @@ static void cor_lock_medium(BlockDriverState *bs, bool locked) > > static BlockDriver bdrv_copy_on_read = { > .format_name = "copy-on-read", > + .instance_size = sizeof(BDRVStateCOR), > > .bdrv_open = cor_open, > .bdrv_child_perm = cor_child_perm, > @@ -159,4 +188,59 @@ static void bdrv_copy_on_read_init(void) > bdrv_register(&bdrv_copy_on_read); > } > > + > +BlockDriverState *bdrv_cor_filter_append(BlockDriverState *bs, > + QDict *node_options, > + int flags, Error **errp) Ok, now function can add ~any filter, not only COR.. But it's a pair for bdrv_cor_filter_drop(), and with "active" hack we don't want make the functions generic I think. So it's OK for now to keep function here and named _cor_. > +{ > + BlockDriverState *cor_filter_bs; > + Error *local_err = NULL; > + > + cor_filter_bs = bdrv_open(NULL, NULL, node_options, flags, errp); > + if (cor_filter_bs == NULL) { > + error_prepend(errp, "Could not create COR-filter node: "); > + return NULL; > + } You've dropped setting ->implicit field if filter_node_name not specified. Probably caller now can do it.. I don't really care about implicit case, so it's OK for me if it works with iotests. So, Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
On 05.10.2020 16:34, Vladimir Sementsov-Ogievskiy wrote: > 29.09.2020 15:38, Andrey Shinkevich wrote: >> Provide API for the COR-filter insertion/removal. >> Also, drop the filter child permissions for an inactive state when the >> filter node is being removed. >> >> Signed-off-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com> >> --- >> block/copy-on-read.c | 84 >> ++++++++++++++++++++++++++++++++++++++++++++++++++++ >> block/copy-on-read.h | 35 ++++++++++++++++++++++ >> 2 files changed, 119 insertions(+) >> create mode 100644 block/copy-on-read.h >> >> diff --git a/block/copy-on-read.c b/block/copy-on-read.c >> index cb03e0f..3c8231f 100644 >> --- a/block/copy-on-read.c >> +++ b/block/copy-on-read.c >> @@ -23,11 +23,21 @@ >> #include "qemu/osdep.h" >> #include "block/block_int.h" >> #include "qemu/module.h" >> +#include "qapi/error.h" >> +#include "qapi/qmp/qdict.h" >> +#include "block/copy-on-read.h" >> + >> + >> +typedef struct BDRVStateCOR { >> + bool active; >> +} BDRVStateCOR; >> static int cor_open(BlockDriverState *bs, QDict *options, int flags, >> Error **errp) >> { >> + BDRVStateCOR *state = bs->opaque; >> + >> bs->file = bdrv_open_child(NULL, options, "file", bs, >> &child_of_bds, >> BDRV_CHILD_FILTERED | >> BDRV_CHILD_PRIMARY, >> false, errp); >> @@ -42,6 +52,13 @@ static int cor_open(BlockDriverState *bs, QDict >> *options, int flags, >> ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) & >> bs->file->bs->supported_zero_flags); >> + state->active = true; >> + >> + /* >> + * We don't need to call bdrv_child_refresh_perms() now as the >> permissions >> + * will be updated later when the filter node gets its parent. >> + */ >> + >> return 0; >> } >> @@ -57,6 +74,17 @@ static void cor_child_perm(BlockDriverState *bs, >> BdrvChild *c, >> uint64_t perm, uint64_t shared, >> uint64_t *nperm, uint64_t *nshared) >> { >> + BDRVStateCOR *s = bs->opaque; >> + >> + if (!s->active) { >> + /* >> + * While the filter is being removed >> + */ >> + *nperm = 0; >> + *nshared = BLK_PERM_ALL; >> + return; >> + } >> + >> *nperm = perm & PERM_PASSTHROUGH; >> *nshared = (shared & PERM_PASSTHROUGH) | PERM_UNCHANGED; >> @@ -135,6 +163,7 @@ static void cor_lock_medium(BlockDriverState *bs, >> bool locked) >> static BlockDriver bdrv_copy_on_read = { >> .format_name = "copy-on-read", >> + .instance_size = sizeof(BDRVStateCOR), >> .bdrv_open = cor_open, >> .bdrv_child_perm = cor_child_perm, >> @@ -159,4 +188,59 @@ static void bdrv_copy_on_read_init(void) >> bdrv_register(&bdrv_copy_on_read); >> } >> + >> +BlockDriverState *bdrv_cor_filter_append(BlockDriverState *bs, >> + QDict *node_options, >> + int flags, Error **errp) > > > Ok, now function can add ~any filter, not only COR.. But it's a pair for > bdrv_cor_filter_drop(), and with "active" hack we don't want make the > functions generic I think. So it's OK for now to keep function here and > named _cor_. > >> +{ >> + BlockDriverState *cor_filter_bs; >> + Error *local_err = NULL; >> + >> + cor_filter_bs = bdrv_open(NULL, NULL, node_options, flags, errp); >> + if (cor_filter_bs == NULL) { >> + error_prepend(errp, "Could not create COR-filter node: "); >> + return NULL; >> + } > > You've dropped setting ->implicit field if filter_node_name not > specified. Probably caller now can do it.. I don't really care about > implicit case, so it's OK for me if it works with iotests. Thank you for your R-B. The idea behind setting the 'implicit' member by a caller is to prepare the code for the node replacement by a function at the block generic layer in future. In the scope of this series, that may be better to keep it here. Andrey > > So, > > Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> > >
diff --git a/block/copy-on-read.c b/block/copy-on-read.c index cb03e0f..3c8231f 100644 --- a/block/copy-on-read.c +++ b/block/copy-on-read.c @@ -23,11 +23,21 @@ #include "qemu/osdep.h" #include "block/block_int.h" #include "qemu/module.h" +#include "qapi/error.h" +#include "qapi/qmp/qdict.h" +#include "block/copy-on-read.h" + + +typedef struct BDRVStateCOR { + bool active; +} BDRVStateCOR; static int cor_open(BlockDriverState *bs, QDict *options, int flags, Error **errp) { + BDRVStateCOR *state = bs->opaque; + bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds, BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, false, errp); @@ -42,6 +52,13 @@ static int cor_open(BlockDriverState *bs, QDict *options, int flags, ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) & bs->file->bs->supported_zero_flags); + state->active = true; + + /* + * We don't need to call bdrv_child_refresh_perms() now as the permissions + * will be updated later when the filter node gets its parent. + */ + return 0; } @@ -57,6 +74,17 @@ static void cor_child_perm(BlockDriverState *bs, BdrvChild *c, uint64_t perm, uint64_t shared, uint64_t *nperm, uint64_t *nshared) { + BDRVStateCOR *s = bs->opaque; + + if (!s->active) { + /* + * While the filter is being removed + */ + *nperm = 0; + *nshared = BLK_PERM_ALL; + return; + } + *nperm = perm & PERM_PASSTHROUGH; *nshared = (shared & PERM_PASSTHROUGH) | PERM_UNCHANGED; @@ -135,6 +163,7 @@ static void cor_lock_medium(BlockDriverState *bs, bool locked) static BlockDriver bdrv_copy_on_read = { .format_name = "copy-on-read", + .instance_size = sizeof(BDRVStateCOR), .bdrv_open = cor_open, .bdrv_child_perm = cor_child_perm, @@ -159,4 +188,59 @@ static void bdrv_copy_on_read_init(void) bdrv_register(&bdrv_copy_on_read); } + +BlockDriverState *bdrv_cor_filter_append(BlockDriverState *bs, + QDict *node_options, + int flags, Error **errp) +{ + BlockDriverState *cor_filter_bs; + Error *local_err = NULL; + + cor_filter_bs = bdrv_open(NULL, NULL, node_options, flags, errp); + if (cor_filter_bs == NULL) { + error_prepend(errp, "Could not create COR-filter node: "); + return NULL; + } + + bdrv_drained_begin(bs); + bdrv_replace_node(bs, cor_filter_bs, &local_err); + bdrv_drained_end(bs); + + if (local_err) { + bdrv_unref(cor_filter_bs); + error_propagate(errp, local_err); + return NULL; + } + + return cor_filter_bs; +} + + +void bdrv_cor_filter_drop(BlockDriverState *cor_filter_bs) +{ + BdrvChild *child; + BlockDriverState *bs; + BDRVStateCOR *s = cor_filter_bs->opaque; + + child = bdrv_filter_child(cor_filter_bs); + if (!child) { + return; + } + bs = child->bs; + + /* Retain the BDS until we complete the graph change. */ + bdrv_ref(bs); + /* Hold a guest back from writing while permissions are being reset. */ + bdrv_drained_begin(bs); + /* Drop permissions before the graph change. */ + s->active = false; + bdrv_child_refresh_perms(cor_filter_bs, child, &error_abort); + bdrv_replace_node(cor_filter_bs, bs, &error_abort); + + bdrv_drained_end(bs); + bdrv_unref(bs); + bdrv_unref(cor_filter_bs); +} + + block_init(bdrv_copy_on_read_init); diff --git a/block/copy-on-read.h b/block/copy-on-read.h new file mode 100644 index 0000000..d6f2422 --- /dev/null +++ b/block/copy-on-read.h @@ -0,0 +1,35 @@ +/* + * Copy-on-read filter block driver + * + * The filter driver performs Copy-On-Read (COR) operations + * + * Copyright (c) 2018-2020 Virtuozzo International GmbH. + * + * Author: + * Andrey Shinkevich <andrey.shinkevich@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/>. + */ + +#ifndef BLOCK_COPY_ON_READ +#define BLOCK_COPY_ON_READ + +#include "block/block_int.h" + +BlockDriverState *bdrv_cor_filter_append(BlockDriverState *bs, + QDict *node_options, + int flags, Error **errp); +void bdrv_cor_filter_drop(BlockDriverState *cor_filter_bs); + +#endif /* BLOCK_COPY_ON_READ */
Provide API for the COR-filter insertion/removal. Also, drop the filter child permissions for an inactive state when the filter node is being removed. Signed-off-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com> --- block/copy-on-read.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++ block/copy-on-read.h | 35 ++++++++++++++++++++++ 2 files changed, 119 insertions(+) create mode 100644 block/copy-on-read.h