Skip to content

Commit

Permalink
svcrpc: document lack of some memory barriers
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: J. Bruce Fields <[email protected]>
  • Loading branch information
J. Bruce Fields committed Nov 10, 2015
1 parent 7fc0564 commit 0442f14
Showing 1 changed file with 31 additions and 6 deletions.
37 changes: 31 additions & 6 deletions net/sunrpc/svcsock.c
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,31 @@ static int svc_sock_secure_port(struct svc_rqst *rqstp)
return svc_port_is_privileged(svc_addr(rqstp));
}

static bool sunrpc_waitqueue_active(wait_queue_head_t *wq)
{
if (!wq)
return false;
/*
* There should normally be a memory * barrier here--see
* wq_has_sleeper().
*
* It appears that isn't currently necessary, though, basically
* because callers all appear to have sufficient memory barriers
* between the time the relevant change is made and the
* time they call these callbacks.
*
* The nfsd code itself doesn't actually explicitly wait on
* these waitqueues, but it may wait on them for example in
* sendpage() or sendmsg() calls. (And those may be the only
* places, since it it uses nonblocking reads.)
*
* Maybe we should add the memory barriers anyway, but these are
* hot paths so we'd need to be convinced there's no sigificant
* penalty.
*/
return waitqueue_active(wq);
}

/*
* INET callback when data has been received on the socket.
*/
Expand All @@ -414,7 +439,7 @@ static void svc_udp_data_ready(struct sock *sk)
set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
svc_xprt_enqueue(&svsk->sk_xprt);
}
if (wq && waitqueue_active(wq))
if (sunrpc_waitqueue_active(wq))
wake_up_interruptible(wq);
}

Expand All @@ -432,7 +457,7 @@ static void svc_write_space(struct sock *sk)
svc_xprt_enqueue(&svsk->sk_xprt);
}

if (wq && waitqueue_active(wq)) {
if (sunrpc_waitqueue_active(wq)) {
dprintk("RPC svc_write_space: someone sleeping on %p\n",
svsk);
wake_up_interruptible(wq);
Expand Down Expand Up @@ -787,7 +812,7 @@ static void svc_tcp_listen_data_ready(struct sock *sk)
}

wq = sk_sleep(sk);
if (wq && waitqueue_active(wq))
if (sunrpc_waitqueue_active(wq))
wake_up_interruptible_all(wq);
}

Expand All @@ -808,7 +833,7 @@ static void svc_tcp_state_change(struct sock *sk)
set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags);
svc_xprt_enqueue(&svsk->sk_xprt);
}
if (wq && waitqueue_active(wq))
if (sunrpc_waitqueue_active(wq))
wake_up_interruptible_all(wq);
}

Expand All @@ -823,7 +848,7 @@ static void svc_tcp_data_ready(struct sock *sk)
set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
svc_xprt_enqueue(&svsk->sk_xprt);
}
if (wq && waitqueue_active(wq))
if (sunrpc_waitqueue_active(wq))
wake_up_interruptible(wq);
}

Expand Down Expand Up @@ -1593,7 +1618,7 @@ static void svc_sock_detach(struct svc_xprt *xprt)
sk->sk_write_space = svsk->sk_owspace;

wq = sk_sleep(sk);
if (wq && waitqueue_active(wq))
if (sunrpc_waitqueue_active(wq))
wake_up_interruptible(wq);
}

Expand Down

0 comments on commit 0442f14

Please sign in to comment.