|
@@ -421,6 +421,9 @@ static void svc_data_ready(struct sock *sk)
|
|
|
dprintk("svc: socket %p(inet %p), busy=%d\n",
|
|
|
svsk, sk,
|
|
|
test_bit(XPT_BUSY, &svsk->sk_xprt.xpt_flags));
|
|
|
+
|
|
|
+ /* Refer to svc_setup_socket() for details. */
|
|
|
+ rmb();
|
|
|
svsk->sk_odata(sk);
|
|
|
if (!test_and_set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags))
|
|
|
svc_xprt_enqueue(&svsk->sk_xprt);
|
|
@@ -437,6 +440,9 @@ static void svc_write_space(struct sock *sk)
|
|
|
if (svsk) {
|
|
|
dprintk("svc: socket %p(inet %p), write_space busy=%d\n",
|
|
|
svsk, sk, test_bit(XPT_BUSY, &svsk->sk_xprt.xpt_flags));
|
|
|
+
|
|
|
+ /* Refer to svc_setup_socket() for details. */
|
|
|
+ rmb();
|
|
|
svsk->sk_owspace(sk);
|
|
|
svc_xprt_enqueue(&svsk->sk_xprt);
|
|
|
}
|
|
@@ -760,8 +766,12 @@ static void svc_tcp_listen_data_ready(struct sock *sk)
|
|
|
dprintk("svc: socket %p TCP (listen) state change %d\n",
|
|
|
sk, sk->sk_state);
|
|
|
|
|
|
- if (svsk)
|
|
|
+ if (svsk) {
|
|
|
+ /* Refer to svc_setup_socket() for details. */
|
|
|
+ rmb();
|
|
|
svsk->sk_odata(sk);
|
|
|
+ }
|
|
|
+
|
|
|
/*
|
|
|
* This callback may called twice when a new connection
|
|
|
* is established as a child socket inherits everything
|
|
@@ -794,6 +804,8 @@ static void svc_tcp_state_change(struct sock *sk)
|
|
|
if (!svsk)
|
|
|
printk("svc: socket %p: no user data\n", sk);
|
|
|
else {
|
|
|
+ /* Refer to svc_setup_socket() for details. */
|
|
|
+ rmb();
|
|
|
svsk->sk_ostate(sk);
|
|
|
if (sk->sk_state != TCP_ESTABLISHED) {
|
|
|
set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags);
|
|
@@ -1381,12 +1393,18 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv,
|
|
|
return ERR_PTR(err);
|
|
|
}
|
|
|
|
|
|
- inet->sk_user_data = svsk;
|
|
|
svsk->sk_sock = sock;
|
|
|
svsk->sk_sk = inet;
|
|
|
svsk->sk_ostate = inet->sk_state_change;
|
|
|
svsk->sk_odata = inet->sk_data_ready;
|
|
|
svsk->sk_owspace = inet->sk_write_space;
|
|
|
+ /*
|
|
|
+ * This barrier is necessary in order to prevent race condition
|
|
|
+ * with svc_data_ready(), svc_listen_data_ready() and others
|
|
|
+ * when calling callbacks above.
|
|
|
+ */
|
|
|
+ wmb();
|
|
|
+ inet->sk_user_data = svsk;
|
|
|
|
|
|
/* Initialize the socket */
|
|
|
if (sock->type == SOCK_DGRAM)
|