diff options
author | Christian Brauner <brauner@kernel.org> | 2025-01-10 12:01:21 +0100 |
---|---|---|
committer | Christian Brauner <brauner@kernel.org> | 2025-01-10 12:01:21 +0100 |
commit | 1623bc27a85a93e82194c8d077eccc464efa67db (patch) | |
tree | 491bd1e87d00a93d474579365add4d0dceb54fc1 /include | |
parent | afs: Fix merge preference rule failure condition (diff) | |
parent | Merge patch series "poll_wait: add mb() to fix theoretical race between waitq... (diff) | |
download | linux-1623bc27a85a93e82194c8d077eccc464efa67db.tar.xz linux-1623bc27a85a93e82194c8d077eccc464efa67db.zip |
Merge branch 'vfs-6.14.poll' into vfs.fixes
Bring in the fixes for __pollwait() and waitqueue_active() interactions.
Signed-off-by: Christian Brauner <brauner@kernel.org>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/poll.h | 26 | ||||
-rw-r--r-- | include/net/sock.h | 17 |
2 files changed, 19 insertions, 24 deletions
diff --git a/include/linux/poll.h b/include/linux/poll.h index d1ea4f3714a8..12bb18e8b978 100644 --- a/include/linux/poll.h +++ b/include/linux/poll.h @@ -25,14 +25,14 @@ struct poll_table_struct; -/* +/* * structures and helpers for f_op->poll implementations */ typedef void (*poll_queue_proc)(struct file *, wait_queue_head_t *, struct poll_table_struct *); /* - * Do not touch the structure directly, use the access functions - * poll_does_not_wait() and poll_requested_events() instead. + * Do not touch the structure directly, use the access function + * poll_requested_events() instead. */ typedef struct poll_table_struct { poll_queue_proc _qproc; @@ -41,18 +41,16 @@ typedef struct poll_table_struct { static inline void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p) { - if (p && p->_qproc && wait_address) + if (p && p->_qproc) { p->_qproc(filp, wait_address, p); -} - -/* - * Return true if it is guaranteed that poll will not wait. This is the case - * if the poll() of another file descriptor in the set got an event, so there - * is no need for waiting. - */ -static inline bool poll_does_not_wait(const poll_table *p) -{ - return p == NULL || p->_qproc == NULL; + /* + * This memory barrier is paired in the wq_has_sleeper(). + * See the comment above prepare_to_wait(), we need to + * ensure that subsequent tests in this thread can't be + * reordered with __add_wait_queue() in _qproc() paths. + */ + smp_mb(); + } } /* diff --git a/include/net/sock.h b/include/net/sock.h index c383126f691d..691ca7695d1d 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -2297,7 +2297,7 @@ static inline bool skwq_has_sleeper(struct socket_wq *wq) } /** - * sock_poll_wait - place memory barrier behind the poll_wait call. + * sock_poll_wait - wrapper for the poll_wait call. * @filp: file * @sock: socket to wait on * @p: poll_table @@ -2307,15 +2307,12 @@ static inline bool skwq_has_sleeper(struct socket_wq *wq) static inline void sock_poll_wait(struct file *filp, struct socket *sock, poll_table *p) { - if (!poll_does_not_wait(p)) { - poll_wait(filp, &sock->wq.wait, p); - /* We need to be sure we are in sync with the - * socket flags modification. - * - * This memory barrier is paired in the wq_has_sleeper. - */ - smp_mb(); - } + /* Provides a barrier we need to be sure we are in sync + * with the socket flags modification. + * + * This memory barrier is paired in the wq_has_sleeper. + */ + poll_wait(filp, &sock->wq.wait, p); } static inline void skb_set_hash_from_sk(struct sk_buff *skb, struct sock *sk) |