2 * Linux AIO request queue
4 * Copyright 2012 IBM, Corp.
5 * Copyright 2012 Red Hat, Inc. and/or its affiliates
8 * Stefan Hajnoczi <stefanha@redhat.com>
10 * This work is licensed under the terms of the GNU GPL, version 2 or later.
11 * See the COPYING file in the top-level directory.
17 void ioq_init(IOQueue
*ioq
, int fd
, unsigned int max_reqs
)
22 ioq
->max_reqs
= max_reqs
;
24 memset(&ioq
->io_ctx
, 0, sizeof ioq
->io_ctx
);
25 rc
= io_setup(max_reqs
, &ioq
->io_ctx
);
27 fprintf(stderr
, "ioq io_setup failed %d\n", rc
);
31 rc
= event_notifier_init(&ioq
->io_notifier
, 0);
33 fprintf(stderr
, "ioq io event notifier creation failed %d\n", rc
);
37 ioq
->freelist
= g_malloc0(sizeof ioq
->freelist
[0] * max_reqs
);
38 ioq
->freelist_idx
= 0;
40 ioq
->queue
= g_malloc0(sizeof ioq
->queue
[0] * max_reqs
);
44 void ioq_cleanup(IOQueue
*ioq
)
46 g_free(ioq
->freelist
);
49 event_notifier_cleanup(&ioq
->io_notifier
);
50 io_destroy(ioq
->io_ctx
);
53 EventNotifier
*ioq_get_notifier(IOQueue
*ioq
)
55 return &ioq
->io_notifier
;
58 struct iocb
*ioq_get_iocb(IOQueue
*ioq
)
60 /* Underflow cannot happen since ioq is sized for max_reqs */
61 assert(ioq
->freelist_idx
!= 0);
63 struct iocb
*iocb
= ioq
->freelist
[--ioq
->freelist_idx
];
64 ioq
->queue
[ioq
->queue_idx
++] = iocb
;
68 void ioq_put_iocb(IOQueue
*ioq
, struct iocb
*iocb
)
70 /* Overflow cannot happen since ioq is sized for max_reqs */
71 assert(ioq
->freelist_idx
!= ioq
->max_reqs
);
73 ioq
->freelist
[ioq
->freelist_idx
++] = iocb
;
76 struct iocb
*ioq_rdwr(IOQueue
*ioq
, bool read
, struct iovec
*iov
,
77 unsigned int count
, long long offset
)
79 struct iocb
*iocb
= ioq_get_iocb(ioq
);
82 io_prep_preadv(iocb
, ioq
->fd
, iov
, count
, offset
);
84 io_prep_pwritev(iocb
, ioq
->fd
, iov
, count
, offset
);
86 io_set_eventfd(iocb
, event_notifier_get_fd(&ioq
->io_notifier
));
90 int ioq_submit(IOQueue
*ioq
)
92 int rc
= io_submit(ioq
->io_ctx
, ioq
->queue_idx
, ioq
->queue
);
93 ioq
->queue_idx
= 0; /* reset */
97 int ioq_run_completion(IOQueue
*ioq
, IOQueueCompletion
*completion
,
100 struct io_event events
[ioq
->max_reqs
];
104 nevents
= io_getevents(ioq
->io_ctx
, 0, ioq
->max_reqs
, events
, NULL
);
105 } while (nevents
< 0 && errno
== EINTR
);
110 for (i
= 0; i
< nevents
; i
++) {
111 ssize_t ret
= ((uint64_t)events
[i
].res2
<< 32) | events
[i
].res
;
113 completion(events
[i
].obj
, ret
, opaque
);
114 ioq_put_iocb(ioq
, events
[i
].obj
);