linux-aio: make it more type safe
Replace void* with an opaque LinuxAioState type. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Acked-by: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
6b98bd6495
commit
dd7f7ed104
@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
struct qemu_laiocb {
|
struct qemu_laiocb {
|
||||||
BlockAIOCB common;
|
BlockAIOCB common;
|
||||||
struct qemu_laio_state *ctx;
|
LinuxAioState *ctx;
|
||||||
struct iocb iocb;
|
struct iocb iocb;
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
size_t nbytes;
|
size_t nbytes;
|
||||||
@ -46,7 +46,7 @@ typedef struct {
|
|||||||
QSIMPLEQ_HEAD(, qemu_laiocb) pending;
|
QSIMPLEQ_HEAD(, qemu_laiocb) pending;
|
||||||
} LaioQueue;
|
} LaioQueue;
|
||||||
|
|
||||||
struct qemu_laio_state {
|
struct LinuxAioState {
|
||||||
io_context_t ctx;
|
io_context_t ctx;
|
||||||
EventNotifier e;
|
EventNotifier e;
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ struct qemu_laio_state {
|
|||||||
int event_max;
|
int event_max;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void ioq_submit(struct qemu_laio_state *s);
|
static void ioq_submit(LinuxAioState *s);
|
||||||
|
|
||||||
static inline ssize_t io_event_ret(struct io_event *ev)
|
static inline ssize_t io_event_ret(struct io_event *ev)
|
||||||
{
|
{
|
||||||
@ -70,8 +70,7 @@ static inline ssize_t io_event_ret(struct io_event *ev)
|
|||||||
/*
|
/*
|
||||||
* Completes an AIO request (calls the callback and frees the ACB).
|
* Completes an AIO request (calls the callback and frees the ACB).
|
||||||
*/
|
*/
|
||||||
static void qemu_laio_process_completion(struct qemu_laio_state *s,
|
static void qemu_laio_process_completion(struct qemu_laiocb *laiocb)
|
||||||
struct qemu_laiocb *laiocb)
|
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@ -99,7 +98,7 @@ static void qemu_laio_process_completion(struct qemu_laio_state *s,
|
|||||||
*
|
*
|
||||||
* The function is somewhat tricky because it supports nested event loops, for
|
* The function is somewhat tricky because it supports nested event loops, for
|
||||||
* example when a request callback invokes aio_poll(). In order to do this,
|
* example when a request callback invokes aio_poll(). In order to do this,
|
||||||
* the completion events array and index are kept in qemu_laio_state. The BH
|
* the completion events array and index are kept in LinuxAioState. The BH
|
||||||
* reschedules itself as long as there are completions pending so it will
|
* reschedules itself as long as there are completions pending so it will
|
||||||
* either be called again in a nested event loop or will be called after all
|
* either be called again in a nested event loop or will be called after all
|
||||||
* events have been completed. When there are no events left to complete, the
|
* events have been completed. When there are no events left to complete, the
|
||||||
@ -107,7 +106,7 @@ static void qemu_laio_process_completion(struct qemu_laio_state *s,
|
|||||||
*/
|
*/
|
||||||
static void qemu_laio_completion_bh(void *opaque)
|
static void qemu_laio_completion_bh(void *opaque)
|
||||||
{
|
{
|
||||||
struct qemu_laio_state *s = opaque;
|
LinuxAioState *s = opaque;
|
||||||
|
|
||||||
/* Fetch more completion events when empty */
|
/* Fetch more completion events when empty */
|
||||||
if (s->event_idx == s->event_max) {
|
if (s->event_idx == s->event_max) {
|
||||||
@ -136,7 +135,7 @@ static void qemu_laio_completion_bh(void *opaque)
|
|||||||
laiocb->ret = io_event_ret(&s->events[s->event_idx]);
|
laiocb->ret = io_event_ret(&s->events[s->event_idx]);
|
||||||
s->event_idx++;
|
s->event_idx++;
|
||||||
|
|
||||||
qemu_laio_process_completion(s, laiocb);
|
qemu_laio_process_completion(laiocb);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!s->io_q.plugged && !QSIMPLEQ_EMPTY(&s->io_q.pending)) {
|
if (!s->io_q.plugged && !QSIMPLEQ_EMPTY(&s->io_q.pending)) {
|
||||||
@ -146,7 +145,7 @@ static void qemu_laio_completion_bh(void *opaque)
|
|||||||
|
|
||||||
static void qemu_laio_completion_cb(EventNotifier *e)
|
static void qemu_laio_completion_cb(EventNotifier *e)
|
||||||
{
|
{
|
||||||
struct qemu_laio_state *s = container_of(e, struct qemu_laio_state, e);
|
LinuxAioState *s = container_of(e, LinuxAioState, e);
|
||||||
|
|
||||||
if (event_notifier_test_and_clear(&s->e)) {
|
if (event_notifier_test_and_clear(&s->e)) {
|
||||||
qemu_bh_schedule(s->completion_bh);
|
qemu_bh_schedule(s->completion_bh);
|
||||||
@ -185,7 +184,7 @@ static void ioq_init(LaioQueue *io_q)
|
|||||||
io_q->blocked = false;
|
io_q->blocked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ioq_submit(struct qemu_laio_state *s)
|
static void ioq_submit(LinuxAioState *s)
|
||||||
{
|
{
|
||||||
int ret, len;
|
int ret, len;
|
||||||
struct qemu_laiocb *aiocb;
|
struct qemu_laiocb *aiocb;
|
||||||
@ -216,18 +215,14 @@ static void ioq_submit(struct qemu_laio_state *s)
|
|||||||
s->io_q.blocked = (s->io_q.n > 0);
|
s->io_q.blocked = (s->io_q.n > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void laio_io_plug(BlockDriverState *bs, void *aio_ctx)
|
void laio_io_plug(BlockDriverState *bs, LinuxAioState *s)
|
||||||
{
|
{
|
||||||
struct qemu_laio_state *s = aio_ctx;
|
|
||||||
|
|
||||||
assert(!s->io_q.plugged);
|
assert(!s->io_q.plugged);
|
||||||
s->io_q.plugged = 1;
|
s->io_q.plugged = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void laio_io_unplug(BlockDriverState *bs, void *aio_ctx)
|
void laio_io_unplug(BlockDriverState *bs, LinuxAioState *s)
|
||||||
{
|
{
|
||||||
struct qemu_laio_state *s = aio_ctx;
|
|
||||||
|
|
||||||
assert(s->io_q.plugged);
|
assert(s->io_q.plugged);
|
||||||
s->io_q.plugged = 0;
|
s->io_q.plugged = 0;
|
||||||
if (!s->io_q.blocked && !QSIMPLEQ_EMPTY(&s->io_q.pending)) {
|
if (!s->io_q.blocked && !QSIMPLEQ_EMPTY(&s->io_q.pending)) {
|
||||||
@ -235,11 +230,10 @@ void laio_io_unplug(BlockDriverState *bs, void *aio_ctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd,
|
BlockAIOCB *laio_submit(BlockDriverState *bs, LinuxAioState *s, int fd,
|
||||||
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
|
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
|
||||||
BlockCompletionFunc *cb, void *opaque, int type)
|
BlockCompletionFunc *cb, void *opaque, int type)
|
||||||
{
|
{
|
||||||
struct qemu_laio_state *s = aio_ctx;
|
|
||||||
struct qemu_laiocb *laiocb;
|
struct qemu_laiocb *laiocb;
|
||||||
struct iocb *iocbs;
|
struct iocb *iocbs;
|
||||||
off_t offset = sector_num * 512;
|
off_t offset = sector_num * 512;
|
||||||
@ -281,26 +275,22 @@ out_free_aiocb:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void laio_detach_aio_context(void *s_, AioContext *old_context)
|
void laio_detach_aio_context(LinuxAioState *s, AioContext *old_context)
|
||||||
{
|
{
|
||||||
struct qemu_laio_state *s = s_;
|
|
||||||
|
|
||||||
aio_set_event_notifier(old_context, &s->e, false, NULL);
|
aio_set_event_notifier(old_context, &s->e, false, NULL);
|
||||||
qemu_bh_delete(s->completion_bh);
|
qemu_bh_delete(s->completion_bh);
|
||||||
}
|
}
|
||||||
|
|
||||||
void laio_attach_aio_context(void *s_, AioContext *new_context)
|
void laio_attach_aio_context(LinuxAioState *s, AioContext *new_context)
|
||||||
{
|
{
|
||||||
struct qemu_laio_state *s = s_;
|
|
||||||
|
|
||||||
s->completion_bh = aio_bh_new(new_context, qemu_laio_completion_bh, s);
|
s->completion_bh = aio_bh_new(new_context, qemu_laio_completion_bh, s);
|
||||||
aio_set_event_notifier(new_context, &s->e, false,
|
aio_set_event_notifier(new_context, &s->e, false,
|
||||||
qemu_laio_completion_cb);
|
qemu_laio_completion_cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *laio_init(void)
|
LinuxAioState *laio_init(void)
|
||||||
{
|
{
|
||||||
struct qemu_laio_state *s;
|
LinuxAioState *s;
|
||||||
|
|
||||||
s = g_malloc0(sizeof(*s));
|
s = g_malloc0(sizeof(*s));
|
||||||
if (event_notifier_init(&s->e, false) < 0) {
|
if (event_notifier_init(&s->e, false) < 0) {
|
||||||
@ -322,10 +312,8 @@ out_free_state:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void laio_cleanup(void *s_)
|
void laio_cleanup(LinuxAioState *s)
|
||||||
{
|
{
|
||||||
struct qemu_laio_state *s = s_;
|
|
||||||
|
|
||||||
event_notifier_cleanup(&s->e);
|
event_notifier_cleanup(&s->e);
|
||||||
|
|
||||||
if (io_destroy(s->ctx) != 0) {
|
if (io_destroy(s->ctx) != 0) {
|
||||||
|
@ -35,15 +35,16 @@
|
|||||||
|
|
||||||
/* linux-aio.c - Linux native implementation */
|
/* linux-aio.c - Linux native implementation */
|
||||||
#ifdef CONFIG_LINUX_AIO
|
#ifdef CONFIG_LINUX_AIO
|
||||||
void *laio_init(void);
|
typedef struct LinuxAioState LinuxAioState;
|
||||||
void laio_cleanup(void *s);
|
LinuxAioState *laio_init(void);
|
||||||
BlockAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd,
|
void laio_cleanup(LinuxAioState *s);
|
||||||
|
BlockAIOCB *laio_submit(BlockDriverState *bs, LinuxAioState *s, int fd,
|
||||||
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
|
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
|
||||||
BlockCompletionFunc *cb, void *opaque, int type);
|
BlockCompletionFunc *cb, void *opaque, int type);
|
||||||
void laio_detach_aio_context(void *s, AioContext *old_context);
|
void laio_detach_aio_context(LinuxAioState *s, AioContext *old_context);
|
||||||
void laio_attach_aio_context(void *s, AioContext *new_context);
|
void laio_attach_aio_context(LinuxAioState *s, AioContext *new_context);
|
||||||
void laio_io_plug(BlockDriverState *bs, void *aio_ctx);
|
void laio_io_plug(BlockDriverState *bs, LinuxAioState *s);
|
||||||
void laio_io_unplug(BlockDriverState *bs, void *aio_ctx);
|
void laio_io_unplug(BlockDriverState *bs, LinuxAioState *s);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
@ -139,7 +139,7 @@ typedef struct BDRVRawState {
|
|||||||
|
|
||||||
#ifdef CONFIG_LINUX_AIO
|
#ifdef CONFIG_LINUX_AIO
|
||||||
int use_aio;
|
int use_aio;
|
||||||
void *aio_ctx;
|
LinuxAioState *aio_ctx;
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_XFS
|
#ifdef CONFIG_XFS
|
||||||
bool is_xfs:1;
|
bool is_xfs:1;
|
||||||
@ -398,7 +398,7 @@ static void raw_attach_aio_context(BlockDriverState *bs,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_LINUX_AIO
|
#ifdef CONFIG_LINUX_AIO
|
||||||
static int raw_set_aio(void **aio_ctx, int *use_aio, int bdrv_flags)
|
static int raw_set_aio(LinuxAioState **aio_ctx, int *use_aio, int bdrv_flags)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
assert(aio_ctx != NULL);
|
assert(aio_ctx != NULL);
|
||||||
|
Loading…
Reference in New Issue
Block a user