typedef struct {
int plugged;
- unsigned int idx;
+ unsigned int n;
bool blocked;
QSIMPLEQ_HEAD(, qemu_laiocb) pending;
} LaioQueue;
int event_max;
};
-static int ioq_submit(struct qemu_laio_state *s);
+static void ioq_submit(struct qemu_laio_state *s);
static inline ssize_t io_event_ret(struct io_event *ev)
{
{
QSIMPLEQ_INIT(&io_q->pending);
io_q->plugged = 0;
- io_q->idx = 0;
+ io_q->n = 0;
io_q->blocked = false;
}
-static int ioq_submit(struct qemu_laio_state *s)
+static void ioq_submit(struct qemu_laio_state *s)
{
- int ret, i, len;
+ int ret, len;
struct qemu_laiocb *aiocb;
struct iocb *iocbs[MAX_QUEUED_IO];
+ QSIMPLEQ_HEAD(, qemu_laiocb) completed;
do {
len = 0;
ret = io_submit(s->ctx, len, iocbs);
if (ret == -EAGAIN) {
- ret = 0;
+ break;
}
if (ret < 0) {
abort();
}
- for (i = 0; i < ret; i++) {
- s->io_q.idx--;
- QSIMPLEQ_REMOVE_HEAD(&s->io_q.pending, next);
- }
+ s->io_q.n -= ret;
+ aiocb = container_of(iocbs[ret - 1], struct qemu_laiocb, iocb);
+ QSIMPLEQ_SPLIT_AFTER(&s->io_q.pending, aiocb, next, &completed);
} while (ret == len && !QSIMPLEQ_EMPTY(&s->io_q.pending));
- s->io_q.blocked = (s->io_q.idx > 0);
-
- return ret;
+ s->io_q.blocked = (s->io_q.n > 0);
}
void laio_io_plug(BlockDriverState *bs, void *aio_ctx)
s->io_q.plugged++;
}
-int laio_io_unplug(BlockDriverState *bs, void *aio_ctx, bool unplug)
+void laio_io_unplug(BlockDriverState *bs, void *aio_ctx, bool unplug)
{
struct qemu_laio_state *s = aio_ctx;
- int ret = 0;
assert(s->io_q.plugged > 0 || !unplug);
if (unplug && --s->io_q.plugged > 0) {
- return 0;
+ return;
}
if (!s->io_q.blocked && !QSIMPLEQ_EMPTY(&s->io_q.pending)) {
- ret = ioq_submit(s);
+ ioq_submit(s);
}
-
- return ret;
}
BlockAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd,
io_set_eventfd(&laiocb->iocb, event_notifier_get_fd(&s->e));
QSIMPLEQ_INSERT_TAIL(&s->io_q.pending, laiocb, next);
- s->io_q.idx++;
+ s->io_q.n++;
if (!s->io_q.blocked &&
- (!s->io_q.plugged || s->io_q.idx >= MAX_QUEUED_IO)) {
+ (!s->io_q.plugged || s->io_q.n >= MAX_QUEUED_IO)) {
ioq_submit(s);
}
return &laiocb->common;
{
struct qemu_laio_state *s = s_;
- aio_set_event_notifier(old_context, &s->e, NULL);
+ aio_set_event_notifier(old_context, &s->e, false, NULL);
qemu_bh_delete(s->completion_bh);
}
struct qemu_laio_state *s = s_;
s->completion_bh = aio_bh_new(new_context, qemu_laio_completion_bh, s);
- aio_set_event_notifier(new_context, &s->e, qemu_laio_completion_cb);
+ aio_set_event_notifier(new_context, &s->e, false,
+ qemu_laio_completion_cb);
}
void *laio_init(void)