[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 31/42] block: Add missing locking in bdrv_co_drain_bh
From: |
Max Reitz |
Subject: |
[Qemu-devel] [PULL 31/42] block: Add missing locking in bdrv_co_drain_bh_cb() |
Date: |
Tue, 25 Sep 2018 17:15:30 +0200 |
From: Kevin Wolf <address@hidden>
bdrv_do_drained_begin/end() assume that they are called with the
AioContext lock of bs held. If we call drain functions from a coroutine
with the AioContext lock held, we yield and schedule a BH to move out of
coroutine context. This means that the lock for the home context of the
coroutine is released and must be re-acquired in the bottom half.
Signed-off-by: Kevin Wolf <address@hidden>
Reviewed-by: Max Reitz <address@hidden>
---
include/qemu/coroutine.h | 5 +++++
block/io.c | 15 +++++++++++++++
util/qemu-coroutine.c | 5 +++++
3 files changed, 25 insertions(+)
diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h
index 6f8a487041..9801e7f5a4 100644
--- a/include/qemu/coroutine.h
+++ b/include/qemu/coroutine.h
@@ -89,6 +89,11 @@ void qemu_aio_coroutine_enter(AioContext *ctx, Coroutine
*co);
*/
void coroutine_fn qemu_coroutine_yield(void);
+/**
+ * Get the AioContext of the given coroutine
+ */
+AioContext *coroutine_fn qemu_coroutine_get_aio_context(Coroutine *co);
+
/**
* Get the currently executing coroutine
*/
diff --git a/block/io.c b/block/io.c
index 7100344c7b..914ba78f1a 100644
--- a/block/io.c
+++ b/block/io.c
@@ -288,6 +288,18 @@ static void bdrv_co_drain_bh_cb(void *opaque)
BlockDriverState *bs = data->bs;
if (bs) {
+ AioContext *ctx = bdrv_get_aio_context(bs);
+ AioContext *co_ctx = qemu_coroutine_get_aio_context(co);
+
+ /*
+ * When the coroutine yielded, the lock for its home context was
+ * released, so we need to re-acquire it here. If it explicitly
+ * acquired a different context, the lock is still held and we don't
+ * want to lock it a second time (or AIO_WAIT_WHILE() would hang).
+ */
+ if (ctx == co_ctx) {
+ aio_context_acquire(ctx);
+ }
bdrv_dec_in_flight(bs);
if (data->begin) {
bdrv_do_drained_begin(bs, data->recursive, data->parent,
@@ -296,6 +308,9 @@ static void bdrv_co_drain_bh_cb(void *opaque)
bdrv_do_drained_end(bs, data->recursive, data->parent,
data->ignore_bds_parents);
}
+ if (ctx == co_ctx) {
+ aio_context_release(ctx);
+ }
} else {
assert(data->begin);
bdrv_drain_all_begin();
diff --git a/util/qemu-coroutine.c b/util/qemu-coroutine.c
index 1ba4191b84..2295928d33 100644
--- a/util/qemu-coroutine.c
+++ b/util/qemu-coroutine.c
@@ -198,3 +198,8 @@ bool qemu_coroutine_entered(Coroutine *co)
{
return co->caller;
}
+
+AioContext *coroutine_fn qemu_coroutine_get_aio_context(Coroutine *co)
+{
+ return co->ctx;
+}
--
2.17.1
- [Qemu-devel] [PULL 21/42] qemu-iotests: Test snapshot=on with nonexistent TMPDIR, (continued)
- [Qemu-devel] [PULL 21/42] qemu-iotests: Test snapshot=on with nonexistent TMPDIR, Max Reitz, 2018/09/25
- [Qemu-devel] [PULL 22/42] util/async: use qemu_aio_coroutine_enter in co_schedule_bh_cb, Max Reitz, 2018/09/25
- [Qemu-devel] [PULL 24/42] job: Fix missing locking due to mismerge, Max Reitz, 2018/09/25
- [Qemu-devel] [PULL 25/42] blockjob: Wake up BDS when job becomes idle, Max Reitz, 2018/09/25
- [Qemu-devel] [PULL 26/42] aio-wait: Increase num_waiters even in home thread, Max Reitz, 2018/09/25
- [Qemu-devel] [PULL 23/42] job: Fix nested aio_poll() hanging in job_txn_apply, Max Reitz, 2018/09/25
- [Qemu-devel] [PULL 28/42] test-blockjob: Acquire AioContext around job_cancel_sync(), Max Reitz, 2018/09/25
- [Qemu-devel] [PULL 27/42] test-bdrv-drain: Drain with block jobs in an I/O thread, Max Reitz, 2018/09/25
- [Qemu-devel] [PULL 30/42] test-bdrv-drain: Test AIO_WAIT_WHILE() in completion callback, Max Reitz, 2018/09/25
- [Qemu-devel] [PULL 29/42] job: Use AIO_WAIT_WHILE() in job_finish_sync(), Max Reitz, 2018/09/25
- [Qemu-devel] [PULL 31/42] block: Add missing locking in bdrv_co_drain_bh_cb(),
Max Reitz <=
- [Qemu-devel] [PULL 32/42] block-backend: Add .drained_poll callback, Max Reitz, 2018/09/25
- [Qemu-devel] [PULL 34/42] block-backend: Decrease in_flight only after callback, Max Reitz, 2018/09/25
- [Qemu-devel] [PULL 33/42] block-backend: Fix potential double blk_delete(), Max Reitz, 2018/09/25
- [Qemu-devel] [PULL 35/42] blockjob: Lie better in child_job_drained_poll(), Max Reitz, 2018/09/25
- [Qemu-devel] [PULL 36/42] block: Remove aio_poll() in bdrv_drain_poll variants, Max Reitz, 2018/09/25
- [Qemu-devel] [PULL 38/42] job: Avoid deadlocks in job_completed_txn_abort(), Max Reitz, 2018/09/25
- [Qemu-devel] [PULL 37/42] test-bdrv-drain: Test nested poll in bdrv_drain_poll_top_level(), Max Reitz, 2018/09/25
- [Qemu-devel] [PULL 40/42] test-bdrv-drain: Fix outdated comments, Max Reitz, 2018/09/25
- [Qemu-devel] [PULL 39/42] test-bdrv-drain: AIO_WAIT_WHILE() in job .commit/.abort, Max Reitz, 2018/09/25
- [Qemu-devel] [PULL 42/42] test-bdrv-drain: Test draining job source child and parent, Max Reitz, 2018/09/25