block: make bdrv_unset_inherits_from to be a transaction action

To be used in the further commit.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Message-Id: <20210428151804.439460-27-vsementsov@virtuozzo.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
Vladimir Sementsov-Ogievskiy 2021-04-28 18:17:54 +03:00 committed by Kevin Wolf
parent 9397c14fcb
commit 332b3a175f

46
block.c
View File

@ -3205,11 +3205,49 @@ void bdrv_root_unref_child(BdrvChild *child)
bdrv_unref(child_bs); bdrv_unref(child_bs);
} }
typedef struct BdrvSetInheritsFrom {
BlockDriverState *bs;
BlockDriverState *old_inherits_from;
} BdrvSetInheritsFrom;
static void bdrv_set_inherits_from_abort(void *opaque)
{
BdrvSetInheritsFrom *s = opaque;
s->bs->inherits_from = s->old_inherits_from;
}
static TransactionActionDrv bdrv_set_inherits_from_drv = {
.abort = bdrv_set_inherits_from_abort,
.clean = g_free,
};
/* @tran is allowed to be NULL. In this case no rollback is possible */
static void bdrv_set_inherits_from(BlockDriverState *bs,
BlockDriverState *new_inherits_from,
Transaction *tran)
{
if (tran) {
BdrvSetInheritsFrom *s = g_new(BdrvSetInheritsFrom, 1);
*s = (BdrvSetInheritsFrom) {
.bs = bs,
.old_inherits_from = bs->inherits_from,
};
tran_add(tran, &bdrv_set_inherits_from_drv, s);
}
bs->inherits_from = new_inherits_from;
}
/** /**
* Clear all inherits_from pointers from children and grandchildren of * Clear all inherits_from pointers from children and grandchildren of
* @root that point to @root, where necessary. * @root that point to @root, where necessary.
* @tran is allowed to be NULL. In this case no rollback is possible
*/ */
static void bdrv_unset_inherits_from(BlockDriverState *root, BdrvChild *child) static void bdrv_unset_inherits_from(BlockDriverState *root, BdrvChild *child,
Transaction *tran)
{ {
BdrvChild *c; BdrvChild *c;
@ -3224,12 +3262,12 @@ static void bdrv_unset_inherits_from(BlockDriverState *root, BdrvChild *child)
} }
} }
if (c == NULL) { if (c == NULL) {
child->bs->inherits_from = NULL; bdrv_set_inherits_from(child->bs, NULL, tran);
} }
} }
QLIST_FOREACH(c, &child->bs->children, next) { QLIST_FOREACH(c, &child->bs->children, next) {
bdrv_unset_inherits_from(root, c); bdrv_unset_inherits_from(root, c, tran);
} }
} }
@ -3240,7 +3278,7 @@ void bdrv_unref_child(BlockDriverState *parent, BdrvChild *child)
return; return;
} }
bdrv_unset_inherits_from(parent, child); bdrv_unset_inherits_from(parent, child, NULL);
bdrv_root_unref_child(child); bdrv_root_unref_child(child);
} }