BdrvChildRole child_role,
Error **errp);
-/* TODO: Remove when no longer needed */
-static void bdrv_inherited_options(BdrvChildRole role, bool parent_is_format,
- int *child_flags, QDict *child_options,
- int parent_flags, QDict *parent_options);
-static void bdrv_child_cb_attach(BdrvChild *child);
-static void bdrv_child_cb_detach(BdrvChild *child);
-
/* If non-zero, use only whitelisted block drivers */
static int use_bdrv_whitelist;
*child_flags &= ~BDRV_O_NATIVE_AIO;
}
-/*
- * Returns the options and flags that bs->file should get if a protocol driver
- * is expected, based on the given options and flags for the parent BDS
- */
-static void bdrv_protocol_options(BdrvChildRole role, bool parent_is_format,
- int *child_flags, QDict *child_options,
- int parent_flags, QDict *parent_options)
-{
- bdrv_inherited_options(BDRV_CHILD_IMAGE, true,
- child_flags, child_options,
- parent_flags, parent_options);
-}
-
-const BdrvChildClass child_file = {
- .parent_is_bds = true,
- .get_parent_desc = bdrv_child_get_parent_desc,
- .inherit_options = bdrv_protocol_options,
- .drained_begin = bdrv_child_cb_drained_begin,
- .drained_poll = bdrv_child_cb_drained_poll,
- .drained_end = bdrv_child_cb_drained_end,
- .attach = bdrv_child_cb_attach,
- .detach = bdrv_child_cb_detach,
- .inactivate = bdrv_child_cb_inactivate,
- .can_set_aio_ctx = bdrv_child_cb_can_set_aio_ctx,
- .set_aio_ctx = bdrv_child_cb_set_aio_ctx,
-};
-
-/*
- * Returns the options and flags that bs->file should get if the use of formats
- * (and not only protocols) is permitted for it, based on the given options and
- * flags for the parent BDS
- */
-static void bdrv_inherited_fmt_options(BdrvChildRole role,
- bool parent_is_format,
- int *child_flags, QDict *child_options,
- int parent_flags, QDict *parent_options)
-{
- bdrv_inherited_options(BDRV_CHILD_DATA, false,
- child_flags, child_options,
- parent_flags, parent_options);
-}
-
-const BdrvChildClass child_format = {
- .parent_is_bds = true,
- .get_parent_desc = bdrv_child_get_parent_desc,
- .inherit_options = bdrv_inherited_fmt_options,
- .drained_begin = bdrv_child_cb_drained_begin,
- .drained_poll = bdrv_child_cb_drained_poll,
- .drained_end = bdrv_child_cb_drained_end,
- .attach = bdrv_child_cb_attach,
- .detach = bdrv_child_cb_detach,
- .inactivate = bdrv_child_cb_inactivate,
- .can_set_aio_ctx = bdrv_child_cb_can_set_aio_ctx,
- .set_aio_ctx = bdrv_child_cb_set_aio_ctx,
-};
-
static void bdrv_backing_attach(BdrvChild *c)
{
BlockDriverState *parent = c->opaque;
parent->backing_blocker);
}
-/* XXX: Will be removed along with child_backing */
-static void bdrv_child_cb_attach_backing(BdrvChild *c)
-{
- if (!(c->role & BDRV_CHILD_COW)) {
- bdrv_backing_attach(c);
- }
- bdrv_child_cb_attach(c);
-}
-
static void bdrv_backing_detach(BdrvChild *c)
{
BlockDriverState *parent = c->opaque;
parent->backing_blocker = NULL;
}
-/* XXX: Will be removed along with child_backing */
-static void bdrv_child_cb_detach_backing(BdrvChild *c)
-{
- if (!(c->role & BDRV_CHILD_COW)) {
- bdrv_backing_detach(c);
- }
- bdrv_child_cb_detach(c);
-}
-
-/*
- * Returns the options and flags that bs->backing should get, based on the
- * given options and flags for the parent BDS
- */
-static void bdrv_backing_options(BdrvChildRole role, bool parent_is_format,
- int *child_flags, QDict *child_options,
- int parent_flags, QDict *parent_options)
-{
- bdrv_inherited_options(BDRV_CHILD_COW, true,
- child_flags, child_options,
- parent_flags, parent_options);
-}
-
static int bdrv_backing_update_filename(BdrvChild *c, BlockDriverState *base,
const char *filename, Error **errp)
{
return ret;
}
-const BdrvChildClass child_backing = {
- .parent_is_bds = true,
- .get_parent_desc = bdrv_child_get_parent_desc,
- .attach = bdrv_child_cb_attach_backing,
- .detach = bdrv_child_cb_detach_backing,
- .inherit_options = bdrv_backing_options,
- .drained_begin = bdrv_child_cb_drained_begin,
- .drained_poll = bdrv_child_cb_drained_poll,
- .drained_end = bdrv_child_cb_drained_end,
- .inactivate = bdrv_child_cb_inactivate,
- .update_filename = bdrv_backing_update_filename,
- .can_set_aio_ctx = bdrv_child_cb_can_set_aio_ctx,
- .set_aio_ctx = bdrv_child_cb_set_aio_ctx,
-};
-
/*
* Returns the options and flags that a generic child of a BDS should
* get, based on the given options and flags for the parent BDS.
}
static void bdrv_child_perm(BlockDriverState *bs, BlockDriverState *child_bs,
- BdrvChild *c, const BdrvChildClass *child_class,
- BdrvChildRole role, BlockReopenQueue *reopen_queue,
+ BdrvChild *c, BdrvChildRole role,
+ BlockReopenQueue *reopen_queue,
uint64_t parent_perm, uint64_t parent_shared,
uint64_t *nperm, uint64_t *nshared)
{
assert(bs->drv && bs->drv->bdrv_child_perm);
- bs->drv->bdrv_child_perm(bs, c, child_class, role, reopen_queue,
+ bs->drv->bdrv_child_perm(bs, c, role, reopen_queue,
parent_perm, parent_shared,
nperm, nshared);
/* TODO Take force_share from reopen_queue */
uint64_t cur_perm, cur_shared;
bool child_tighten_restr;
- bdrv_child_perm(bs, c->bs, c, c->klass, c->role, q,
+ bdrv_child_perm(bs, c->bs, c, c->role, q,
cumulative_perms, cumulative_shared_perms,
&cur_perm, &cur_shared);
ret = bdrv_child_check_perm(c, q, cur_perm, cur_shared, ignore_children,
/* Update all children */
QLIST_FOREACH(c, &bs->children, next) {
uint64_t cur_perm, cur_shared;
- bdrv_child_perm(bs, c->bs, c, c->klass, c->role, NULL,
+ bdrv_child_perm(bs, c->bs, c, c->role, NULL,
cumulative_perms, cumulative_shared_perms,
&cur_perm, &cur_shared);
bdrv_child_set_perm(c, cur_perm, cur_shared);
uint64_t perms, shared;
bdrv_get_cumulative_perm(bs, &parent_perms, &parent_shared);
- bdrv_child_perm(bs, c->bs, c, c->klass, c->role, NULL,
+ bdrv_child_perm(bs, c->bs, c, c->role, NULL,
parent_perms, parent_shared, &perms, &shared);
return bdrv_child_try_set_perm(c, perms, shared, errp);
}
-void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c,
- const BdrvChildClass *child_class,
- BdrvChildRole role,
- BlockReopenQueue *reopen_queue,
- uint64_t perm, uint64_t shared,
- uint64_t *nperm, uint64_t *nshared)
+/*
+ * Default implementation for .bdrv_child_perm() for block filters:
+ * Forward CONSISTENT_READ, WRITE, WRITE_UNCHANGED, and RESIZE to the
+ * filtered child.
+ */
+static void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c,
+ BdrvChildRole role,
+ BlockReopenQueue *reopen_queue,
+ uint64_t perm, uint64_t shared,
+ uint64_t *nperm, uint64_t *nshared)
{
*nperm = perm & DEFAULT_PERM_PASSTHROUGH;
*nshared = (shared & DEFAULT_PERM_PASSTHROUGH) | DEFAULT_PERM_UNCHANGED;
}
static void bdrv_default_perms_for_cow(BlockDriverState *bs, BdrvChild *c,
- const BdrvChildClass *child_class,
BdrvChildRole role,
BlockReopenQueue *reopen_queue,
uint64_t perm, uint64_t shared,
uint64_t *nperm, uint64_t *nshared)
{
- assert(child_class == &child_backing ||
- (child_class == &child_of_bds && (role & BDRV_CHILD_COW)));
+ assert(role & BDRV_CHILD_COW);
/*
* We want consistent read from backing files if the parent needs it.
}
static void bdrv_default_perms_for_storage(BlockDriverState *bs, BdrvChild *c,
- const BdrvChildClass *child_class,
BdrvChildRole role,
BlockReopenQueue *reopen_queue,
uint64_t perm, uint64_t shared,
{
int flags;
- assert(child_class == &child_file ||
- (child_class == &child_of_bds &&
- (role & (BDRV_CHILD_METADATA | BDRV_CHILD_DATA))));
+ assert(role & (BDRV_CHILD_METADATA | BDRV_CHILD_DATA));
flags = bdrv_reopen_get_flags(reopen_queue, bs);
* Apart from the modifications below, the same permissions are
* forwarded and left alone as for filters
*/
- bdrv_filter_default_perms(bs, c, child_class, role, reopen_queue,
+ bdrv_filter_default_perms(bs, c, role, reopen_queue,
perm, shared, &perm, &shared);
if (role & BDRV_CHILD_METADATA) {
*nshared = shared;
}
-void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
- const BdrvChildClass *child_class,
- BdrvChildRole role,
- BlockReopenQueue *reopen_queue,
- uint64_t perm, uint64_t shared,
- uint64_t *nperm, uint64_t *nshared)
+void bdrv_default_perms(BlockDriverState *bs, BdrvChild *c,
+ BdrvChildRole role, BlockReopenQueue *reopen_queue,
+ uint64_t perm, uint64_t shared,
+ uint64_t *nperm, uint64_t *nshared)
{
- bool backing = (child_class == &child_backing);
- assert(child_class == &child_backing || child_class == &child_file);
-
- if (!backing) {
- bdrv_default_perms_for_storage(bs, c, child_class, role, reopen_queue,
+ if (role & BDRV_CHILD_FILTERED) {
+ assert(!(role & (BDRV_CHILD_DATA | BDRV_CHILD_METADATA |
+ BDRV_CHILD_COW)));
+ bdrv_filter_default_perms(bs, c, role, reopen_queue,
+ perm, shared, nperm, nshared);
+ } else if (role & BDRV_CHILD_COW) {
+ assert(!(role & (BDRV_CHILD_DATA | BDRV_CHILD_METADATA)));
+ bdrv_default_perms_for_cow(bs, c, role, reopen_queue,
+ perm, shared, nperm, nshared);
+ } else if (role & (BDRV_CHILD_METADATA | BDRV_CHILD_DATA)) {
+ bdrv_default_perms_for_storage(bs, c, role, reopen_queue,
perm, shared, nperm, nshared);
} else {
- bdrv_default_perms_for_cow(bs, c, child_class, role, reopen_queue,
- perm, shared, nperm, nshared);
+ g_assert_not_reached();
}
}
bdrv_get_cumulative_perm(parent_bs, &perm, &shared_perm);
assert(parent_bs->drv);
- bdrv_child_perm(parent_bs, child_bs, NULL, child_class, child_role, NULL,
+ bdrv_child_perm(parent_bs, child_bs, NULL, child_role, NULL,
perm, shared_perm, &perm, &shared_perm);
child = bdrv_root_attach_child(child_bs, child_name, child_class,
return child != NULL;
}
+/*
+ * Return the BdrvChildRole for @bs's backing child. bs->backing is
+ * mostly used for COW backing children (role = COW), but also for
+ * filtered children (role = FILTERED | PRIMARY).
+ */
+static BdrvChildRole bdrv_backing_role(BlockDriverState *bs)
+{
+ if (bs->drv && bs->drv->is_filter) {
+ return BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY;
+ } else {
+ return BDRV_CHILD_COW;
+ }
+}
+
/*
* Sets the backing file link of a BDS. A new reference is created; callers
* which don't need their own reference any more must call bdrv_unref().
goto out;
}
- bs->backing = bdrv_attach_child(bs, backing_hd, "backing", &child_backing,
- 0, errp);
+ bs->backing = bdrv_attach_child(bs, backing_hd, "backing", &child_of_bds,
+ bdrv_backing_role(bs), errp);
/* If backing_hd was already part of bs's backing chain, and
* inherits_from pointed recursively to bs then let's update it to
* point directly to bs (else it will become NULL). */
}
backing_hd = bdrv_open_inherit(backing_filename, reference, options, 0, bs,
- &child_backing, 0, errp);
+ &child_of_bds, bdrv_backing_role(bs), errp);
if (!backing_hd) {
bs->open_flags |= BDRV_O_NO_BACKING;
error_prepend(errp, "Could not open backing file: ");
BlockDriverState *file_bs;
file_bs = bdrv_open_child_bs(filename, options, "file", bs,
- &child_file, 0, true, &local_err);
+ &child_of_bds, BDRV_CHILD_IMAGE,
+ true, &local_err);
if (local_err) {
goto fail;
}
if (state->replace_backing_bs && state->new_backing_bs) {
uint64_t nperm, nshared;
bdrv_child_perm(state->bs, state->new_backing_bs,
- NULL, &child_backing, 0, bs_queue,
- state->perm, state->shared_perm,
+ NULL, bdrv_backing_role(state->bs),
+ bs_queue, state->perm, state->shared_perm,
&nperm, &nshared);
ret = bdrv_check_update_perm(state->new_backing_bs, NULL,
nperm, nshared, NULL, NULL, errp);
} else {
uint64_t nperm, nshared;
- bdrv_child_perm(parent->state.bs, bs, c, c->klass, c->role, q,
+ bdrv_child_perm(parent->state.bs, bs, c, c->role, q,
parent->state.perm, parent->state.shared_perm,
&nperm, &nshared);
drv->bdrv_gather_child_options(bs, opts, backing_overridden);
} else {
QLIST_FOREACH(child, &bs->children, next) {
- if (child->klass == &child_backing && !backing_overridden) {
+ if (child == bs->backing && !backing_overridden) {
/* We can skip the backing BDS if it has not been overridden */
continue;
}