diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2014-12-11 14:52:27 +0100 |
---|---|---|
committer | Stefan Hajnoczi <stefanha@redhat.com> | 2014-12-12 16:57:55 +0000 |
commit | 43f2376e096382df44d9322ae0cbdca89612d464 (patch) | |
tree | 7224c96c9665c21d4f3e87c8bf950867c4663e90 | |
parent | 28b240877bbcdc8add61be227f429b536edd4653 (diff) | |
download | hqemu-43f2376e096382df44d9322ae0cbdca89612d464.zip hqemu-43f2376e096382df44d9322ae0cbdca89612d464.tar.gz |
linux-aio: track whether the queue is blocked
Avoid that unplug submits requests when io_submit reported that it
couldn't accept more; at the same time, try more io_submit calls if it
could handle the whole set of requests that were passed, so that the
"blocked" flag is reset as soon as possible.
After the previous patch, laio_submit already tried to avoid submitting
requests to a blocked queue, by comparing s->io_q.idx with "==" instead
of the more natural ">=". Switch to the simpler expression now that we
have the "blocked" flag.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Message-id: 1418305950-30924-3-git-send-email-pbonzini@redhat.com
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
-rw-r--r-- | block/linux-aio.c | 47 |
1 files changed, 27 insertions, 20 deletions
diff --git a/block/linux-aio.c b/block/linux-aio.c index b6fbfd8..b870942 100644 --- a/block/linux-aio.c +++ b/block/linux-aio.c @@ -41,6 +41,7 @@ struct qemu_laiocb { typedef struct { int plugged; unsigned int idx; + bool blocked; QSIMPLEQ_HEAD(, qemu_laiocb) pending; } LaioQueue; @@ -180,34 +181,39 @@ static void ioq_init(LaioQueue *io_q) QSIMPLEQ_INIT(&io_q->pending); io_q->plugged = 0; io_q->idx = 0; + io_q->blocked = false; } static int ioq_submit(struct qemu_laio_state *s) { - int ret, i; - int len = 0; + int ret, i, len; struct qemu_laiocb *aiocb; struct iocb *iocbs[MAX_QUEUED_IO]; - QSIMPLEQ_FOREACH(aiocb, &s->io_q.pending, next) { - iocbs[len++] = &aiocb->iocb; - if (len == MAX_QUEUED_IO) { - break; + do { + len = 0; + QSIMPLEQ_FOREACH(aiocb, &s->io_q.pending, next) { + iocbs[len++] = &aiocb->iocb; + if (len == MAX_QUEUED_IO) { + break; + } } - } - ret = io_submit(s->ctx, len, iocbs); - if (ret == -EAGAIN) { - ret = 0; - } - if (ret < 0) { - abort(); - } + ret = io_submit(s->ctx, len, iocbs); + if (ret == -EAGAIN) { + ret = 0; + } + if (ret < 0) { + abort(); + } + + for (i = 0; i < ret; i++) { + s->io_q.idx--; + QSIMPLEQ_REMOVE_HEAD(&s->io_q.pending, next); + } + } while (ret == len && !QSIMPLEQ_EMPTY(&s->io_q.pending)); + s->io_q.blocked = (s->io_q.idx > 0); - for (i = 0; i < ret; i++) { - s->io_q.idx--; - QSIMPLEQ_REMOVE_HEAD(&s->io_q.pending, next); - } return ret; } @@ -229,7 +235,7 @@ int laio_io_unplug(BlockDriverState *bs, void *aio_ctx, bool unplug) return 0; } - if (!QSIMPLEQ_EMPTY(&s->io_q.pending)) { + if (!s->io_q.blocked && !QSIMPLEQ_EMPTY(&s->io_q.pending)) { ret = ioq_submit(s); } @@ -271,7 +277,8 @@ BlockAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd, QSIMPLEQ_INSERT_TAIL(&s->io_q.pending, laiocb, next); s->io_q.idx++; - if (s->io_q.idx == (s->io_q.plugged ? MAX_QUEUED_IO : 1)) { + if (!s->io_q.blocked && + (!s->io_q.plugged || s->io_q.idx >= MAX_QUEUED_IO)) { ioq_submit(s); } return &laiocb->common; |