aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/block/block.h26
-rw-r--r--include/block/block_int.h17
2 files changed, 40 insertions, 3 deletions
diff --git a/include/block/block.h b/include/block/block.h
index 84257ab940..b7dc7d54ae 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -337,9 +337,29 @@ void bdrv_drain_all(void);
#define BDRV_POLL_WHILE(bs, cond) ({ \
bool waited_ = false; \
BlockDriverState *bs_ = (bs); \
- while ((cond)) { \
- aio_poll(bdrv_get_aio_context(bs_), true); \
- waited_ = true; \
+ AioContext *ctx_ = bdrv_get_aio_context(bs_); \
+ if (aio_context_in_iothread(ctx_)) { \
+ while ((cond)) { \
+ aio_poll(ctx_, true); \
+ waited_ = true; \
+ } \
+ } 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); \
+ bs_->wakeup = true; \
+ while ((cond)) { \
+ aio_context_release(ctx_); \
+ aio_poll(qemu_get_aio_context(), true); \
+ aio_context_acquire(ctx_); \
+ waited_ = true; \
+ } \
+ bs_->wakeup = false; \
} \
waited_; })
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 1044dfef43..e7ff58419c 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -475,6 +475,8 @@ struct BlockDriverState {
unsigned int in_flight;
unsigned int serialising_in_flight;
+ bool wakeup;
+
/* Offset after the highest byte written to */
uint64_t wr_highest_offset;
@@ -633,6 +635,21 @@ void bdrv_remove_aio_context_notifier(BlockDriverState *bs,
void (*aio_context_detached)(void *),
void *opaque);
+/**
+ * bdrv_wakeup:
+ * @bs: The BlockDriverState for which an I/O operation has been completed.
+ *
+ * Wake up the main thread if it is waiting on BDRV_POLL_WHILE. During
+ * synchronous I/O on a BlockDriverState that is attached to another
+ * I/O thread, the main thread lets the I/O thread's event loop run,
+ * waiting for the I/O operation to complete. A bdrv_wakeup will wake
+ * up the main thread if necessary.
+ *
+ * Manual calls to bdrv_wakeup are rarely necessary, because
+ * bdrv_dec_in_flight already calls it.
+ */
+void bdrv_wakeup(BlockDriverState *bs);
+
#ifdef _WIN32
int is_windows_drive(const char *filename);
#endif