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>
This commit is contained in:
parent
28b240877b
commit
43f2376e09
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user