diff options
author | J. Bruce Fields <bfields@redhat.com> | 2015-10-08 21:44:07 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2015-11-10 17:02:47 -0500 |
commit | 0442f14b15f8e7a8b3778a9f8cf640ef89b2df26 (patch) | |
tree | dd7cae613d5d154bd945b9c140d4764074bbbe08 | |
parent | 7fc0564e3a8d16df096f48c9c6425ba84d945c6e (diff) |
svcrpc: document lack of some memory barriers
We're missing memory barriers in net/sunrpc/svcsock.c in some spots we'd
expect them. But it doesn't appear they're necessary in our case, and
this is likely a hot path--for now just document the odd behavior.
Kosuke Tatsukawa found this issue while looking through the linux source
code for places calling waitqueue_active() before wake_up*(), but
without preceding memory barriers, after sending a patch to fix a
similar issue in drivers/tty/n_tty.c (Details about the original issue
can be found here: https://lkml.org/lkml/2015/9/28/849).
Reported-by: Kosuke Tatsukawa <tatsu@ab.jp.nec.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
-rw-r--r-- | net/sunrpc/svcsock.c | 37 |
1 files changed, 31 insertions, 6 deletions
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index e0c7b3355495..1413cdcc131c 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
@@ -399,6 +399,31 @@ static int svc_sock_secure_port(struct svc_rqst *rqstp) | |||
399 | return svc_port_is_privileged(svc_addr(rqstp)); | 399 | return svc_port_is_privileged(svc_addr(rqstp)); |
400 | } | 400 | } |
401 | 401 | ||
402 | static bool sunrpc_waitqueue_active(wait_queue_head_t *wq) | ||
403 | { | ||
404 | if (!wq) | ||
405 | return false; | ||
406 | /* | ||
407 | * There should normally be a memory * barrier here--see | ||
408 | * wq_has_sleeper(). | ||
409 | * | ||
410 | * It appears that isn't currently necessary, though, basically | ||
411 | * because callers all appear to have sufficient memory barriers | ||
412 | * between the time the relevant change is made and the | ||
413 | * time they call these callbacks. | ||
414 | * | ||
415 | * The nfsd code itself doesn't actually explicitly wait on | ||
416 | * these waitqueues, but it may wait on them for example in | ||
417 | * sendpage() or sendmsg() calls. (And those may be the only | ||
418 | * places, since it it uses nonblocking reads.) | ||
419 | * | ||
420 | * Maybe we should add the memory barriers anyway, but these are | ||
421 | * hot paths so we'd need to be convinced there's no sigificant | ||
422 | * penalty. | ||
423 | */ | ||
424 | return waitqueue_active(wq); | ||
425 | } | ||
426 | |||
402 | /* | 427 | /* |
403 | * INET callback when data has been received on the socket. | 428 | * INET callback when data has been received on the socket. |
404 | */ | 429 | */ |
@@ -414,7 +439,7 @@ static void svc_udp_data_ready(struct sock *sk) | |||
414 | set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); | 439 | set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); |
415 | svc_xprt_enqueue(&svsk->sk_xprt); | 440 | svc_xprt_enqueue(&svsk->sk_xprt); |
416 | } | 441 | } |
417 | if (wq && waitqueue_active(wq)) | 442 | if (sunrpc_waitqueue_active(wq)) |
418 | wake_up_interruptible(wq); | 443 | wake_up_interruptible(wq); |
419 | } | 444 | } |
420 | 445 | ||
@@ -432,7 +457,7 @@ static void svc_write_space(struct sock *sk) | |||
432 | svc_xprt_enqueue(&svsk->sk_xprt); | 457 | svc_xprt_enqueue(&svsk->sk_xprt); |
433 | } | 458 | } |
434 | 459 | ||
435 | if (wq && waitqueue_active(wq)) { | 460 | if (sunrpc_waitqueue_active(wq)) { |
436 | dprintk("RPC svc_write_space: someone sleeping on %p\n", | 461 | dprintk("RPC svc_write_space: someone sleeping on %p\n", |
437 | svsk); | 462 | svsk); |
438 | wake_up_interruptible(wq); | 463 | wake_up_interruptible(wq); |
@@ -787,7 +812,7 @@ static void svc_tcp_listen_data_ready(struct sock *sk) | |||
787 | } | 812 | } |
788 | 813 | ||
789 | wq = sk_sleep(sk); | 814 | wq = sk_sleep(sk); |
790 | if (wq && waitqueue_active(wq)) | 815 | if (sunrpc_waitqueue_active(wq)) |
791 | wake_up_interruptible_all(wq); | 816 | wake_up_interruptible_all(wq); |
792 | } | 817 | } |
793 | 818 | ||
@@ -808,7 +833,7 @@ static void svc_tcp_state_change(struct sock *sk) | |||
808 | set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); | 833 | set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); |
809 | svc_xprt_enqueue(&svsk->sk_xprt); | 834 | svc_xprt_enqueue(&svsk->sk_xprt); |
810 | } | 835 | } |
811 | if (wq && waitqueue_active(wq)) | 836 | if (sunrpc_waitqueue_active(wq)) |
812 | wake_up_interruptible_all(wq); | 837 | wake_up_interruptible_all(wq); |
813 | } | 838 | } |
814 | 839 | ||
@@ -823,7 +848,7 @@ static void svc_tcp_data_ready(struct sock *sk) | |||
823 | set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); | 848 | set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); |
824 | svc_xprt_enqueue(&svsk->sk_xprt); | 849 | svc_xprt_enqueue(&svsk->sk_xprt); |
825 | } | 850 | } |
826 | if (wq && waitqueue_active(wq)) | 851 | if (sunrpc_waitqueue_active(wq)) |
827 | wake_up_interruptible(wq); | 852 | wake_up_interruptible(wq); |
828 | } | 853 | } |
829 | 854 | ||
@@ -1593,7 +1618,7 @@ static void svc_sock_detach(struct svc_xprt *xprt) | |||
1593 | sk->sk_write_space = svsk->sk_owspace; | 1618 | sk->sk_write_space = svsk->sk_owspace; |
1594 | 1619 | ||
1595 | wq = sk_sleep(sk); | 1620 | wq = sk_sleep(sk); |
1596 | if (wq && waitqueue_active(wq)) | 1621 | if (sunrpc_waitqueue_active(wq)) |
1597 | wake_up_interruptible(wq); | 1622 | wake_up_interruptible(wq); |
1598 | } | 1623 | } |
1599 | 1624 | ||