diff options
author | Kevin Wolf <kwolf@redhat.com> | 2017-12-18 16:05:48 +0100 |
---|---|---|
committer | Kevin Wolf <kwolf@redhat.com> | 2017-12-22 15:05:32 +0100 |
commit | d736f119dae6d292e8d60f2e02fa51a79524113e (patch) | |
tree | d43428b92070b16badcd30678dde7974e0be02ac /block | |
parent | 27e64474a384e68ca928fa875930b921b53d61f4 (diff) |
block: Allow graph changes in subtree drained section
We need to remember how many of the drain sections in which a node is
were recursive (i.e. subtree drain rather than node drain), so that they
can be correctly applied when children are added or removed during the
drained section.
With this change, it is safe to modify the graph even inside a
bdrv_subtree_drained_begin/end() section.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Diffstat (limited to 'block')
-rw-r--r-- | block/io.c | 28 |
1 files changed, 24 insertions, 4 deletions
diff --git a/block/io.c b/block/io.c index 6befef166d..7ea402352e 100644 --- a/block/io.c +++ b/block/io.c @@ -270,8 +270,8 @@ static void coroutine_fn bdrv_co_yield_to_drain(BlockDriverState *bs, assert(data.done); } -static void bdrv_do_drained_begin(BlockDriverState *bs, bool recursive, - BdrvChild *parent) +void bdrv_do_drained_begin(BlockDriverState *bs, bool recursive, + BdrvChild *parent) { BdrvChild *child, *next; @@ -290,6 +290,7 @@ static void bdrv_do_drained_begin(BlockDriverState *bs, bool recursive, bdrv_drain_recurse(bs); if (recursive) { + bs->recursive_quiesce_counter++; QLIST_FOREACH_SAFE(child, &bs->children, next, next) { bdrv_do_drained_begin(child->bs, true, child); } @@ -306,8 +307,8 @@ void bdrv_subtree_drained_begin(BlockDriverState *bs) bdrv_do_drained_begin(bs, true, NULL); } -static void bdrv_do_drained_end(BlockDriverState *bs, bool recursive, - BdrvChild *parent) +void bdrv_do_drained_end(BlockDriverState *bs, bool recursive, + BdrvChild *parent) { BdrvChild *child, *next; int old_quiesce_counter; @@ -327,6 +328,7 @@ static void bdrv_do_drained_end(BlockDriverState *bs, bool recursive, } if (recursive) { + bs->recursive_quiesce_counter--; QLIST_FOREACH_SAFE(child, &bs->children, next, next) { bdrv_do_drained_end(child->bs, true, child); } @@ -343,6 +345,24 @@ void bdrv_subtree_drained_end(BlockDriverState *bs) bdrv_do_drained_end(bs, true, NULL); } +void bdrv_apply_subtree_drain(BdrvChild *child, BlockDriverState *new_parent) +{ + int i; + + for (i = 0; i < new_parent->recursive_quiesce_counter; i++) { + bdrv_do_drained_begin(child->bs, true, child); + } +} + +void bdrv_unapply_subtree_drain(BdrvChild *child, BlockDriverState *old_parent) +{ + int i; + + for (i = 0; i < old_parent->recursive_quiesce_counter; i++) { + bdrv_do_drained_end(child->bs, true, child); + } +} + /* * Wait for pending requests to complete on a single BlockDriverState subtree, * and suspend block driver's internal I/O until next request arrives. |