Skip to content

Commit ab6956a

Browse files
axboegregkh
authored andcommitted
UPSTREAM: eventfd: provide a eventfd_signal_mask() helper
[ Upstream commit 03e02acda8e267a8183e1e0ed289ff1ef9cd7ed8 ] This is identical to eventfd_signal(), but it allows the caller to pass in a mask to be used for the poll wakeup key. The use case is avoiding repeated multishot triggers if we have a dependency between eventfd and io_uring. If we setup an eventfd context and register that as the io_uring eventfd, and at the same time queue a multishot poll request for the eventfd context, then any CQE posted will repeatedly trigger the multishot request until it terminates when the CQ ring overflows. In preparation for io_uring detecting this circular dependency, add the mentioned helper so that io_uring can pass in EPOLL_URING as part of the poll wakeup key. Cc: stable@vger.kernel.org # 6.0 [axboe: fold in !CONFIG_EVENTFD fix from Zhang Qilong] Change-Id: I91472ab0a4233368431b9b4d8d897f9639946675 Signed-off-by: Jens Axboe <axboe@kernel.dk> Signed-off-by: Sasha Levin <sashal@kernel.org> (cherry picked from commit 77baf39) Bug: 268174392 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
1 parent b4ab4ac commit ab6956a

File tree

2 files changed

+28
-16
lines changed

2 files changed

+28
-16
lines changed

fs/eventfd.c

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -43,21 +43,7 @@ struct eventfd_ctx {
4343
int id;
4444
};
4545

46-
/**
47-
* eventfd_signal - Adds @n to the eventfd counter.
48-
* @ctx: [in] Pointer to the eventfd context.
49-
* @n: [in] Value of the counter to be added to the eventfd internal counter.
50-
* The value cannot be negative.
51-
*
52-
* This function is supposed to be called by the kernel in paths that do not
53-
* allow sleeping. In this function we allow the counter to reach the ULLONG_MAX
54-
* value, and we signal this as overflow condition by returning a EPOLLERR
55-
* to poll(2).
56-
*
57-
* Returns the amount by which the counter was incremented. This will be less
58-
* than @n if the counter has overflowed.
59-
*/
60-
__u64 eventfd_signal(struct eventfd_ctx *ctx, __u64 n)
46+
__u64 eventfd_signal_mask(struct eventfd_ctx *ctx, __u64 n, unsigned mask)
6147
{
6248
unsigned long flags;
6349

@@ -78,12 +64,31 @@ __u64 eventfd_signal(struct eventfd_ctx *ctx, __u64 n)
7864
n = ULLONG_MAX - ctx->count;
7965
ctx->count += n;
8066
if (waitqueue_active(&ctx->wqh))
81-
wake_up_locked_poll(&ctx->wqh, EPOLLIN);
67+
wake_up_locked_poll(&ctx->wqh, EPOLLIN | mask);
8268
current->in_eventfd_signal = 0;
8369
spin_unlock_irqrestore(&ctx->wqh.lock, flags);
8470

8571
return n;
8672
}
73+
74+
/**
75+
* eventfd_signal - Adds @n to the eventfd counter.
76+
* @ctx: [in] Pointer to the eventfd context.
77+
* @n: [in] Value of the counter to be added to the eventfd internal counter.
78+
* The value cannot be negative.
79+
*
80+
* This function is supposed to be called by the kernel in paths that do not
81+
* allow sleeping. In this function we allow the counter to reach the ULLONG_MAX
82+
* value, and we signal this as overflow condition by returning a EPOLLERR
83+
* to poll(2).
84+
*
85+
* Returns the amount by which the counter was incremented. This will be less
86+
* than @n if the counter has overflowed.
87+
*/
88+
__u64 eventfd_signal(struct eventfd_ctx *ctx, __u64 n)
89+
{
90+
return eventfd_signal_mask(ctx, n, 0);
91+
}
8792
EXPORT_SYMBOL_GPL(eventfd_signal);
8893

8994
static void eventfd_free_ctx(struct eventfd_ctx *ctx)

include/linux/eventfd.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ struct file *eventfd_fget(int fd);
4040
struct eventfd_ctx *eventfd_ctx_fdget(int fd);
4141
struct eventfd_ctx *eventfd_ctx_fileget(struct file *file);
4242
__u64 eventfd_signal(struct eventfd_ctx *ctx, __u64 n);
43+
__u64 eventfd_signal_mask(struct eventfd_ctx *ctx, __u64 n, unsigned mask);
4344
int eventfd_ctx_remove_wait_queue(struct eventfd_ctx *ctx, wait_queue_entry_t *wait,
4445
__u64 *cnt);
4546
void eventfd_ctx_do_read(struct eventfd_ctx *ctx, __u64 *cnt);
@@ -66,6 +67,12 @@ static inline int eventfd_signal(struct eventfd_ctx *ctx, int n)
6667
return -ENOSYS;
6768
}
6869

70+
static inline int eventfd_signal_mask(struct eventfd_ctx *ctx, __u64 n,
71+
unsigned mask)
72+
{
73+
return -ENOSYS;
74+
}
75+
6976
static inline void eventfd_ctx_put(struct eventfd_ctx *ctx)
7077
{
7178

0 commit comments

Comments
 (0)