Skip to content

Commit

Permalink
net: Generalise wq_has_sleeper helper
Browse files Browse the repository at this point in the history
The memory barrier in the helper wq_has_sleeper is needed by just
about every user of waitqueue_active.  This patch generalises it
by making it take a wait_queue_head_t directly.  The existing
helper is renamed to skwq_has_sleeper.

Signed-off-by: Herbert Xu <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
herbertx authored and davem330 committed Nov 30, 2015
1 parent c52fd05 commit 1ce0bf5
Show file tree
Hide file tree
Showing 13 changed files with 44 additions and 28 deletions.
4 changes: 2 additions & 2 deletions crypto/algif_aead.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ static void aead_wmem_wakeup(struct sock *sk)

rcu_read_lock();
wq = rcu_dereference(sk->sk_wq);
if (wq_has_sleeper(wq))
if (skwq_has_sleeper(wq))
wake_up_interruptible_sync_poll(&wq->wait, POLLIN |
POLLRDNORM |
POLLRDBAND);
Expand Down Expand Up @@ -157,7 +157,7 @@ static void aead_data_wakeup(struct sock *sk)

rcu_read_lock();
wq = rcu_dereference(sk->sk_wq);
if (wq_has_sleeper(wq))
if (skwq_has_sleeper(wq))
wake_up_interruptible_sync_poll(&wq->wait, POLLOUT |
POLLRDNORM |
POLLRDBAND);
Expand Down
4 changes: 2 additions & 2 deletions crypto/algif_skcipher.c
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ static void skcipher_wmem_wakeup(struct sock *sk)

rcu_read_lock();
wq = rcu_dereference(sk->sk_wq);
if (wq_has_sleeper(wq))
if (skwq_has_sleeper(wq))
wake_up_interruptible_sync_poll(&wq->wait, POLLIN |
POLLRDNORM |
POLLRDBAND);
Expand Down Expand Up @@ -288,7 +288,7 @@ static void skcipher_data_wakeup(struct sock *sk)

rcu_read_lock();
wq = rcu_dereference(sk->sk_wq);
if (wq_has_sleeper(wq))
if (skwq_has_sleeper(wq))
wake_up_interruptible_sync_poll(&wq->wait, POLLOUT |
POLLRDNORM |
POLLRDBAND);
Expand Down
21 changes: 21 additions & 0 deletions include/linux/wait.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,27 @@ static inline int waitqueue_active(wait_queue_head_t *q)
return !list_empty(&q->task_list);
}

/**
* wq_has_sleeper - check if there are any waiting processes
* @wq: wait queue head
*
* Returns true if wq has waiting processes
*
* Please refer to the comment for waitqueue_active.
*/
static inline bool wq_has_sleeper(wait_queue_head_t *wq)
{
/*
* We need to be sure we are in sync with the
* add_wait_queue modifications to the wait queue.
*
* This memory barrier should be paired with one on the
* waiting side.
*/
smp_mb();
return waitqueue_active(wq);
}

extern void add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait);
extern void add_wait_queue_exclusive(wait_queue_head_t *q, wait_queue_t *wait);
extern void remove_wait_queue(wait_queue_head_t *q, wait_queue_t *wait);
Expand Down
15 changes: 5 additions & 10 deletions include/net/sock.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
#include <linux/memcontrol.h>
#include <linux/static_key.h>
#include <linux/sched.h>
#include <linux/wait.h>

#include <linux/filter.h>
#include <linux/rculist_nulls.h>
Expand Down Expand Up @@ -1879,12 +1880,12 @@ static inline bool sk_has_allocations(const struct sock *sk)
}

/**
* wq_has_sleeper - check if there are any waiting processes
* skwq_has_sleeper - check if there are any waiting processes
* @wq: struct socket_wq
*
* Returns true if socket_wq has waiting processes
*
* The purpose of the wq_has_sleeper and sock_poll_wait is to wrap the memory
* The purpose of the skwq_has_sleeper and sock_poll_wait is to wrap the memory
* barrier call. They were added due to the race found within the tcp code.
*
* Consider following tcp code paths:
Expand All @@ -1910,15 +1911,9 @@ static inline bool sk_has_allocations(const struct sock *sk)
* data on the socket.
*
*/
static inline bool wq_has_sleeper(struct socket_wq *wq)
static inline bool skwq_has_sleeper(struct socket_wq *wq)
{
/* We need to be sure we are in sync with the
* add_wait_queue modifications to the wait queue.
*
* This memory barrier is paired in the sock_poll_wait.
*/
smp_mb();
return wq && waitqueue_active(&wq->wait);
return wq && wq_has_sleeper(&wq->wait);
}

