diff options
-rw-r--r-- | net/sunrpc/svcsock.c | 22 |
1 files changed, 20 insertions, 2 deletions
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 2b720fa35c4f..e18500151236 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
@@ -421,6 +421,9 @@ static void svc_data_ready(struct sock *sk) | |||
421 | dprintk("svc: socket %p(inet %p), busy=%d\n", | 421 | dprintk("svc: socket %p(inet %p), busy=%d\n", |
422 | svsk, sk, | 422 | svsk, sk, |
423 | test_bit(XPT_BUSY, &svsk->sk_xprt.xpt_flags)); | 423 | test_bit(XPT_BUSY, &svsk->sk_xprt.xpt_flags)); |
424 | |||
425 | /* Refer to svc_setup_socket() for details. */ | ||
426 | rmb(); | ||
424 | svsk->sk_odata(sk); | 427 | svsk->sk_odata(sk); |
425 | if (!test_and_set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags)) | 428 | if (!test_and_set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags)) |
426 | svc_xprt_enqueue(&svsk->sk_xprt); | 429 | svc_xprt_enqueue(&svsk->sk_xprt); |
@@ -437,6 +440,9 @@ static void svc_write_space(struct sock *sk) | |||
437 | if (svsk) { | 440 | if (svsk) { |
438 | dprintk("svc: socket %p(inet %p), write_space busy=%d\n", | 441 | dprintk("svc: socket %p(inet %p), write_space busy=%d\n", |
439 | svsk, sk, test_bit(XPT_BUSY, &svsk->sk_xprt.xpt_flags)); | 442 | svsk, sk, test_bit(XPT_BUSY, &svsk->sk_xprt.xpt_flags)); |
443 | |||
444 | /* Refer to svc_setup_socket() for details. */ | ||
445 | rmb(); | ||
440 | svsk->sk_owspace(sk); | 446 | svsk->sk_owspace(sk); |
441 | svc_xprt_enqueue(&svsk->sk_xprt); | 447 | svc_xprt_enqueue(&svsk->sk_xprt); |
442 | } | 448 | } |
@@ -760,8 +766,12 @@ static void svc_tcp_listen_data_ready(struct sock *sk) | |||
760 | dprintk("svc: socket %p TCP (listen) state change %d\n", | 766 | dprintk("svc: socket %p TCP (listen) state change %d\n", |
761 | sk, sk->sk_state); | 767 | sk, sk->sk_state); |
762 | 768 | ||
763 | if (svsk) | 769 | if (svsk) { |
770 | /* Refer to svc_setup_socket() for details. */ | ||
771 | rmb(); | ||
764 | svsk->sk_odata(sk); | 772 | svsk->sk_odata(sk); |
773 | } | ||
774 | |||
765 | /* | 775 | /* |
766 | * This callback may called twice when a new connection | 776 | * This callback may called twice when a new connection |
767 | * is established as a child socket inherits everything | 777 | * is established as a child socket inherits everything |
@@ -794,6 +804,8 @@ static void svc_tcp_state_change(struct sock *sk) | |||
794 | if (!svsk) | 804 | if (!svsk) |
795 | printk("svc: socket %p: no user data\n", sk); | 805 | printk("svc: socket %p: no user data\n", sk); |
796 | else { | 806 | else { |
807 | /* Refer to svc_setup_socket() for details. */ | ||
808 | rmb(); | ||
797 | svsk->sk_ostate(sk); | 809 | svsk->sk_ostate(sk); |
798 | if (sk->sk_state != TCP_ESTABLISHED) { | 810 | if (sk->sk_state != TCP_ESTABLISHED) { |
799 | set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); | 811 | set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); |
@@ -1381,12 +1393,18 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv, | |||
1381 | return ERR_PTR(err); | 1393 | return ERR_PTR(err); |
1382 | } | 1394 | } |
1383 | 1395 | ||
1384 | inet->sk_user_data = svsk; | ||
1385 | svsk->sk_sock = sock; | 1396 | svsk->sk_sock = sock; |
1386 | svsk->sk_sk = inet; | 1397 | svsk->sk_sk = inet; |
1387 | svsk->sk_ostate = inet->sk_state_change; | 1398 | svsk->sk_ostate = inet->sk_state_change; |
1388 | svsk->sk_odata = inet->sk_data_ready; | 1399 | svsk->sk_odata = inet->sk_data_ready; |
1389 | svsk->sk_owspace = inet->sk_write_space; | 1400 | svsk->sk_owspace = inet->sk_write_space; |
1401 | /* | ||
1402 | * This barrier is necessary in order to prevent race condition | ||
1403 | * with svc_data_ready(), svc_listen_data_ready() and others | ||
1404 | * when calling callbacks above. | ||
1405 | */ | ||
1406 | wmb(); | ||
1407 | inet->sk_user_data = svsk; | ||
1390 | 1408 | ||
1391 | /* Initialize the socket */ | 1409 | /* Initialize the socket */ |
1392 | if (sock->type == SOCK_DGRAM) | 1410 | if (sock->type == SOCK_DGRAM) |