io_uring: add support for eventfd notifications

Allow registration of an eventfd, which will trigger an event every
time a completion event happens for this io_uring instance.

Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
Jens Axboe 2019-04-11 11:45:41 -06:00
parent 5d17b4a4b7
commit 9b402849e8
2 changed files with 50 additions and 0 deletions

View File

@ -241,6 +241,7 @@ struct io_ring_ctx {
unsigned cq_mask; unsigned cq_mask;
struct wait_queue_head cq_wait; struct wait_queue_head cq_wait;
struct fasync_struct *cq_fasync; struct fasync_struct *cq_fasync;
struct eventfd_ctx *cq_ev_fd;
} ____cacheline_aligned_in_smp; } ____cacheline_aligned_in_smp;
/* /*
@ -516,6 +517,8 @@ static void io_cqring_ev_posted(struct io_ring_ctx *ctx)
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)
eventfd_signal(ctx->cq_ev_fd, 1);
} }
static void io_cqring_add_event(struct io_ring_ctx *ctx, u64 user_data, static void io_cqring_add_event(struct io_ring_ctx *ctx, u64 user_data,
@ -2757,6 +2760,38 @@ err:
return ret; return ret;
} }
static int io_eventfd_register(struct io_ring_ctx *ctx, void __user *arg)
{
__s32 __user *fds = arg;
int fd;
if (ctx->cq_ev_fd)
return -EBUSY;
if (copy_from_user(&fd, fds, sizeof(*fds)))
return -EFAULT;
ctx->cq_ev_fd = eventfd_ctx_fdget(fd);
if (IS_ERR(ctx->cq_ev_fd)) {
int ret = PTR_ERR(ctx->cq_ev_fd);
ctx->cq_ev_fd = NULL;
return ret;
}
return 0;
}
static int io_eventfd_unregister(struct io_ring_ctx *ctx)
{
if (ctx->cq_ev_fd) {
eventfd_ctx_put(ctx->cq_ev_fd);
ctx->cq_ev_fd = NULL;
return 0;
}
return -ENXIO;
}
static void io_ring_ctx_free(struct io_ring_ctx *ctx) static void io_ring_ctx_free(struct io_ring_ctx *ctx)
{ {
io_finish_async(ctx); io_finish_async(ctx);
@ -2766,6 +2801,7 @@ static void io_ring_ctx_free(struct io_ring_ctx *ctx)
io_iopoll_reap_events(ctx); io_iopoll_reap_events(ctx);
io_sqe_buffer_unregister(ctx); io_sqe_buffer_unregister(ctx);
io_sqe_files_unregister(ctx); io_sqe_files_unregister(ctx);
io_eventfd_unregister(ctx);
#if defined(CONFIG_UNIX) #if defined(CONFIG_UNIX)
if (ctx->ring_sock) if (ctx->ring_sock)
@ -3179,6 +3215,18 @@ static int __io_uring_register(struct io_ring_ctx *ctx, unsigned opcode,
break; break;
ret = io_sqe_files_unregister(ctx); ret = io_sqe_files_unregister(ctx);
break; break;
case IORING_REGISTER_EVENTFD:
ret = -EINVAL;
if (nr_args != 1)
break;
ret = io_eventfd_register(ctx, arg);
break;
case IORING_UNREGISTER_EVENTFD:
ret = -EINVAL;
if (arg || nr_args)
break;
ret = io_eventfd_unregister(ctx);
break;
default: default:
ret = -EINVAL; ret = -EINVAL;
break; break;

View File

@ -136,5 +136,7 @@ struct io_uring_params {
#define IORING_UNREGISTER_BUFFERS 1 #define IORING_UNREGISTER_BUFFERS 1
#define IORING_REGISTER_FILES 2 #define IORING_REGISTER_FILES 2
#define IORING_UNREGISTER_FILES 3 #define IORING_UNREGISTER_FILES 3
#define IORING_REGISTER_EVENTFD 4
#define IORING_UNREGISTER_EVENTFD 5
#endif #endif