repair throttling code
PATCH 1/1 repair throttling code
since v3:
silence bogus checkpatch warning [abligh]
Benoît Canet (1):
block: Repair the throttling code.
block.c | 7 +++---- include/block/coroutine.h | 9 +++++++-- qemu-coroutine-lock.c | 20 ++++++++++++++++++-- 3 files changed, 28 insertions(+), 8 deletions(-)
Signature · 1 line
1.7.10.4
PATCH 1/1 block: Repair the throttling code.
The throttling code was segfaulting since commit 02ffb504485f0920cfc75a0982a602f824a9a4f4 because some qemu_co_queue_next caller does not run in a coroutine.qemu_co_queue_do_restart assume that the caller is a coroutinne. As suggested by Stefan fix this by entering the coroutine directly. Also make sure like suggested that qemu_co_queue_next() and qemu_co_queue_restart_all() can be called only in coroutines.
--- block.c | 7 +++---- include/block/coroutine.h | 9 +++++++-- qemu-coroutine-lock.c | 20 ++++++++++++++++++-- 3 files changed, 28 insertions(+), 8 deletions(-)
block.c +3 -4
@@ -127,7 +127,7 @@ void bdrv_io_limits_disable(BlockDriverState *bs) { bs->io_limits_enabled = false; -while (qemu_co_queue_next (&bs->throttled_reqs)); +do {}while (qemu_co_enter_next (&bs->throttled_reqs));if (bs->block_timer) {qemu_del_timer (bs->block_timer);
@@ -143,7 +143,7 @@ static void bdrv_block_timer(void *opaque) {BlockDriverState *bs = opaque; -qemu_co_queue_next (&bs->throttled_reqs); +qemu_co_enter_next (&bs->throttled_reqs); }void bdrv_io_limits_enable (BlockDriverState *bs)
@@ -1445,8 +1445,7 @@ void bdrv_drain_all(void)* a busy wait. */ QTAILQ_FOREACH(bs, &bdrv_states, list) { -if (!qemu_co_queue_empty (&bs->throttled_reqs)) { -qemu_co_queue_restart_all (&bs->throttled_reqs); +while (qemu_co_enter_next (&bs->throttled_reqs)) { busy = true; } }
include/block/coroutine.h +7 -2
@@ -130,12 +130,17 @@ void coroutine_fn qemu_co_queue_wait_insert_head(CoQueue *queue);* * Returns true if a coroutine was restarted, false if the queue is empty. */ -bool qemu_co_queue_next (CoQueue *queue); +bool coroutine_fn qemu_co_queue_next(CoQueue *queue);/** * Restarts all coroutines in the CoQueue and leaves the queue empty. */ -void qemu_co_queue_restart_all (CoQueue *queue); +void coroutine_fn qemu_co_queue_restart_all(CoQueue *queue); + +/** +* Enter the next coroutine in the queue +*/ +bool qemu_co_enter_next (CoQueue *queue);/** * Checks if the CoQueue is empty.
qemu-coroutine-lock.c +18 -2
@@ -88,16 +88,32 @@ static bool qemu_co_queue_do_restart(CoQueue *queue, bool single)return true; } -bool qemu_co_queue_next (CoQueue *queue) +bool coroutine_fn qemu_co_queue_next(CoQueue *queue) { +assert (qemu_in_coroutine ());return qemu_co_queue_do_restart (queue, true); } -void qemu_co_queue_restart_all (CoQueue *queue) +void coroutine_fn qemu_co_queue_restart_all(CoQueue *queue) { +assert (qemu_in_coroutine ());qemu_co_queue_do_restart (queue, false); } +bool qemu_co_enter_next (CoQueue *queue) +{ +Coroutine *next; + + next =QTAILQ_FIRST (&queue->entries); +if (!next) { +return false; + } + +QTAILQ_REMOVE (&queue->entries, next, co_queue_next); +qemu_coroutine_enter (next,NULL ); +return true; +} +bool qemu_co_queue_empty (CoQueue *queue) {return (QTAILQ_FIRST (&queue->entries) ==NULL );
Signature · 1 line
1.7.10.4
Stefan Hajnoczi
AppliedQuoted 11 lines · Benoît Canet
since v3:
silence bogus checkpatch warning [abligh]
Benoît Canet (1):
block: Repair the throttling code.block.c | 7 +++---- include/block/coroutine.h | 9 +++++++-- qemu-coroutine-lock.c | 20 ++++++++++++++++++-- 3 files changed, 28 insertions(+), 8 deletions(-)
Thanks, applied to my block tree:
https://github.com/stefanha/qemu/commits/block
Stefan