summaryrefslogtreecommitdiff
path: root/io_uring/register.c
diff options
context:
space:
mode:
authorJens Axboe <axboe@kernel.dk>2024-06-03 11:19:10 -0600
committerJens Axboe <axboe@kernel.dk>2024-06-16 14:54:55 -0600
commit60b6c075e8eb8bd23c106e2ab13370a146a94a5b (patch)
treec0e9290454a312d572705bbb9f6d242a5ba32605 /io_uring/register.c
parentf4eaf8eda89e1ae5d8274297094687245293deff (diff)
downloadlwn-60b6c075e8eb8bd23c106e2ab13370a146a94a5b.tar.gz
lwn-60b6c075e8eb8bd23c106e2ab13370a146a94a5b.zip
io_uring/eventfd: move to more idiomatic RCU free usage
In some ways, it just "happens to work" currently with using the ops field for both the free and signaling bit. But it depends on ordering of operations in terms of freeing and signaling. Clean it up and use the usual refs == 0 under RCU read side lock to determine if the ev_fd is still valid, and use the reference to gate the freeing as well. Fixes: 21a091b970cd ("io_uring: signal registered eventfd to process deferred task work") Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'io_uring/register.c')
-rw-r--r--io_uring/register.c6
1 files changed, 3 insertions, 3 deletions
diff --git a/io_uring/register.c b/io_uring/register.c
index c0010a66a6f2..212711e9bc8a 100644
--- a/io_uring/register.c
+++ b/io_uring/register.c
@@ -63,9 +63,9 @@ static int io_eventfd_register(struct io_ring_ctx *ctx, void __user *arg,
ev_fd->eventfd_async = eventfd_async;
ctx->has_evfd = true;
- rcu_assign_pointer(ctx->io_ev_fd, ev_fd);
atomic_set(&ev_fd->refs, 1);
atomic_set(&ev_fd->ops, 0);
+ rcu_assign_pointer(ctx->io_ev_fd, ev_fd);
return 0;
}
@@ -78,8 +78,8 @@ int io_eventfd_unregister(struct io_ring_ctx *ctx)
if (ev_fd) {
ctx->has_evfd = false;
rcu_assign_pointer(ctx->io_ev_fd, NULL);
- if (!atomic_fetch_or(BIT(IO_EVENTFD_OP_FREE_BIT), &ev_fd->ops))
- call_rcu(&ev_fd->rcu, io_eventfd_ops);
+ if (atomic_dec_and_test(&ev_fd->refs))
+ call_rcu(&ev_fd->rcu, io_eventfd_free);
return 0;
}