Commit f2842ab5 authored by Jens Axboe's avatar Jens Axboe

io_uring: enable option to only trigger eventfd for async completions

If an application is using eventfd notifications with poll to know when
new SQEs can be issued, it's expecting the following read/writes to
complete inline. And with that, it knows that there are events available,
and don't want spurious wakeups on the eventfd for those requests.

This adds IORING_REGISTER_EVENTFD_ASYNC, which works just like
IORING_REGISTER_EVENTFD, except it only triggers notifications for events
that happen from async completions (IRQ, or io-wq worker completions).
Any completions inline from the submission itself will not trigger
notifications.
Suggested-by: default avatarMark Papadakis <markuspapadakis@icloud.com>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 69b3e546
...@@ -206,6 +206,7 @@ struct io_ring_ctx { ...@@ -206,6 +206,7 @@ struct io_ring_ctx {
int account_mem: 1; int account_mem: 1;
int cq_overflow_flushed: 1; int cq_overflow_flushed: 1;
int drain_next: 1; int drain_next: 1;
int eventfd_async: 1;
/* /*
* Ring buffer of indices into array of io_uring_sqe, which is * Ring buffer of indices into array of io_uring_sqe, which is
...@@ -963,13 +964,20 @@ static struct io_uring_cqe *io_get_cqring(struct io_ring_ctx *ctx) ...@@ -963,13 +964,20 @@ static struct io_uring_cqe *io_get_cqring(struct io_ring_ctx *ctx)
return &rings->cqes[tail & ctx->cq_mask]; return &rings->cqes[tail & ctx->cq_mask];
} }
static inline bool io_should_trigger_evfd(struct io_ring_ctx *ctx)
{
if (!ctx->eventfd_async)
return true;
return io_wq_current_is_worker() || in_interrupt();
}
static void io_cqring_ev_posted(struct io_ring_ctx *ctx) static void io_cqring_ev_posted(struct io_ring_ctx *ctx)
{ {
if (waitqueue_active(&ctx->wait)) if (waitqueue_active(&ctx->wait))
wake_up(&ctx->wait); wake_up(&ctx->wait);
if (waitqueue_active(&ctx->sqo_wait)) if (waitqueue_active(&ctx->sqo_wait))
wake_up(&ctx->sqo_wait); wake_up(&ctx->sqo_wait);
if (ctx->cq_ev_fd) if (ctx->cq_ev_fd && io_should_trigger_evfd(ctx))
eventfd_signal(ctx->cq_ev_fd, 1); eventfd_signal(ctx->cq_ev_fd, 1);
} }
...@@ -6556,10 +6564,17 @@ static int __io_uring_register(struct io_ring_ctx *ctx, unsigned opcode, ...@@ -6556,10 +6564,17 @@ static int __io_uring_register(struct io_ring_ctx *ctx, unsigned opcode,
ret = io_sqe_files_update(ctx, arg, nr_args); ret = io_sqe_files_update(ctx, arg, nr_args);
break; break;
case IORING_REGISTER_EVENTFD: case IORING_REGISTER_EVENTFD:
case IORING_REGISTER_EVENTFD_ASYNC:
ret = -EINVAL; ret = -EINVAL;
if (nr_args != 1) if (nr_args != 1)
break; break;
ret = io_eventfd_register(ctx, arg); ret = io_eventfd_register(ctx, arg);
if (ret)
break;
if (opcode == IORING_REGISTER_EVENTFD_ASYNC)
ctx->eventfd_async = 1;
else
ctx->eventfd_async = 0;
break; break;
case IORING_UNREGISTER_EVENTFD: case IORING_UNREGISTER_EVENTFD:
ret = -EINVAL; ret = -EINVAL;
......
...@@ -192,6 +192,7 @@ struct io_uring_params { ...@@ -192,6 +192,7 @@ struct io_uring_params {
#define IORING_REGISTER_EVENTFD 4 #define IORING_REGISTER_EVENTFD 4
#define IORING_UNREGISTER_EVENTFD 5 #define IORING_UNREGISTER_EVENTFD 5
#define IORING_REGISTER_FILES_UPDATE 6 #define IORING_REGISTER_FILES_UPDATE 6
#define IORING_REGISTER_EVENTFD_ASYNC 7
struct io_uring_files_update { struct io_uring_files_update {
__u32 offset; __u32 offset;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment