diff options
author | Kevin Wolf <kwolf@redhat.com> | 2018-03-22 14:11:20 +0100 |
---|---|---|
committer | Kevin Wolf <kwolf@redhat.com> | 2018-06-18 15:03:25 +0200 |
commit | 89bd030533e3592ca0a995450dcfc5d53e459e20 (patch) | |
tree | 565f35b4251f99f5ea34d1d19f03a979f36c6df8 /include | |
parent | 1cc8e54ada97f7ac479554e15ca9e426c895b158 (diff) |
block: Really pause block jobs on drain
We already requested that block jobs be paused in .bdrv_drained_begin,
but no guarantee was made that the job was actually inactive at the
point where bdrv_drained_begin() returned.
This introduces a new callback BdrvChildRole.bdrv_drained_poll() and
uses it to make bdrv_drain_poll() consider block jobs using the node to
be drained.
For the test case to work as expected, we have to switch from
block_job_sleep_ns() to qemu_co_sleep_ns() so that the test job is even
considered active and must be waited for when draining the node.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Diffstat (limited to 'include')
-rw-r--r-- | include/block/block.h | 8 | ||||
-rw-r--r-- | include/block/block_int.h | 7 | ||||
-rw-r--r-- | include/block/blockjob_int.h | 8 |
3 files changed, 23 insertions, 0 deletions
diff --git a/include/block/block.h b/include/block/block.h index e677080c4e..cebbb39c6c 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -568,6 +568,14 @@ void bdrv_parent_drained_begin(BlockDriverState *bs, BdrvChild *ignore); void bdrv_parent_drained_end(BlockDriverState *bs, BdrvChild *ignore); /** + * bdrv_drain_poll: + * + * Poll for pending requests in @bs and its parents (except for + * @ignore_parent). This is part of bdrv_drained_begin. + */ +bool bdrv_drain_poll(BlockDriverState *bs, BdrvChild *ignore_parent); + +/** * bdrv_drained_begin: * * Begin a quiesced section for exclusive access to the BDS, by disabling diff --git a/include/block/block_int.h b/include/block/block_int.h index 327e478a73..1b811db8ec 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -605,6 +605,13 @@ struct BdrvChildRole { void (*drained_begin)(BdrvChild *child); void (*drained_end)(BdrvChild *child); + /* + * Returns whether the parent has pending requests for the child. This + * callback is polled after .drained_begin() has been called until all + * activity on the child has stopped. + */ + bool (*drained_poll)(BdrvChild *child); + /* Notifies the parent that the child has been activated/inactivated (e.g. * when migration is completing) and it can start/stop requesting * permissions and doing I/O on it. */ diff --git a/include/block/blockjob_int.h b/include/block/blockjob_int.h index 5cd50c6639..e4a318dd15 100644 --- a/include/block/blockjob_int.h +++ b/include/block/blockjob_int.h @@ -39,6 +39,14 @@ struct BlockJobDriver { JobDriver job_driver; /* + * Returns whether the job has pending requests for the child or will + * submit new requests before the next pause point. This callback is polled + * in the context of draining a job node after requesting that the job be + * paused, until all activity on the child has stopped. + */ + bool (*drained_poll)(BlockJob *job); + + /* * If the callback is not NULL, it will be invoked before the job is * resumed in a new AioContext. This is the place to move any resources * besides job->blk to the new AioContext. |