diff options
Diffstat (limited to 'include')
| -rw-r--r-- | include/block/block.h | 42 | ||||
| -rw-r--r-- | include/block/block_int.h | 15 |
2 files changed, 42 insertions, 15 deletions
diff --git a/include/block/block.h b/include/block/block.h index 734c9d2f76..60f00479e0 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -601,15 +601,6 @@ void bdrv_io_plug(BlockDriverState *bs); void bdrv_io_unplug(BlockDriverState *bs); /** - * bdrv_parent_drained_begin: - * - * Begin a quiesced section of all users of @bs. This is part of - * bdrv_drained_begin. - */ -void bdrv_parent_drained_begin(BlockDriverState *bs, BdrvChild *ignore, - bool ignore_bds_parents); - -/** * bdrv_parent_drained_begin_single: * * Begin a quiesced section for the parent of @c. If @poll is true, wait for @@ -618,13 +609,14 @@ void bdrv_parent_drained_begin(BlockDriverState *bs, BdrvChild *ignore, void bdrv_parent_drained_begin_single(BdrvChild *c, bool poll); /** - * bdrv_parent_drained_end: + * bdrv_parent_drained_end_single: + * + * End a quiesced section for the parent of @c. * - * End a quiesced section of all users of @bs. This is part of - * bdrv_drained_end. + * This polls @bs's AioContext until all scheduled sub-drained_ends + * have settled, which may result in graph changes. */ -void bdrv_parent_drained_end(BlockDriverState *bs, BdrvChild *ignore, - bool ignore_bds_parents); +void bdrv_parent_drained_end_single(BdrvChild *c); /** * bdrv_drain_poll: @@ -672,10 +664,32 @@ void bdrv_subtree_drained_begin(BlockDriverState *bs); * bdrv_drained_end: * * End a quiescent section started by bdrv_drained_begin(). + * + * This polls @bs's AioContext until all scheduled sub-drained_ends + * have settled. On one hand, that may result in graph changes. On + * the other, this requires that all involved nodes (@bs and all of + * its parents) are in the same AioContext, and that the caller has + * acquired it. + * If there are any nodes that are in different contexts from @bs, + * these contexts must not be acquired. */ void bdrv_drained_end(BlockDriverState *bs); /** + * bdrv_drained_end_no_poll: + * + * Same as bdrv_drained_end(), but do not poll for the subgraph to + * actually become unquiesced. Therefore, no graph changes will occur + * with this function. + * + * *drained_end_counter is incremented for every background operation + * that is scheduled, and will be decremented for every operation once + * it settles. The caller must poll until it reaches 0. The counter + * should be accessed using atomic operations only. + */ +void bdrv_drained_end_no_poll(BlockDriverState *bs, int *drained_end_counter); + +/** * End a quiescent section started by bdrv_subtree_drained_begin(). */ void bdrv_subtree_drained_end(BlockDriverState *bs); diff --git a/include/block/block_int.h b/include/block/block_int.h index 50902531b7..3aa1e832a8 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -664,11 +664,15 @@ struct BdrvChildRole { * These functions must not change the graph (and therefore also must not * call aio_poll(), which could change the graph indirectly). * + * If drained_end() schedules background operations, it must atomically + * increment *drained_end_counter for each such operation and atomically + * decrement it once the operation has settled. + * * Note that this can be nested. If drained_begin() was called twice, new * I/O is allowed only after drained_end() was called twice, too. */ void (*drained_begin)(BdrvChild *child); - void (*drained_end)(BdrvChild *child); + void (*drained_end)(BdrvChild *child, int *drained_end_counter); /* * Returns whether the parent has pending requests for the child. This @@ -729,6 +733,15 @@ struct BdrvChild { */ bool frozen; + /* + * How many times the parent of this child has been drained + * (through role->drained_*). + * Usually, this is equal to bs->quiesce_counter (potentially + * reduced by bdrv_drain_all_count). It may differ while the + * child is entering or leaving a drained section. + */ + int parent_quiesce_counter; + QLIST_ENTRY(BdrvChild) next; QLIST_ENTRY(BdrvChild) next_parent; }; |