[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 50/61] qed: Use CoQueue for serialising allocations
From: |
Kevin Wolf |
Subject: |
[Qemu-devel] [PULL 50/61] qed: Use CoQueue for serialising allocations |
Date: |
Fri, 23 Jun 2017 18:21:48 +0200 |
Now that we're running in coroutine context, the ad-hoc serialisation
code (which drops a request that has to wait out of coroutine context)
can be replaced by a CoQueue.
This means that when we resume a serialised request, it is running in
coroutine context again and its I/O isn't blocking any more.
Signed-off-by: Kevin Wolf <address@hidden>
Reviewed-by: Stefan Hajnoczi <address@hidden>
---
block/qed.c | 49 +++++++++++++++++--------------------------------
block/qed.h | 3 ++-
2 files changed, 19 insertions(+), 33 deletions(-)
diff --git a/block/qed.c b/block/qed.c
index a5111fd..cd3ef55 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -269,16 +269,10 @@ static void qed_plug_allocating_write_reqs(BDRVQEDState
*s)
static void qed_unplug_allocating_write_reqs(BDRVQEDState *s)
{
- QEDAIOCB *acb;
-
assert(s->allocating_write_reqs_plugged);
s->allocating_write_reqs_plugged = false;
-
- acb = QSIMPLEQ_FIRST(&s->allocating_write_reqs);
- if (acb) {
- qed_aio_start_io(acb);
- }
+ qemu_co_enter_next(&s->allocating_write_reqs);
}
static void qed_clear_need_check(void *opaque, int ret)
@@ -305,7 +299,7 @@ static void qed_need_check_timer_cb(void *opaque)
BDRVQEDState *s = opaque;
/* The timer should only fire when allocating writes have drained */
- assert(!QSIMPLEQ_FIRST(&s->allocating_write_reqs));
+ assert(!s->allocating_acb);
trace_qed_need_check_timer_cb(s);
@@ -388,7 +382,7 @@ static int bdrv_qed_do_open(BlockDriverState *bs, QDict
*options, int flags,
int ret;
s->bs = bs;
- QSIMPLEQ_INIT(&s->allocating_write_reqs);
+ qemu_co_queue_init(&s->allocating_write_reqs);
ret = bdrv_pread(bs->file, 0, &le_header, sizeof(le_header));
if (ret < 0) {
@@ -910,11 +904,6 @@ static void qed_aio_complete_bh(void *opaque)
qed_release(s);
}
-static void qed_resume_alloc_bh(void *opaque)
-{
- qed_aio_start_io(opaque);
-}
-
static void qed_aio_complete(QEDAIOCB *acb, int ret)
{
BDRVQEDState *s = acb_to_s(acb);
@@ -942,13 +931,10 @@ static void qed_aio_complete(QEDAIOCB *acb, int ret)
* next request in the queue. This ensures that we don't cycle through
* requests multiple times but rather finish one at a time completely.
*/
- if (acb == QSIMPLEQ_FIRST(&s->allocating_write_reqs)) {
- QEDAIOCB *next_acb;
- QSIMPLEQ_REMOVE_HEAD(&s->allocating_write_reqs, next);
- next_acb = QSIMPLEQ_FIRST(&s->allocating_write_reqs);
- if (next_acb) {
- aio_bh_schedule_oneshot(bdrv_get_aio_context(acb->common.bs),
- qed_resume_alloc_bh, next_acb);
+ if (acb == s->allocating_acb) {
+ s->allocating_acb = NULL;
+ if (!qemu_co_queue_empty(&s->allocating_write_reqs)) {
+ qemu_co_enter_next(&s->allocating_write_reqs);
} else if (s->header.features & QED_F_NEED_CHECK) {
qed_start_need_check_timer(s);
}
@@ -1124,17 +1110,18 @@ static int qed_aio_write_alloc(QEDAIOCB *acb, size_t
len)
int ret;
/* Cancel timer when the first allocating request comes in */
- if (QSIMPLEQ_EMPTY(&s->allocating_write_reqs)) {
+ if (s->allocating_acb == NULL) {
qed_cancel_need_check_timer(s);
}
/* Freeze this request if another allocating write is in progress */
- if (acb != QSIMPLEQ_FIRST(&s->allocating_write_reqs)) {
- QSIMPLEQ_INSERT_TAIL(&s->allocating_write_reqs, acb, next);
- }
- if (acb != QSIMPLEQ_FIRST(&s->allocating_write_reqs) ||
- s->allocating_write_reqs_plugged) {
- return -EINPROGRESS; /* wait for existing request to finish */
+ if (s->allocating_acb != acb || s->allocating_write_reqs_plugged) {
+ if (s->allocating_acb != NULL) {
+ qemu_co_queue_wait(&s->allocating_write_reqs, NULL);
+ assert(s->allocating_acb == NULL);
+ }
+ s->allocating_acb = acb;
+ return -EAGAIN; /* start over with looking up table entries */
}
acb->cur_nclusters = qed_bytes_to_clusters(s,
@@ -1313,10 +1300,8 @@ static void qed_aio_next_io(QEDAIOCB *acb)
ret = qed_aio_read_data(acb, ret, offset, len);
}
- if (ret < 0) {
- if (ret != -EINPROGRESS) {
- qed_aio_complete(acb, ret);
- }
+ if (ret < 0 && ret != -EAGAIN) {
+ qed_aio_complete(acb, ret);
return;
}
}
diff --git a/block/qed.h b/block/qed.h
index 8644fed..37558e4 100644
--- a/block/qed.h
+++ b/block/qed.h
@@ -163,7 +163,8 @@ typedef struct {
uint32_t l2_mask;
/* Allocating write request queue */
- QSIMPLEQ_HEAD(, QEDAIOCB) allocating_write_reqs;
+ QEDAIOCB *allocating_acb;
+ CoQueue allocating_write_reqs;
bool allocating_write_reqs_plugged;
/* Periodic flush and clear need check flag */
--
1.8.3.1
- [Qemu-devel] [PULL 41/61] qed: Add return value to qed_aio_write_l1_update(), (continued)
- [Qemu-devel] [PULL 41/61] qed: Add return value to qed_aio_write_l1_update(), Kevin Wolf, 2017/06/23
- [Qemu-devel] [PULL 37/61] qed: Remove callback from qed_write_table(), Kevin Wolf, 2017/06/23
- [Qemu-devel] [PULL 43/61] qed: Add return value to qed_aio_write_main(), Kevin Wolf, 2017/06/23
- [Qemu-devel] [PULL 45/61] qed: Add return value to qed_aio_write_inplace/alloc(), Kevin Wolf, 2017/06/23
- [Qemu-devel] [PULL 47/61] qed: Remove ret argument from qed_aio_next_io(), Kevin Wolf, 2017/06/23
- [Qemu-devel] [PULL 48/61] qed: Remove recursion in qed_aio_next_io(), Kevin Wolf, 2017/06/23
- [Qemu-devel] [PULL 46/61] qed: Add return value to qed_aio_read/write_data(), Kevin Wolf, 2017/06/23
- [Qemu-devel] [PULL 39/61] qed: Make qed_aio_write_main() synchronous, Kevin Wolf, 2017/06/23
- [Qemu-devel] [PULL 42/61] qed: Add return value to qed_aio_write_l2_update(), Kevin Wolf, 2017/06/23
- [Qemu-devel] [PULL 44/61] qed: Add return value to qed_aio_write_cow(), Kevin Wolf, 2017/06/23
- [Qemu-devel] [PULL 50/61] qed: Use CoQueue for serialising allocations,
Kevin Wolf <=
- [Qemu-devel] [PULL 49/61] qed: Implement .bdrv_co_readv/writev, Kevin Wolf, 2017/06/23
- [Qemu-devel] [PULL 51/61] qed: Simplify request handling, Kevin Wolf, 2017/06/23
- [Qemu-devel] [PULL 52/61] qed: Use a coroutine for need_check_timer, Kevin Wolf, 2017/06/23
- [Qemu-devel] [PULL 54/61] qed: Use bdrv_co_* for coroutine_fns, Kevin Wolf, 2017/06/23
- [Qemu-devel] [PULL 53/61] qed: Add coroutine_fn to I/O path functions, Kevin Wolf, 2017/06/23
- [Qemu-devel] [PULL 57/61] fix: avoid an infinite loop or a dangling pointer problem in img_commit, Kevin Wolf, 2017/06/23
- [Qemu-devel] [PULL 55/61] block: Remove bdrv_aio_readv/writev/flush(), Kevin Wolf, 2017/06/23
- [Qemu-devel] [PULL 58/61] blkdebug: Catch bs->exact_filename overflow, Kevin Wolf, 2017/06/23
- [Qemu-devel] [PULL 61/61] qemu-img: don't shadow opts variable in img_dd(), Kevin Wolf, 2017/06/23
- [Qemu-devel] [PULL 59/61] blkverify: Catch bs->exact_filename overflow, Kevin Wolf, 2017/06/23