mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
block/io_uring: use aio_add_sqe()
AioContext has its own io_uring instance for file descriptor monitoring. The disk I/O io_uring code was developed separately. Originally I thought the characteristics of file descriptor monitoring and disk I/O were too different, requiring separate io_uring instances. Now it has become clear to me that it's feasible to share a single io_uring instance for file descriptor monitoring and disk I/O. We're not using io_uring's IOPOLL feature or anything else that would require a separate instance. Unify block/io_uring.c and util/fdmon-io_uring.c using the new aio_add_sqe() API that allows user-defined io_uring sqe submission. Now block/io_uring.c just needs to submit readv/writev/fsync and most of the io_uring-specific logic is handled by fdmon-io_uring.c. There are two immediate advantages: 1. Fewer system calls. There is no need to monitor the disk I/O io_uring ring fd from the file descriptor monitoring io_uring instance. Disk I/O completions are now picked up directly. Also, sqes are accumulated in the sq ring until the end of the event loop iteration and there are fewer io_uring_enter(2) syscalls. 2. Less code duplication. Note that error_setg() messages are not supposed to end with punctuation, so I removed a '.' for the non-io_uring build error message. Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Message-ID: <20251104022933.618123-15-stefanha@redhat.com> Reviewed-by: Kevin Wolf <kwolf@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
committed by
Kevin Wolf
parent
1eebdab3c3
commit
047dabef97
+14
-26
@@ -755,14 +755,23 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
|
||||
}
|
||||
#endif /* !defined(CONFIG_LINUX_AIO) */
|
||||
|
||||
#ifndef CONFIG_LINUX_IO_URING
|
||||
if (s->use_linux_io_uring) {
|
||||
#ifdef CONFIG_LINUX_IO_URING
|
||||
if (!aio_has_io_uring()) {
|
||||
error_setg(errp, "aio=io_uring was specified, but is not "
|
||||
"available (disabled via io_uring_disabled "
|
||||
"sysctl or blocked by container runtime "
|
||||
"seccomp policy?)");
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
#else
|
||||
error_setg(errp, "aio=io_uring was specified, but is not supported "
|
||||
"in this build.");
|
||||
"in this build");
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
#endif /* !defined(CONFIG_LINUX_IO_URING) */
|
||||
}
|
||||
|
||||
s->has_discard = true;
|
||||
s->has_write_zeroes = true;
|
||||
@@ -2522,27 +2531,6 @@ static bool bdrv_qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov)
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LINUX_IO_URING
|
||||
static inline bool raw_check_linux_io_uring(BDRVRawState *s)
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
AioContext *ctx;
|
||||
|
||||
if (!s->use_linux_io_uring) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ctx = qemu_get_current_aio_context();
|
||||
if (unlikely(!aio_setup_linux_io_uring(ctx, &local_err))) {
|
||||
error_reportf_err(local_err, "Unable to use linux io_uring, "
|
||||
"falling back to thread pool: ");
|
||||
s->use_linux_io_uring = false;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LINUX_AIO
|
||||
static inline bool raw_check_linux_aio(BDRVRawState *s)
|
||||
{
|
||||
@@ -2595,7 +2583,7 @@ raw_co_prw(BlockDriverState *bs, int64_t *offset_ptr, uint64_t bytes,
|
||||
if (s->needs_alignment && !bdrv_qiov_is_aligned(bs, qiov)) {
|
||||
type |= QEMU_AIO_MISALIGNED;
|
||||
#ifdef CONFIG_LINUX_IO_URING
|
||||
} else if (raw_check_linux_io_uring(s)) {
|
||||
} else if (s->use_linux_io_uring) {
|
||||
assert(qiov->size == bytes);
|
||||
ret = luring_co_submit(bs, s->fd, offset, qiov, type, flags);
|
||||
goto out;
|
||||
@@ -2692,7 +2680,7 @@ static int coroutine_fn raw_co_flush_to_disk(BlockDriverState *bs)
|
||||
};
|
||||
|
||||
#ifdef CONFIG_LINUX_IO_URING
|
||||
if (raw_check_linux_io_uring(s)) {
|
||||
if (s->use_linux_io_uring) {
|
||||
return luring_co_submit(bs, s->fd, 0, NULL, QEMU_AIO_FLUSH, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
+113
-376
File diff suppressed because it is too large
Load Diff
+3
-9
@@ -62,15 +62,9 @@ qmp_block_stream(void *bs) "bs %p"
|
||||
file_paio_submit(void *acb, void *opaque, int64_t offset, int count, int type) "acb %p opaque %p offset %"PRId64" count %d type %d"
|
||||
|
||||
# io_uring.c
|
||||
luring_init_state(void *s, size_t size) "s %p size %zu"
|
||||
luring_cleanup_state(void *s) "%p freed"
|
||||
luring_unplug_fn(void *s, int blocked, int queued, int inflight) "LuringState %p blocked %d queued %d inflight %d"
|
||||
luring_do_submit(void *s, int blocked, int queued, int inflight) "LuringState %p blocked %d queued %d inflight %d"
|
||||
luring_do_submit_done(void *s, int ret) "LuringState %p submitted to kernel %d"
|
||||
luring_co_submit(void *bs, void *s, void *luringcb, int fd, uint64_t offset, size_t nbytes, int type) "bs %p s %p luringcb %p fd %d offset %" PRId64 " nbytes %zd type %d"
|
||||
luring_process_completion(void *s, void *aiocb, int ret) "LuringState %p luringcb %p ret %d"
|
||||
luring_io_uring_submit(void *s, int ret) "LuringState %p ret %d"
|
||||
luring_resubmit_short_read(void *s, void *luringcb, int nread) "LuringState %p luringcb %p nread %d"
|
||||
luring_cqe_handler(void *req, int ret) "req %p ret %d"
|
||||
luring_co_submit(void *bs, void *req, int fd, uint64_t offset, size_t nbytes, int type) "bs %p req %p fd %d offset %" PRId64 " nbytes %zd type %d"
|
||||
luring_resubmit_short_read(void *req, int nread) "req %p nread %d"
|
||||
|
||||
# qcow2.c
|
||||
qcow2_add_task(void *co, void *bs, void *pool, const char *action, int cluster_type, uint64_t host_offset, uint64_t offset, uint64_t bytes, void *qiov, size_t qiov_offset) "co %p bs %p pool %p: %s: cluster_type %d file_cluster_offset %" PRIu64 " offset %" PRIu64 " bytes %" PRIu64 " qiov %p qiov_offset %zu"
|
||||
|
||||
@@ -310,8 +310,6 @@ struct AioContext {
|
||||
struct LinuxAioState *linux_aio;
|
||||
#endif
|
||||
#ifdef CONFIG_LINUX_IO_URING
|
||||
LuringState *linux_io_uring;
|
||||
|
||||
/* State for file descriptor monitoring using Linux io_uring */
|
||||
struct io_uring fdmon_io_uring;
|
||||
AioHandlerSList submit_list;
|
||||
@@ -615,11 +613,6 @@ struct LinuxAioState *aio_setup_linux_aio(AioContext *ctx, Error **errp);
|
||||
/* Return the LinuxAioState bound to this AioContext */
|
||||
struct LinuxAioState *aio_get_linux_aio(AioContext *ctx);
|
||||
|
||||
/* Setup the LuringState bound to this AioContext */
|
||||
LuringState *aio_setup_linux_io_uring(AioContext *ctx, Error **errp);
|
||||
|
||||
/* Return the LuringState bound to this AioContext */
|
||||
LuringState *aio_get_linux_io_uring(AioContext *ctx);
|
||||
/**
|
||||
* aio_timer_new_with_attrs:
|
||||
* @ctx: the aio context
|
||||
|
||||
@@ -74,15 +74,10 @@ static inline bool laio_has_fua(void)
|
||||
#endif
|
||||
/* io_uring.c - Linux io_uring implementation */
|
||||
#ifdef CONFIG_LINUX_IO_URING
|
||||
LuringState *luring_init(Error **errp);
|
||||
void luring_cleanup(LuringState *s);
|
||||
|
||||
/* luring_co_submit: submit I/O requests in the thread's current AioContext. */
|
||||
int coroutine_fn luring_co_submit(BlockDriverState *bs, int fd, uint64_t offset,
|
||||
QEMUIOVector *qiov, int type,
|
||||
BdrvRequestFlags flags);
|
||||
void luring_detach_aio_context(LuringState *s, AioContext *old_context);
|
||||
void luring_attach_aio_context(LuringState *s, AioContext *new_context);
|
||||
bool luring_has_fua(void);
|
||||
#else
|
||||
static inline bool luring_has_fua(void)
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* Linux io_uring support.
|
||||
*
|
||||
* Copyright (C) 2009 IBM, Corp.
|
||||
* Copyright (C) 2009 Red Hat, Inc.
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "block/aio.h"
|
||||
#include "block/raw-aio.h"
|
||||
|
||||
void luring_detach_aio_context(LuringState *s, AioContext *old_context)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
void luring_attach_aio_context(LuringState *s, AioContext *new_context)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
LuringState *luring_init(Error **errp)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
void luring_cleanup(LuringState *s)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
@@ -32,9 +32,6 @@ if have_block or have_ga
|
||||
stub_ss.add(files('cpus-virtual-clock.c'))
|
||||
stub_ss.add(files('icount.c'))
|
||||
stub_ss.add(files('graph-lock.c'))
|
||||
if linux_io_uring.found()
|
||||
stub_ss.add(files('io_uring.c'))
|
||||
endif
|
||||
if libaio.found()
|
||||
stub_ss.add(files('linux-aio.c'))
|
||||
endif
|
||||
|
||||
@@ -386,14 +386,6 @@ aio_ctx_finalize(GSource *source)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LINUX_IO_URING
|
||||
if (ctx->linux_io_uring) {
|
||||
luring_detach_aio_context(ctx->linux_io_uring, ctx);
|
||||
luring_cleanup(ctx->linux_io_uring);
|
||||
ctx->linux_io_uring = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
assert(QSLIST_EMPTY(&ctx->scheduled_coroutines));
|
||||
qemu_bh_delete(ctx->co_schedule_bh);
|
||||
|
||||
@@ -469,29 +461,6 @@ LinuxAioState *aio_get_linux_aio(AioContext *ctx)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LINUX_IO_URING
|
||||
LuringState *aio_setup_linux_io_uring(AioContext *ctx, Error **errp)
|
||||
{
|
||||
if (ctx->linux_io_uring) {
|
||||
return ctx->linux_io_uring;
|
||||
}
|
||||
|
||||
ctx->linux_io_uring = luring_init(errp);
|
||||
if (!ctx->linux_io_uring) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
luring_attach_aio_context(ctx->linux_io_uring, ctx);
|
||||
return ctx->linux_io_uring;
|
||||
}
|
||||
|
||||
LuringState *aio_get_linux_io_uring(AioContext *ctx)
|
||||
{
|
||||
assert(ctx->linux_io_uring);
|
||||
return ctx->linux_io_uring;
|
||||
}
|
||||
#endif
|
||||
|
||||
void aio_notify(AioContext *ctx)
|
||||
{
|
||||
/*
|
||||
@@ -631,10 +600,6 @@ AioContext *aio_context_new(Error **errp)
|
||||
ctx->linux_aio = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LINUX_IO_URING
|
||||
ctx->linux_io_uring = NULL;
|
||||
#endif
|
||||
|
||||
ctx->thread_pool = NULL;
|
||||
qemu_rec_mutex_init(&ctx->lock);
|
||||
timerlistgroup_init(&ctx->tlg, aio_timerlist_notify, ctx);
|
||||
|
||||
Reference in New Issue
Block a user