aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2015-11-26 00:55:39 -0500
committerDavid S. Miller <davem@davemloft.net>2015-11-30 14:47:33 -0500
commit1ce0bf50ae2233c7115a18c0c623662d177b434c (patch)
tree41860e17fe4b2184055d29e669e503d09796775a
parentc52fd05a2ff2ad20e2a7056baf314c7d1d624ba9 (diff)
net: Generalise wq_has_sleeper helper
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 <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--crypto/algif_aead.c4
-rw-r--r--crypto/algif_skcipher.c4
-rw-r--r--include/linux/wait.h21
-rw-r--r--include/net/sock.h15
-rw-r--r--net/atm/common.c4
-rw-r--r--net/core/sock.c8
-rw-r--r--net/core/stream.c2
-rw-r--r--net/dccp/output.c2
-rw-r--r--net/iucv/af_iucv.c2
-rw-r--r--net/rxrpc/af_rxrpc.c2
-rw-r--r--net/sctp/socket.c2
-rw-r--r--net/tipc/socket.c4
-rw-r--r--net/unix/af_unix.c2
13 files changed, 44 insertions, 28 deletions
diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c
index 0aa6fdfb448a..fb99f30849d2 100644
--- a/crypto/algif_aead.c
+++ b/crypto/algif_aead.c
@@ -106,7 +106,7 @@ static void aead_wmem_wakeup(struct sock *sk)
106 106
107 rcu_read_lock(); 107 rcu_read_lock();
108 wq = rcu_dereference(sk->sk_wq); 108 wq = rcu_dereference(sk->sk_wq);
109 if (wq_has_sleeper(wq)) 109 if (skwq_has_sleeper(wq))
110 wake_up_interruptible_sync_poll(&wq->wait, POLLIN | 110 wake_up_interruptible_sync_poll(&wq->wait, POLLIN |
111 POLLRDNORM | 111 POLLRDNORM |
112 POLLRDBAND); 112 POLLRDBAND);
@@ -157,7 +157,7 @@ static void aead_data_wakeup(struct sock *sk)
157 157
158 rcu_read_lock(); 158 rcu_read_lock();
159 wq = rcu_dereference(sk->sk_wq); 159 wq = rcu_dereference(sk->sk_wq);
160 if (wq_has_sleeper(wq)) 160 if (skwq_has_sleeper(wq))
161 wake_up_interruptible_sync_poll(&wq->wait, POLLOUT | 161 wake_up_interruptible_sync_poll(&wq->wait, POLLOUT |
162 POLLRDNORM | 162 POLLRDNORM |
163 POLLRDBAND); 163 POLLRDBAND);
diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
index af31a0ee4057..0e6702e41472 100644
--- a/crypto/algif_skcipher.c
+++ b/crypto/algif_skcipher.c
@@ -238,7 +238,7 @@ static void skcipher_wmem_wakeup(struct sock *sk)
238 238
239 rcu_read_lock(); 239 rcu_read_lock();
240 wq = rcu_dereference(sk->sk_wq); 240 wq = rcu_dereference(sk->sk_wq);
241 if (wq_has_sleeper(wq)) 241 if (skwq_has_sleeper(wq))
242 wake_up_interruptible_sync_poll(&wq->wait, POLLIN | 242 wake_up_interruptible_sync_poll(&wq->wait, POLLIN |
243 POLLRDNORM | 243 POLLRDNORM |
244 POLLRDBAND); 244 POLLRDBAND);
@@ -288,7 +288,7 @@ static void skcipher_data_wakeup(struct sock *sk)
288 288
289 rcu_read_lock(); 289 rcu_read_lock();
290 wq = rcu_dereference(sk->sk_wq); 290 wq = rcu_dereference(sk->sk_wq);
291 if (wq_has_sleeper(wq)) 291 if (skwq_has_sleeper(wq))
292 wake_up_interruptible_sync_poll(&wq->wait, POLLOUT | 292 wake_up_interruptible_sync_poll(&wq->wait, POLLOUT |
293 POLLRDNORM | 293 POLLRDNORM |
294 POLLRDBAND); 294 POLLRDBAND);
diff --git a/include/linux/wait.h b/include/linux/wait.h
index 1e1bf9f963a9..6aa09a875fbd 100644
--- a/include/linux/wait.h
+++ b/include/linux/wait.h
@@ -107,6 +107,27 @@ static inline int waitqueue_active(wait_queue_head_t *q)
107 return !list_empty(&q->task_list); 107 return !list_empty(&q->task_list);
108} 108}
109 109
110/**
111 * wq_has_sleeper - check if there are any waiting processes
112 * @wq: wait queue head
113 *
114 * Returns true if wq has waiting processes
115 *
116 * Please refer to the comment for waitqueue_active.
117 */
118static inline bool wq_has_sleeper(wait_queue_head_t *wq)
119{
120 /*
121 * We need to be sure we are in sync with the
122 * add_wait_queue modifications to the wait queue.
123 *
124 * This memory barrier should be paired with one on the
125 * waiting side.
126 */
127 smp_mb();
128 return waitqueue_active(wq);
129}
130
110extern void add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait); 131extern void add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait);
111extern void add_wait_queue_exclusive(wait_queue_head_t *q, wait_queue_t *wait); 132extern void add_wait_queue_exclusive(wait_queue_head_t *q, wait_queue_t *wait);
112extern void remove_wait_queue(wait_queue_head_t *q, wait_queue_t *wait); 133extern void remove_wait_queue(wait_queue_head_t *q, wait_queue_t *wait);
diff --git a/include/net/sock.h b/include/net/sock.h
index 7f89e4ba18d1..62d35afcb3ac 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -58,6 +58,7 @@
58#include <linux/memcontrol.h> 58#include <linux/memcontrol.h>
59#include <linux/static_key.h> 59#include <linux/static_key.h>
60#include <linux/sched.h> 60#include <linux/sched.h>
61#include <linux/wait.h>
61 62
62#include <linux/filter.h> 63#include <linux/filter.h>
63#include <linux/rculist_nulls.h> 64#include <linux/rculist_nulls.h>
@@ -1879,12 +1880,12 @@ static inline bool sk_has_allocations(const struct sock *sk)
1879} 1880}
1880 1881
1881/** 1882/**
1882 * wq_has_sleeper - check if there are any waiting processes 1883 * skwq_has_sleeper - check if there are any waiting processes
1883 * @wq: struct socket_wq 1884 * @wq: struct socket_wq
1884 * 1885 *
1885 * Returns true if socket_wq has waiting processes 1886 * Returns true if socket_wq has waiting processes
1886 * 1887 *
1887 * The purpose of the wq_has_sleeper and sock_poll_wait is to wrap the memory 1888 * The purpose of the skwq_has_sleeper and sock_poll_wait is to wrap the memory
1888 * barrier call. They were added due to the race found within the tcp code. 1889 * barrier call. They were added due to the race found within the tcp code.
1889 * 1890 *
1890 * Consider following tcp code paths: 1891 * Consider following tcp code paths:
@@ -1910,15 +1911,9 @@ static inline bool sk_has_allocations(const struct sock *sk)
1910 * data on the socket. 1911 * data on the socket.
1911 * 1912 *
1912 */ 1913 */
1913static inline bool wq_has_sleeper(struct socket_wq *wq) 1914static inline bool skwq_has_sleeper(struct socket_wq *wq)
1914{ 1915{
1915 /* We need to be sure we are in sync with the 1916 return wq && wq_has_sleeper(&wq->wait);
1916 * add_wait_queue modifications to the wait queue.
1917 *
1918 * This memory barrier is paired in the sock_poll_wait.
1919 */
1920 smp_mb();
1921 return wq && waitqueue_active(&wq->wait);
1922} 1917}
1923 1918
1924/** 1919/**
diff --git a/net/atm/common.c b/net/atm/common.c
index 49a872db7e42..6dc12305799e 100644
--- a/net/atm/common.c
+++ b/net/atm/common.c
@@ -96,7 +96,7 @@ static void vcc_def_wakeup(struct sock *sk)
96 96
97 rcu_read_lock(); 97 rcu_read_lock();
98 wq = rcu_dereference(sk->sk_wq); 98 wq = rcu_dereference(sk->sk_wq);
99 if (wq_has_sleeper(wq)) 99 if (skwq_has_sleeper(wq))
100 wake_up(&wq->wait); 100 wake_up(&wq->wait);
101 rcu_read_unlock(); 101 rcu_read_unlock();
102} 102}
@@ -117,7 +117,7 @@ static void vcc_write_space(struct sock *sk)
117 117
118 if (vcc_writable(sk)) { 118 if (vcc_writable(sk)) {
119 wq = rcu_dereference(sk->sk_wq); 119 wq = rcu_dereference(sk->sk_wq);
120 if (wq_has_sleeper(wq)) 120 if (skwq_has_sleeper(wq))
121 wake_up_interruptible(&wq->wait); 121 wake_up_interruptible(&wq->wait);
122 122
123 sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); 123 sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT);
diff --git a/net/core/sock.c b/net/core/sock.c
index 1e4dd54bfb5a..2769bd3a4d7c 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -2283,7 +2283,7 @@ static void sock_def_wakeup(struct sock *sk)
2283 2283
2284 rcu_read_lock(); 2284 rcu_read_lock();
2285 wq = rcu_dereference(sk->sk_wq); 2285 wq = rcu_dereference(sk->sk_wq);
2286 if (wq_has_sleeper(wq)) 2286 if (skwq_has_sleeper(wq))
2287 wake_up_interruptible_all(&wq->wait); 2287 wake_up_interruptible_all(&wq->wait);
2288 rcu_read_unlock(); 2288 rcu_read_unlock();
2289} 2289}
@@ -2294,7 +2294,7 @@ static void sock_def_error_report(struct sock *sk)
2294 2294
2295 rcu_read_lock(); 2295 rcu_read_lock();
2296 wq = rcu_dereference(sk->sk_wq); 2296 wq = rcu_dereference(sk->sk_wq);
2297 if (wq_has_sleeper(wq)) 2297 if (skwq_has_sleeper(wq))
2298 wake_up_interruptible_poll(&wq->wait, POLLERR); 2298 wake_up_interruptible_poll(&wq->wait, POLLERR);
2299 sk_wake_async(sk, SOCK_WAKE_IO, POLL_ERR); 2299 sk_wake_async(sk, SOCK_WAKE_IO, POLL_ERR);
2300 rcu_read_unlock(); 2300 rcu_read_unlock();
@@ -2306,7 +2306,7 @@ static void sock_def_readable(struct sock *sk)
2306 2306
2307 rcu_read_lock(); 2307 rcu_read_lock();
2308 wq = rcu_dereference(sk->sk_wq); 2308 wq = rcu_dereference(sk->sk_wq);
2309 if (wq_has_sleeper(wq)) 2309 if (skwq_has_sleeper(wq))
2310 wake_up_interruptible_sync_poll(&wq->wait, POLLIN | POLLPRI | 2310 wake_up_interruptible_sync_poll(&wq->wait, POLLIN | POLLPRI |
2311 POLLRDNORM | POLLRDBAND); 2311 POLLRDNORM | POLLRDBAND);
2312 sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN); 2312 sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN);
@@ -2324,7 +2324,7 @@ static void sock_def_write_space(struct sock *sk)
2324 */ 2324 */
2325 if ((atomic_read(&sk->sk_wmem_alloc) << 1) <= sk->sk_sndbuf) { 2325 if ((atomic_read(&sk->sk_wmem_alloc) << 1) <= sk->sk_sndbuf) {
2326 wq = rcu_dereference(sk->sk_wq); 2326 wq = rcu_dereference(sk->sk_wq);
2327 if (wq_has_sleeper(wq)) 2327 if (skwq_has_sleeper(wq))
2328 wake_up_interruptible_sync_poll(&wq->wait, POLLOUT | 2328 wake_up_interruptible_sync_poll(&wq->wait, POLLOUT |
2329 POLLWRNORM | POLLWRBAND); 2329 POLLWRNORM | POLLWRBAND);
2330 2330
diff --git a/net/core/stream.c b/net/core/stream.c
index d70f77a0c889..8ff9d63b4265 100644
--- a/net/core/stream.c
+++ b/net/core/stream.c
@@ -35,7 +35,7 @@ void sk_stream_write_space(struct sock *sk)
35 35
36 rcu_read_lock(); 36 rcu_read_lock();
37 wq = rcu_dereference(sk->sk_wq); 37 wq = rcu_dereference(sk->sk_wq);
38 if (wq_has_sleeper(wq)) 38 if (skwq_has_sleeper(wq))
39 wake_up_interruptible_poll(&wq->wait, POLLOUT | 39 wake_up_interruptible_poll(&wq->wait, POLLOUT |
40 POLLWRNORM | POLLWRBAND); 40 POLLWRNORM | POLLWRBAND);
41 if (wq && wq->fasync_list && !(sk->sk_shutdown & SEND_SHUTDOWN)) 41 if (wq && wq->fasync_list && !(sk->sk_shutdown & SEND_SHUTDOWN))
diff --git a/net/dccp/output.c b/net/dccp/output.c
index 4ce912e691d0..b66c84db0766 100644
--- a/net/dccp/output.c
+++ b/net/dccp/output.c
@@ -201,7 +201,7 @@ void dccp_write_space(struct sock *sk)
201 201
202 rcu_read_lock(); 202 rcu_read_lock();
203 wq = rcu_dereference(sk->sk_wq); 203 wq = rcu_dereference(sk->sk_wq);
204 if (wq_has_sleeper(wq)) 204 if (skwq_has_sleeper(wq))
205 wake_up_interruptible(&wq->wait); 205 wake_up_interruptible(&wq->wait);
206 /* Should agree with poll, otherwise some programs break */ 206 /* Should agree with poll, otherwise some programs break */
207 if (sock_writeable(sk)) 207 if (sock_writeable(sk))
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
index fcb2752419c6..4f0aa91470c6 100644
--- a/net/iucv/af_iucv.c
+++ b/net/iucv/af_iucv.c
@@ -303,7 +303,7 @@ static void iucv_sock_wake_msglim(struct sock *sk)
303 303
304 rcu_read_lock(); 304 rcu_read_lock();
305 wq = rcu_dereference(sk->sk_wq); 305 wq = rcu_dereference(sk->sk_wq);
306 if (wq_has_sleeper(wq)) 306 if (skwq_has_sleeper(wq))
307 wake_up_interruptible_all(&wq->wait); 307 wake_up_interruptible_all(&wq->wait);
308 sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); 308 sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT);
309 rcu_read_unlock(); 309 rcu_read_unlock();
diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c
index 1f8a144a5dc2..7e2d1057d8bc 100644
--- a/net/rxrpc/af_rxrpc.c
+++ b/net/rxrpc/af_rxrpc.c
@@ -67,7 +67,7 @@ static void rxrpc_write_space(struct sock *sk)
67 if (rxrpc_writable(sk)) { 67 if (rxrpc_writable(sk)) {
68 struct socket_wq *wq = rcu_dereference(sk->sk_wq); 68 struct socket_wq *wq = rcu_dereference(sk->sk_wq);
69 69
70 if (wq_has_sleeper(wq)) 70 if (skwq_has_sleeper(wq))
71 wake_up_interruptible(&wq->wait); 71 wake_up_interruptible(&wq->wait);
72 sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); 72 sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT);
73 } 73 }
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 897c01c029ca..ec10b66354b8 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -6978,7 +6978,7 @@ void sctp_data_ready(struct sock *sk)
6978 6978
6979 rcu_read_lock(); 6979 rcu_read_lock();
6980 wq = rcu_dereference(sk->sk_wq); 6980 wq = rcu_dereference(sk->sk_wq);
6981 if (wq_has_sleeper(wq)) 6981 if (skwq_has_sleeper(wq))
6982 wake_up_interruptible_sync_poll(&wq->wait, POLLIN | 6982 wake_up_interruptible_sync_poll(&wq->wait, POLLIN |
6983 POLLRDNORM | POLLRDBAND); 6983 POLLRDNORM | POLLRDBAND);
6984 sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN); 6984 sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN);
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 552dbaba9cf3..525acf6dd1c6 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -1492,7 +1492,7 @@ static void tipc_write_space(struct sock *sk)
1492 1492
1493 rcu_read_lock(); 1493 rcu_read_lock();
1494 wq = rcu_dereference(sk->sk_wq); 1494 wq = rcu_dereference(sk->sk_wq);
1495 if (wq_has_sleeper(wq)) 1495 if (skwq_has_sleeper(wq))
1496 wake_up_interruptible_sync_poll(&wq->wait, POLLOUT | 1496 wake_up_interruptible_sync_poll(&wq->wait, POLLOUT |
1497 POLLWRNORM | POLLWRBAND); 1497 POLLWRNORM | POLLWRBAND);
1498 rcu_read_unlock(); 1498 rcu_read_unlock();
@@ -1509,7 +1509,7 @@ static void tipc_data_ready(struct sock *sk)
1509 1509
1510 rcu_read_lock(); 1510 rcu_read_lock();
1511 wq = rcu_dereference(sk->sk_wq); 1511 wq = rcu_dereference(sk->sk_wq);
1512 if (wq_has_sleeper(wq)) 1512 if (skwq_has_sleeper(wq))
1513 wake_up_interruptible_sync_poll(&wq->wait, POLLIN | 1513 wake_up_interruptible_sync_poll(&wq->wait, POLLIN |
1514 POLLRDNORM | POLLRDBAND); 1514 POLLRDNORM | POLLRDBAND);
1515 rcu_read_unlock(); 1515 rcu_read_unlock();
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 955ec152cb71..efb706e1d1c0 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -339,7 +339,7 @@ static void unix_write_space(struct sock *sk)
339 rcu_read_lock(); 339 rcu_read_lock();
340 if (unix_writable(sk)) { 340 if (unix_writable(sk)) {
341 wq = rcu_dereference(sk->sk_wq); 341 wq = rcu_dereference(sk->sk_wq);
342 if (wq_has_sleeper(wq)) 342 if (skwq_has_sleeper(wq))
343 wake_up_interruptible_sync_poll(&wq->wait, 343 wake_up_interruptible_sync_poll(&wq->wait,
344 POLLOUT | POLLWRNORM | POLLWRBAND); 344 POLLOUT | POLLWRNORM | POLLWRBAND);
345 sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); 345 sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT);