Merge tag 'nfs-for-4.14-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 12 Sep 2017 05:01:44 +0000 (22:01 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 12 Sep 2017 05:01:44 +0000 (22:01 -0700)
Pull NFS client updates from Trond Myklebust:
 "Hightlights include:

  Stable bugfixes:
   - Fix mirror allocation in the writeback code to avoid a use after
     free
   - Fix the O_DSYNC writes to use the correct byte range
   - Fix 2 use after free issues in the I/O code

  Features:
   - Writeback fixes to split up the inode->i_lock in order to reduce
     contention
   - RPC client receive fixes to reduce the amount of time the
     xprt->transport_lock is held when receiving data from a socket into
     am XDR buffer.
   - Ditto fixes to reduce contention between call side users of the
     rdma rb_lock, and its use in rpcrdma_reply_handler.
   - Re-arrange rdma stats to reduce false cacheline sharing.
   - Various rdma cleanups and optimisations.
   - Refactor the NFSv4.1 exchange id code and clean up the code.
   - Const-ify all instances of struct rpc_xprt_ops

  Bugfixes:
   - Fix the NFSv2 'sec=' mount option.
   - NFSv4.1: don't use machine credentials for CLOSE when using
     'sec=sys'
   - Fix the NFSv3 GRANT callback when the port changes on the server.
   - Fix livelock issues with COMMIT
   - NFSv4: Use correct inode in _nfs4_opendata_to_nfs4_state() when
     doing and NFSv4.1 open by filehandle"

* tag 'nfs-for-4.14-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (69 commits)
  NFS: Count the bytes of skipped subrequests in nfs_lock_and_join_requests()
  NFS: Don't hold the group lock when calling nfs_release_request()
  NFS: Remove pnfs_generic_transfer_commit_list()
  NFS: nfs_lock_and_join_requests and nfs_scan_commit_list can deadlock
  NFS: Fix 2 use after free issues in the I/O code
  NFS: Sync the correct byte range during synchronous writes
  lockd: Delete an error message for a failed memory allocation in reclaimer()
  NFS: remove jiffies field from access cache
  NFS: flush data when locking a file to ensure cache coherence for mmap.
  SUNRPC: remove some dead code.
  NFS: don't expect errors from mempool_alloc().
  xprtrdma: Use xprt_pin_rqst in rpcrdma_reply_handler
  xprtrdma: Re-arrange struct rx_stats
  NFS: Fix NFSv2 security settings
  NFSv4.1: don't use machine credentials for CLOSE when using 'sec=sys'
  SUNRPC: ECONNREFUSED should cause a rebind.
  NFS: Remove unused parameter gfp_flags from nfs_pageio_init()
  NFSv4: Fix up mirror allocation
  SUNRPC: Add a separate spinlock to protect the RPC request receive list
  SUNRPC: Cleanup xs_tcp_read_common()
  ...

1  2 
net/sunrpc/svcsock.c

diff --combined net/sunrpc/svcsock.c
index 399fab5d19365e59a0c4526edab2c4ccb42545df,272063ca81e88310beec3b59c8feb0f115e067c8..ff8e06cd067e975eb87b55a5ff2485fd90299a0a
@@@ -421,9 -421,6 +421,9 @@@ static void svc_data_ready(struct sock 
                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);
@@@ -440,9 -437,6 +440,9 @@@ static void svc_write_space(struct soc
        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);
        }
@@@ -693,7 -687,7 +693,7 @@@ static struct svc_xprt *svc_udp_create(
        return svc_create_socket(serv, IPPROTO_UDP, net, sa, salen, flags);
  }
  
 -static struct svc_xprt_ops svc_udp_ops = {
 +static const struct svc_xprt_ops svc_udp_ops = {
        .xpo_create = svc_udp_create,
        .xpo_recvfrom = svc_udp_recvfrom,
        .xpo_sendto = svc_udp_sendto,
@@@ -766,12 -760,8 +766,12 @@@ static void svc_tcp_listen_data_ready(s
        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
@@@ -804,8 -794,6 +804,8 @@@ static void svc_tcp_state_change(struc
        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);
@@@ -1013,7 -1001,7 +1013,7 @@@ static int receive_cb_reply(struct svc_
  
        if (!bc_xprt)
                return -EAGAIN;
-       spin_lock_bh(&bc_xprt->transport_lock);
+       spin_lock(&bc_xprt->recv_lock);
        req = xprt_lookup_rqst(bc_xprt, xid);
        if (!req)
                goto unlock_notfound;
        memcpy(dst->iov_base, src->iov_base, src->iov_len);
        xprt_complete_rqst(req->rq_task, rqstp->rq_arg.len);
        rqstp->rq_arg.len = 0;
-       spin_unlock_bh(&bc_xprt->transport_lock);
+       spin_unlock(&bc_xprt->recv_lock);
        return 0;
  unlock_notfound:
        printk(KERN_NOTICE
                __func__, ntohl(calldir),
                bc_xprt, ntohl(xid));
  unlock_eagain:
-       spin_unlock_bh(&bc_xprt->transport_lock);
+       spin_unlock(&bc_xprt->recv_lock);
        return -EAGAIN;
  }
  
@@@ -1241,7 -1229,7 +1241,7 @@@ static void svc_bc_tcp_sock_detach(stru
  {
  }
  
 -static struct svc_xprt_ops svc_tcp_bc_ops = {
 +static const struct svc_xprt_ops svc_tcp_bc_ops = {
        .xpo_create = svc_bc_tcp_create,
        .xpo_detach = svc_bc_tcp_sock_detach,
        .xpo_free = svc_bc_sock_free,
@@@ -1275,7 -1263,7 +1275,7 @@@ static void svc_cleanup_bc_xprt_sock(vo
  }
  #endif /* CONFIG_SUNRPC_BACKCHANNEL */
  
 -static struct svc_xprt_ops svc_tcp_ops = {
 +static const struct svc_xprt_ops svc_tcp_ops = {
        .xpo_create = svc_tcp_create,
        .xpo_recvfrom = svc_tcp_recvfrom,
        .xpo_sendto = svc_tcp_sendto,
@@@ -1393,18 -1381,12 +1393,18 @@@ static struct svc_sock *svc_setup_socke
                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)