/**
Expand Down
4 changes: 2 additions & 2 deletions net/atm/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ static void vcc_def_wakeup(struct sock *sk)

rcu_read_lock();
wq = rcu_dereference(sk->sk_wq);
if (wq_has_sleeper(wq))
if (skwq_has_sleeper(wq))
wake_up(&wq->wait);
rcu_read_unlock();
}
Expand All @@ -117,7 +117,7 @@ static void vcc_write_space(struct sock *sk)

if (vcc_writable(sk)) {
wq = rcu_dereference(sk->sk_wq);
if (wq_has_sleeper(wq))
if (skwq_has_sleeper(wq))
wake_up_interruptible(&wq->wait);

sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT);
Expand Down
8 changes: 4 additions & 4 deletions net/core/sock.c
Original file line number Diff line number Diff line change
Expand Up @@ -2283,7 +2283,7 @@ static void sock_def_wakeup(struct sock *sk)

rcu_read_lock();
wq = rcu_dereference(sk->sk_wq);
if (wq_has_sleeper(wq))
if (skwq_has_sleeper(wq))
wake_up_interruptible_all(&wq->wait);
rcu_read_unlock();
}
Expand All @@ -2294,7 +2294,7 @@ static void sock_def_error_report(struct sock *sk)

rcu_read_lock();
wq = rcu_dereference(sk->sk_wq);
if (wq_has_sleeper(wq))
if (skwq_has_sleeper(wq))
wake_up_interruptible_poll(&wq->wait, POLLERR);
sk_wake_async(sk, SOCK_WAKE_IO, POLL_ERR);
rcu_read_unlock();
Expand All @@ -2306,7 +2306,7 @@ static void sock_def_readable(struct sock *sk)

rcu_read_lock();
wq = rcu_dereference(sk->sk_wq);
if (wq_has_sleeper(wq))
if (skwq_has_sleeper(wq))
wake_up_interruptible_sync_poll(&wq->wait, POLLIN | POLLPRI |
POLLRDNORM | POLLRDBAND);
sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN);
Expand All @@ -2324,7 +2324,7 @@ static void sock_def_write_space(struct sock *sk)
*/
if ((atomic_read(&sk->sk_wmem_alloc) << 1) <= sk->sk_sndbuf) {
wq = rcu_dereference(sk->sk_wq);
if (wq_has_sleeper(wq))
if (skwq_has_sleeper(wq))
wake_up_interruptible_sync_poll(&wq->wait, POLLOUT |
POLLWRNORM | POLLWRBAND);

Expand Down
2 changes: 1 addition & 1 deletion net/core/stream.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ void sk_stream_write_space(struct sock *sk)

rcu_read_lock();
wq = rcu_dereference(sk->sk_wq);
if (wq_has_sleeper(wq))
if (skwq_has_sleeper(wq))
wake_up_interruptible_poll(&wq->wait, POLLOUT |
POLLWRNORM | POLLWRBAND);
if (wq && wq->fasync_list && !(sk->sk_shutdown & SEND_SHUTDOWN))
Expand Down
2 changes: 1 addition & 1 deletion net/dccp/output.c
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ void dccp_write_space(struct sock *sk)

rcu_read_lock();
wq = rcu_dereference(sk->sk_wq);
if (wq_has_sleeper(wq))
if (skwq_has_sleeper(wq))
wake_up_interruptible(&wq->wait);
/* Should agree with poll, otherwise some programs break */
if (sock_writeable(sk))
Expand Down
2 changes: 1 addition & 1 deletion net/iucv/af_iucv.c
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ static void iucv_sock_wake_msglim(struct sock *sk)

rcu_read_lock();
wq = rcu_dereference(sk->sk_wq);
if (wq_has_sleeper(wq))
if (skwq_has_sleeper(wq))
wake_up_interruptible_all(&wq->wait);
sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT);
rcu_read_unlock();
Expand Down
2 changes: 1 addition & 1 deletion net/rxrpc/af_rxrpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ static void rxrpc_write_space(struct sock *sk)
if (rxrpc_writable(sk)) {
struct socket_wq *wq = rcu_dereference(sk->sk_wq);

if (wq_has_sleeper(wq))
if (skwq_has_sleeper(wq))
wake_up_interruptible(&wq->wait);
sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT);
}
Expand Down
2 changes: 1 addition & 1 deletion net/sctp/socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -6978,7 +6978,7 @@ void sctp_data_ready(struct sock *sk)

rcu_read_lock();
wq = rcu_dereference(sk->sk_wq);
if (wq_has_sleeper(wq))
if (skwq_has_sleeper(wq))
wake_up_interruptible_sync_poll(&wq->wait, POLLIN |
POLLRDNORM | POLLRDBAND);
sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN);
Expand Down
4 changes: 2 additions & 2 deletions net/tipc/socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -1492,7 +1492,7 @@ static void tipc_write_space(struct sock *sk)

rcu_read_lock();
wq = rcu_dereference(sk->sk_wq);
if (wq_has_sleeper(wq))
if (skwq_has_sleeper(wq))
wake_up_interruptible_sync_poll(&wq->wait, POLLOUT |
POLLWRNORM | POLLWRBAND);
rcu_read_unlock();
Expand All @@ -1509,7 +1509,7 @@ static void tipc_data_ready(struct sock *sk)

rcu_read_lock();
wq = rcu_dereference(sk->sk_wq);
if (wq_has_sleeper(wq))
if (skwq_has_sleeper(wq))
wake_up_interruptible_sync_poll(&wq->wait, POLLIN |
POLLRDNORM | POLLRDBAND);
rcu_read_unlock();
Expand Down
2 changes: 1 addition & 1 deletion net/unix/af_unix.c
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ static void unix_write_space(struct sock *sk)
rcu_read_lock();
if (unix_writable(sk)) {
wq = rcu_dereference(sk->sk_wq);
if (wq_has_sleeper(wq))
if (skwq_has_sleeper(wq))
wake_up_interruptible_sync_poll(&wq->wait,
POLLOUT | POLLWRNORM | POLLWRBAND);
sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT);
Expand Down

0 comments on commit 1ce0bf5

Please sign in to comment.