diff options
author | Stefan Hajnoczi <stefanha@redhat.com> | 2018-02-16 16:50:12 +0000 |
---|---|---|
committer | Kevin Wolf <kwolf@redhat.com> | 2018-03-02 18:39:07 +0100 |
commit | 7719f3c968c59e1bcda7e177679dc765b59e578f (patch) | |
tree | 9a712da144732941764479a42272a493098339f7 /include/block/block.h | |
parent | d2b63ba8dd20c1091b3f1033e6a95ef95b18149d (diff) |
block: extract AIO_WAIT_WHILE() from BlockDriverState
BlockDriverState has the BDRV_POLL_WHILE() macro to wait on event loop
activity while a condition evaluates to true. This is used to implement
synchronous operations where it acts as a condvar between the IOThread
running the operation and the main loop waiting for the operation. It
can also be called from the thread that owns the AioContext and in that
case it's just a nested event loop.
BlockBackend needs this behavior but doesn't always have a
BlockDriverState it can use. This patch extracts BDRV_POLL_WHILE() into
the AioWait abstraction, which can be used with AioContext and isn't
tied to BlockDriverState anymore.
This feature could be built directly into AioContext but then all users
would kick the event loop even if they signal different conditions.
Imagine an AioContext with many BlockDriverStates, each time a request
completes any waiter would wake up and re-check their condition. It's
nicer to keep a separate AioWait object for each condition instead.
Please see "block/aio-wait.h" for details on the API.
The name AIO_WAIT_WHILE() avoids the confusion between AIO_POLL_WHILE()
and AioContext polling.
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Diffstat (limited to 'include/block/block.h')
-rw-r--r-- | include/block/block.h | 40 |
1 files changed, 7 insertions, 33 deletions
diff --git a/include/block/block.h b/include/block/block.h index bc41ed253b..4a80a2acd4 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -2,6 +2,7 @@ #define BLOCK_H #include "block/aio.h" +#include "block/aio-wait.h" #include "qapi-types.h" #include "qemu/iov.h" #include "qemu/coroutine.h" @@ -367,41 +368,14 @@ void bdrv_drain_all_begin(void); void bdrv_drain_all_end(void); void bdrv_drain_all(void); +/* Returns NULL when bs == NULL */ +AioWait *bdrv_get_aio_wait(BlockDriverState *bs); + #define BDRV_POLL_WHILE(bs, cond) ({ \ - bool waited_ = false; \ - bool busy_ = true; \ BlockDriverState *bs_ = (bs); \ - AioContext *ctx_ = bdrv_get_aio_context(bs_); \ - if (in_aio_context_home_thread(ctx_)) { \ - while ((cond) || busy_) { \ - busy_ = aio_poll(ctx_, (cond)); \ - waited_ |= !!(cond) | busy_; \ - } \ - } else { \ - assert(qemu_get_current_aio_context() == \ - qemu_get_aio_context()); \ - /* Ask bdrv_dec_in_flight to wake up the main \ - * QEMU AioContext. Extra I/O threads never take \ - * other I/O threads' AioContexts (see for example \ - * block_job_defer_to_main_loop for how to do it). \ - */ \ - assert(!bs_->wakeup); \ - /* Set bs->wakeup before evaluating cond. */ \ - atomic_mb_set(&bs_->wakeup, true); \ - while (busy_) { \ - if ((cond)) { \ - waited_ = busy_ = true; \ - aio_context_release(ctx_); \ - aio_poll(qemu_get_aio_context(), true); \ - aio_context_acquire(ctx_); \ - } else { \ - busy_ = aio_poll(ctx_, false); \ - waited_ |= busy_; \ - } \ - } \ - atomic_set(&bs_->wakeup, false); \ - } \ - waited_; }) + AIO_WAIT_WHILE(bdrv_get_aio_wait(bs_), \ + bdrv_get_aio_context(bs_), \ + cond); }) int bdrv_pdiscard(BlockDriverState *bs, int64_t offset, int bytes); int bdrv_co_pdiscard(BlockDriverState *bs, int64_t offset, int bytes); |