]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/commitdiff
merge nfsd 4.13 bugfixes into nfsd for-4.14 branch
authorJ. Bruce Fields <bfields@redhat.com>
Tue, 5 Sep 2017 19:11:47 +0000 (15:11 -0400)
committerJ. Bruce Fields <bfields@redhat.com>
Tue, 5 Sep 2017 19:11:47 +0000 (15:11 -0400)
fs/nfsd/nfs4xdr.c
net/sunrpc/svcsock.c

index 0c3b935d100f7356c1c21881ef016eabf1b5a774..08691fe394b2d89a8477853e47ae0cd5025ac35f 100644 (file)
@@ -144,7 +144,7 @@ static void next_decode_page(struct nfsd4_compoundargs *argp)
        argp->p = page_address(argp->pagelist[0]);
        argp->pagelist++;
        if (argp->pagelen < PAGE_SIZE) {
-               argp->end = argp->p + (argp->pagelen>>2);
+               argp->end = argp->p + XDR_QUADLEN(argp->pagelen);
                argp->pagelen = 0;
        } else {
                argp->end = argp->p + (PAGE_SIZE>>2);
@@ -1279,9 +1279,7 @@ nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write)
                argp->pagelen -= pages * PAGE_SIZE;
                len -= pages * PAGE_SIZE;
 
-               argp->p = (__be32 *)page_address(argp->pagelist[0]);
-               argp->pagelist++;
-               argp->end = argp->p + XDR_QUADLEN(PAGE_SIZE);
+               next_decode_page(argp);
        }
        argp->p += XDR_QUADLEN(len);
 
index b434f524d6771738da9dd5279957be6c872c5f30..399fab5d19365e59a0c4526edab2c4ccb42545df 100644 (file)
@@ -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)