diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2015-11-26 00:55:39 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-11-30 14:47:33 -0500 |
commit | 1ce0bf50ae2233c7115a18c0c623662d177b434c (patch) | |
tree | 41860e17fe4b2184055d29e669e503d09796775a | |
parent | c52fd05a2ff2ad20e2a7056baf314c7d1d624ba9 (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.c | 4 | ||||
-rw-r--r-- | crypto/algif_skcipher.c | 4 | ||||
-rw-r--r-- | include/linux/wait.h | 21 | ||||
-rw-r--r-- | include/net/sock.h | 15 | ||||
-rw-r--r-- | net/atm/common.c | 4 | ||||
-rw-r--r-- | net/core/sock.c | 8 | ||||
-rw-r--r-- | net/core/stream.c | 2 | ||||
-rw-r--r-- | net/dccp/output.c | 2 | ||||
-rw-r--r-- | net/iucv/af_iucv.c | 2 | ||||
-rw-r--r-- | net/rxrpc/af_rxrpc.c | 2 | ||||
-rw-r--r-- | net/sctp/socket.c | 2 | ||||
-rw-r--r-- | net/tipc/socket.c | 4 | ||||
-rw-r--r-- | net/unix/af_unix.c | 2 |
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 | */ | ||
118 | static 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 | |||
110 | extern void add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait); | 131 | extern void add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait); |
111 | extern void add_wait_queue_exclusive(wait_queue_head_t *q, wait_queue_t *wait); | 132 | extern void add_wait_queue_exclusive(wait_queue_head_t *q, wait_queue_t *wait); |
112 | extern void remove_wait_queue(wait_queue_head_t *q, wait_queue_t *wait); | 133 | extern 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 | */ |
1913 | static inline bool wq_has_sleeper(struct socket_wq *wq) | 1914 | static 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); |