linux-aio: use event notifiers

Since linux-aio already uses an eventfd, converting it to use the
EventNotifier-based API simplifies the code even though it is not
meant to be portable.

Reviewed-by: Anthony Liguori <anthony@codemonkey.ws>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Paolo Bonzini 2012-02-24 08:39:02 +01:00
parent 22bfa75eaf
commit c90caf25e2
1 changed files with 19 additions and 30 deletions

View File

@ -11,8 +11,8 @@
#include "qemu-aio.h" #include "qemu-aio.h"
#include "qemu-queue.h" #include "qemu-queue.h"
#include "block/raw-posix-aio.h" #include "block/raw-posix-aio.h"
#include "event_notifier.h"
#include <sys/eventfd.h>
#include <libaio.h> #include <libaio.h>
/* /*
@ -38,7 +38,7 @@ struct qemu_laiocb {
struct qemu_laio_state { struct qemu_laio_state {
io_context_t ctx; io_context_t ctx;
int efd; EventNotifier e;
int count; int count;
}; };
@ -77,29 +77,17 @@ static void qemu_laio_process_completion(struct qemu_laio_state *s,
qemu_aio_release(laiocb); qemu_aio_release(laiocb);
} }
static void qemu_laio_completion_cb(void *opaque) static void qemu_laio_completion_cb(EventNotifier *e)
{ {
struct qemu_laio_state *s = opaque; struct qemu_laio_state *s = container_of(e, struct qemu_laio_state, e);
while (1) { while (event_notifier_test_and_clear(&s->e)) {
struct io_event events[MAX_EVENTS]; struct io_event events[MAX_EVENTS];
uint64_t val;
ssize_t ret;
struct timespec ts = { 0 }; struct timespec ts = { 0 };
int nevents, i; int nevents, i;
do { do {
ret = read(s->efd, &val, sizeof(val)); nevents = io_getevents(s->ctx, MAX_EVENTS, MAX_EVENTS, events, &ts);
} while (ret == -1 && errno == EINTR);
if (ret == -1 && errno == EAGAIN)
break;
if (ret != 8)
break;
do {
nevents = io_getevents(s->ctx, val, MAX_EVENTS, events, &ts);
} while (nevents == -EINTR); } while (nevents == -EINTR);
for (i = 0; i < nevents; i++) { for (i = 0; i < nevents; i++) {
@ -113,9 +101,9 @@ static void qemu_laio_completion_cb(void *opaque)
} }
} }
static int qemu_laio_flush_cb(void *opaque) static int qemu_laio_flush_cb(EventNotifier *e)
{ {
struct qemu_laio_state *s = opaque; struct qemu_laio_state *s = container_of(e, struct qemu_laio_state, e);
return (s->count > 0) ? 1 : 0; return (s->count > 0) ? 1 : 0;
} }
@ -147,8 +135,9 @@ static void laio_cancel(BlockDriverAIOCB *blockacb)
* We might be able to do this slightly more optimal by removing the * We might be able to do this slightly more optimal by removing the
* O_NONBLOCK flag. * O_NONBLOCK flag.
*/ */
while (laiocb->ret == -EINPROGRESS) while (laiocb->ret == -EINPROGRESS) {
qemu_laio_completion_cb(laiocb->ctx); qemu_laio_completion_cb(&laiocb->ctx->e);
}
} }
static AIOPool laio_pool = { static AIOPool laio_pool = {
@ -187,7 +176,7 @@ BlockDriverAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd,
__func__, type); __func__, type);
goto out_free_aiocb; goto out_free_aiocb;
} }
io_set_eventfd(&laiocb->iocb, s->efd); io_set_eventfd(&laiocb->iocb, event_notifier_get_fd(&s->e));
s->count++; s->count++;
if (io_submit(s->ctx, 1, &iocbs) < 0) if (io_submit(s->ctx, 1, &iocbs) < 0)
@ -206,21 +195,21 @@ void *laio_init(void)
struct qemu_laio_state *s; struct qemu_laio_state *s;
s = g_malloc0(sizeof(*s)); s = g_malloc0(sizeof(*s));
s->efd = eventfd(0, 0); if (event_notifier_init(&s->e, false) < 0) {
if (s->efd == -1)
goto out_free_state; goto out_free_state;
fcntl(s->efd, F_SETFL, O_NONBLOCK); }
if (io_setup(MAX_EVENTS, &s->ctx) != 0) if (io_setup(MAX_EVENTS, &s->ctx) != 0) {
goto out_close_efd; goto out_close_efd;
}
qemu_aio_set_fd_handler(s->efd, qemu_laio_completion_cb, NULL, qemu_aio_set_event_notifier(&s->e, qemu_laio_completion_cb,
qemu_laio_flush_cb, s); qemu_laio_flush_cb);
return s; return s;
out_close_efd: out_close_efd:
close(s->efd); event_notifier_cleanup(&s->e);
out_free_state: out_free_state:
g_free(s); g_free(s);
return NULL; return NULL;