diff --git a/include/block/aio.h b/include/block/aio.h index 433e7ff8b6..c23de3cd1f 100644 --- a/include/block/aio.h +++ b/include/block/aio.h @@ -214,9 +214,9 @@ bool aio_pending(AioContext *ctx); /* Progress in completing AIO work to occur. This can issue new pending * aio as a result of executing I/O completion or bh callbacks. * - * If there is no pending AIO operation or completion (bottom half), - * return false. If there are pending AIO operations of bottom halves, - * return true. + * Return whether any progress was made by executing AIO or bottom half + * handlers. If @blocking == true, this should always be true except + * if someone called aio_notify. * * If there are no pending bottom halves, but there are pending AIO * operations, it may not be possible to make any progress without diff --git a/iothread.c b/iothread.c index 1fbf9f1c49..d9403cf69e 100644 --- a/iothread.c +++ b/iothread.c @@ -30,6 +30,7 @@ typedef ObjectClass IOThreadClass; static void *iothread_run(void *opaque) { IOThread *iothread = opaque; + bool blocking; qemu_mutex_lock(&iothread->init_done_lock); iothread->thread_id = qemu_get_thread_id(); @@ -38,8 +39,10 @@ static void *iothread_run(void *opaque) while (!iothread->stopping) { aio_context_acquire(iothread->ctx); - while (!iothread->stopping && aio_poll(iothread->ctx, true)) { + blocking = true; + while (!iothread->stopping && aio_poll(iothread->ctx, blocking)) { /* Progress was made, keep going */ + blocking = false; } aio_context_release(iothread->ctx); } diff --git a/tests/test-aio.c b/tests/test-aio.c index 264dab9106..4c40a4971f 100644 --- a/tests/test-aio.c +++ b/tests/test-aio.c @@ -24,14 +24,6 @@ typedef struct { bool auto_set; } EventNotifierTestData; -/* Wait until there are no more BHs or AIO requests */ -static void wait_for_aio(void) -{ - while (aio_poll(ctx, true)) { - /* Do nothing */ - } -} - /* Wait until event notifier becomes inactive */ static void wait_until_inactive(EventNotifierTestData *data) { @@ -204,7 +196,9 @@ static void test_bh_schedule10(void) g_assert(aio_poll(ctx, true)); g_assert_cmpint(data.n, ==, 2); - wait_for_aio(); + while (data.n < 10) { + aio_poll(ctx, true); + } g_assert_cmpint(data.n, ==, 10); g_assert(!aio_poll(ctx, false)); @@ -252,7 +246,9 @@ static void test_bh_delete_from_cb(void) qemu_bh_schedule(data1.bh); g_assert_cmpint(data1.n, ==, 0); - wait_for_aio(); + while (data1.n < data1.max) { + aio_poll(ctx, true); + } g_assert_cmpint(data1.n, ==, data1.max); g_assert(data1.bh == NULL); @@ -287,7 +283,12 @@ static void test_bh_delete_from_cb_many(void) g_assert_cmpint(data4.n, ==, 1); g_assert(data1.bh == NULL); - wait_for_aio(); + while (data1.n < data1.max || + data2.n < data2.max || + data3.n < data3.max || + data4.n < data4.max) { + aio_poll(ctx, true); + } g_assert_cmpint(data1.n, ==, data1.max); g_assert_cmpint(data2.n, ==, data2.max); g_assert_cmpint(data3.n, ==, data3.max); @@ -306,7 +307,7 @@ static void test_bh_flush(void) qemu_bh_schedule(data.bh); g_assert_cmpint(data.n, ==, 0); - wait_for_aio(); + g_assert(aio_poll(ctx, true)); g_assert_cmpint(data.n, ==, 1); g_assert(!aio_poll(ctx, false));