diff options
| author | Jens Axboe <axboe@kernel.dk> | 2024-09-21 01:59:51 -0600 |
|---|---|---|
| committer | Jens Axboe <axboe@kernel.dk> | 2024-10-29 13:43:26 -0600 |
| commit | 83a4f865e273b83426eafdd3aa51334cc21ac0fd (patch) | |
| tree | 6231a25b773116ff66c27b082bdf8f6c87d4f7e8 /io_uring | |
| parent | 3ca5a356041438534ecbb74159df91736238c6b1 (diff) | |
| download | linux-next-83a4f865e273b83426eafdd3aa51334cc21ac0fd.tar.gz linux-next-83a4f865e273b83426eafdd3aa51334cc21ac0fd.zip | |
io_uring/eventfd: abstract out ev_fd grab + release helpers
In preparation for needing the ev_fd grabbing (and releasing) from
another path, abstract out two helpers for that.
Link: https://lore.kernel.org/r/20240921080307.185186-6-axboe@kernel.dk
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'io_uring')
| -rw-r--r-- | io_uring/eventfd.c | 41 |
1 files changed, 30 insertions, 11 deletions
diff --git a/io_uring/eventfd.c b/io_uring/eventfd.c index 0946d3da88d3..d1fdecd0c458 100644 --- a/io_uring/eventfd.c +++ b/io_uring/eventfd.c @@ -47,6 +47,13 @@ static void io_eventfd_put(struct io_ev_fd *ev_fd) call_rcu(&ev_fd->rcu, io_eventfd_free); } +static void io_eventfd_release(struct io_ev_fd *ev_fd, bool put_ref) +{ + if (put_ref) + io_eventfd_put(ev_fd); + rcu_read_unlock(); +} + /* * Returns true if the caller should put the ev_fd reference, false if not. */ @@ -74,14 +81,18 @@ static bool io_eventfd_trigger(struct io_ev_fd *ev_fd) return false; } -void io_eventfd_signal(struct io_ring_ctx *ctx) +/* + * On success, returns with an ev_fd reference grabbed and the RCU read + * lock held. + */ +static struct io_ev_fd *io_eventfd_grab(struct io_ring_ctx *ctx) { - struct io_ev_fd *ev_fd = NULL; + struct io_ev_fd *ev_fd; if (READ_ONCE(ctx->rings->cq_flags) & IORING_CQ_EVENTFD_DISABLED) - return; + return NULL; - guard(rcu)(); + rcu_read_lock(); /* * rcu_dereference ctx->io_ev_fd once and use it for both for checking @@ -90,16 +101,24 @@ void io_eventfd_signal(struct io_ring_ctx *ctx) ev_fd = rcu_dereference(ctx->io_ev_fd); /* - * Check again if ev_fd exists incase an io_eventfd_unregister call + * Check again if ev_fd exists in case an io_eventfd_unregister call * completed between the NULL check of ctx->io_ev_fd at the start of * the function and rcu_read_lock. */ - if (!io_eventfd_trigger(ev_fd)) - return; - if (!refcount_inc_not_zero(&ev_fd->refs)) - return; - if (__io_eventfd_signal(ev_fd)) - io_eventfd_put(ev_fd); + if (io_eventfd_trigger(ev_fd) && refcount_inc_not_zero(&ev_fd->refs)) + return ev_fd; + + rcu_read_unlock(); + return NULL; +} + +void io_eventfd_signal(struct io_ring_ctx *ctx) +{ + struct io_ev_fd *ev_fd; + + ev_fd = io_eventfd_grab(ctx); + if (ev_fd) + io_eventfd_release(ev_fd, __io_eventfd_signal(ev_fd)); } void io_eventfd_flush_signal(struct io_ring_ctx *ctx) |
