Merge tag 'nfsd-4.20' of git://linux-nfs.org/~bfields/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 30 Oct 2018 20:03:29 +0000 (13:03 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 30 Oct 2018 20:03:29 +0000 (13:03 -0700)
Pull nfsd updates from Bruce Fields:
 "Olga added support for the NFSv4.2 asynchronous copy protocol. We
  already supported COPY, by copying a limited amount of data and then
  returning a short result, letting the client resend. The asynchronous
  protocol should offer better performance at the expense of some
  complexity.

  The other highlight is Trond's work to convert the duplicate reply
  cache to a red-black tree, and to move it and some other server caches
  to RCU. (Previously these have meant taking global spinlocks on every
  RPC)

  Otherwise, some RDMA work and miscellaneous bugfixes"

* tag 'nfsd-4.20' of git://linux-nfs.org/~bfields/linux: (30 commits)
  lockd: fix access beyond unterminated strings in prints
  nfsd: Fix an Oops in free_session()
  nfsd: correctly decrement odstate refcount in error path
  svcrdma: Increase the default connection credit limit
  svcrdma: Remove try_module_get from backchannel
  svcrdma: Remove ->release_rqst call in bc reply handler
  svcrdma: Reduce max_send_sges
  nfsd: fix fall-through annotations
  knfsd: Improve lookup performance in the duplicate reply cache using an rbtree
  knfsd: Further simplify the cache lookup
  knfsd: Simplify NFS duplicate replay cache
  knfsd: Remove dead code from nfsd_cache_lookup
  SUNRPC: Simplify TCP receive code
  SUNRPC: Replace the cache_detail->hash_lock with a regular spinlock
  SUNRPC: Remove non-RCU protected lookup
  NFS: Fix up a typo in nfs_dns_ent_put
  NFS: Lockless DNS lookups
  knfsd: Lockless lookup of NFSv4 identities.
  SUNRPC: Lockless server RPCSEC_GSS context lookup
  knfsd: Allow lockless lookups of the exports
  ...

1  2 
fs/nfsd/vfs.c
net/sunrpc/svc_xprt.c
net/sunrpc/svcsock.c
net/sunrpc/xprtrdma/svc_rdma_backchannel.c

diff --combined fs/nfsd/vfs.c
@@@ -541,8 -541,7 +541,8 @@@ __be32 nfsd4_set_nfs4_label(struct svc_
  __be32 nfsd4_clone_file_range(struct file *src, u64 src_pos, struct file *dst,
                u64 dst_pos, u64 count)
  {
 -      return nfserrno(do_clone_file_range(src, src_pos, dst, dst_pos, count));
 +      return nfserrno(vfs_clone_file_range(src, src_pos, dst, dst_pos,
 +                                           count));
  }
  
  ssize_t nfsd_copy_file_range(struct file *src, u64 src_pos, struct file *dst,
@@@ -1276,7 -1275,6 +1276,6 @@@ nfsd_create(struct svc_rqst *rqstp, str
                int type, dev_t rdev, struct svc_fh *resfhp)
  {
        struct dentry   *dentry, *dchild = NULL;
-       struct inode    *dirp;
        __be32          err;
        int             host_err;
  
                return err;
  
        dentry = fhp->fh_dentry;
-       dirp = d_inode(dentry);
  
        host_err = fh_want_write(fhp);
        if (host_err)
@@@ -1409,6 -1406,7 +1407,7 @@@ do_nfsd_create(struct svc_rqst *rqstp, 
                                        *created = 1;
                                break;
                        }
+                       /* fall through */
                case NFS4_CREATE_EXCLUSIVE4_1:
                        if (   d_inode(dchild)->i_mtime.tv_sec == v_mtime
                            && d_inode(dchild)->i_atime.tv_sec == v_atime
                                        *created = 1;
                                goto set_attr;
                        }
-                        /* fallthru */
+                       /* fall through */
                case NFS3_CREATE_GUARDED:
                        err = nfserr_exist;
                }
diff --combined net/sunrpc/svc_xprt.c
@@@ -171,6 -171,7 +171,6 @@@ void svc_xprt_init(struct net *net, str
        mutex_init(&xprt->xpt_mutex);
        spin_lock_init(&xprt->xpt_lock);
        set_bit(XPT_BUSY, &xprt->xpt_flags);
 -      rpc_init_wait_queue(&xprt->xpt_bc_pending, "xpt_bc_pending");
        xprt->xpt_net = get_net(net);
        strcpy(xprt->xpt_remotebuf, "uninitialized");
  }
@@@ -894,6 -895,7 +894,6 @@@ int svc_send(struct svc_rqst *rqstp
        else
                len = xprt->xpt_ops->xpo_sendto(rqstp);
        mutex_unlock(&xprt->xpt_mutex);
 -      rpc_wake_up(&xprt->xpt_bc_pending);
        trace_svc_send(rqstp, len);
        svc_xprt_release(rqstp);
  
@@@ -987,7 -989,7 +987,7 @@@ static void call_xpt_users(struct svc_x
        spin_lock(&xprt->xpt_lock);
        while (!list_empty(&xprt->xpt_users)) {
                u = list_first_entry(&xprt->xpt_users, struct svc_xpt_user, list);
-               list_del(&u->list);
+               list_del_init(&u->list);
                u->callback(u);
        }
        spin_unlock(&xprt->xpt_lock);
diff --combined net/sunrpc/svcsock.c
@@@ -325,59 -325,34 +325,34 @@@ static int svc_one_sock_name(struct svc
  /*
   * Generic recvfrom routine.
   */
- static int svc_recvfrom(struct svc_rqst *rqstp, struct kvec *iov, int nr,
-                       int buflen)
+ static ssize_t svc_recvfrom(struct svc_rqst *rqstp, struct kvec *iov,
+                           unsigned int nr, size_t buflen, unsigned int base)
  {
        struct svc_sock *svsk =
                container_of(rqstp->rq_xprt, struct svc_sock, sk_xprt);
-       struct msghdr msg = {
-               .msg_flags      = MSG_DONTWAIT,
-       };
-       int len;
+       struct msghdr msg = { NULL };
+       ssize_t len;
  
        rqstp->rq_xprt_hlen = 0;
  
        clear_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
        iov_iter_kvec(&msg.msg_iter, READ | ITER_KVEC, iov, nr, buflen);
-       len = sock_recvmsg(svsk->sk_sock, &msg, msg.msg_flags);
+       if (base != 0) {
+               iov_iter_advance(&msg.msg_iter, base);
+               buflen -= base;
+       }
+       len = sock_recvmsg(svsk->sk_sock, &msg, MSG_DONTWAIT);
        /* If we read a full record, then assume there may be more
         * data to read (stream based sockets only!)
         */
        if (len == buflen)
                set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
  
-       dprintk("svc: socket %p recvfrom(%p, %zu) = %d\n",
+       dprintk("svc: socket %p recvfrom(%p, %zu) = %zd\n",
                svsk, iov[0].iov_base, iov[0].iov_len, len);
        return len;
  }
  
- static int svc_partial_recvfrom(struct svc_rqst *rqstp,
-                               struct kvec *iov, int nr,
-                               int buflen, unsigned int base)
- {
-       size_t save_iovlen;
-       void *save_iovbase;
-       unsigned int i;
-       int ret;
-       if (base == 0)
-               return svc_recvfrom(rqstp, iov, nr, buflen);
-       for (i = 0; i < nr; i++) {
-               if (iov[i].iov_len > base)
-                       break;
-               base -= iov[i].iov_len;
-       }
-       save_iovlen = iov[i].iov_len;
-       save_iovbase = iov[i].iov_base;
-       iov[i].iov_len -= base;
-       iov[i].iov_base += base;
-       ret = svc_recvfrom(rqstp, &iov[i], nr - i, buflen);
-       iov[i].iov_len = save_iovlen;
-       iov[i].iov_base = save_iovbase;
-       return ret;
- }
  /*
   * Set socket snd and rcv buffer lengths
   */
@@@ -962,7 -937,8 +937,8 @@@ static int svc_tcp_recv_record(struct s
                want = sizeof(rpc_fraghdr) - svsk->sk_tcplen;
                iov.iov_base = ((char *) &svsk->sk_reclen) + svsk->sk_tcplen;
                iov.iov_len  = want;
-               if ((len = svc_recvfrom(rqstp, &iov, 1, want)) < 0)
+               len = svc_recvfrom(rqstp, &iov, 1, want, 0);
+               if (len < 0)
                        goto error;
                svsk->sk_tcplen += len;
  
@@@ -1004,7 -980,7 +980,7 @@@ static int receive_cb_reply(struct svc_
  
        if (!bc_xprt)
                return -EAGAIN;
 -      spin_lock(&bc_xprt->recv_lock);
 +      spin_lock(&bc_xprt->queue_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(&bc_xprt->recv_lock);
 +      spin_unlock(&bc_xprt->queue_lock);
        return 0;
  unlock_notfound:
        printk(KERN_NOTICE
                __func__, ntohl(calldir),
                bc_xprt, ntohl(xid));
  unlock_eagain:
 -      spin_unlock(&bc_xprt->recv_lock);
 +      spin_unlock(&bc_xprt->queue_lock);
        return -EAGAIN;
  }
  
@@@ -1088,14 -1064,13 +1064,13 @@@ static int svc_tcp_recvfrom(struct svc_
  
        vec = rqstp->rq_vec;
  
-       pnum = copy_pages_to_kvecs(&vec[0], &rqstp->rq_pages[0],
-                                               svsk->sk_datalen + want);
+       pnum = copy_pages_to_kvecs(&vec[0], &rqstp->rq_pages[0], base + want);
  
        rqstp->rq_respages = &rqstp->rq_pages[pnum];
        rqstp->rq_next_page = rqstp->rq_respages + 1;
  
        /* Now receive data */
-       len = svc_partial_recvfrom(rqstp, vec, pnum, want, base);
+       len = svc_recvfrom(rqstp, vec, pnum, base + want, base);
        if (len >= 0) {
                svsk->sk_tcplen += len;
                svsk->sk_datalen += len;
@@@ -5,8 -5,6 +5,6 @@@
   * Support for backward direction RPCs on RPC/RDMA (server-side).
   */
  
- #include <linux/module.h>
  #include <linux/sunrpc/svc_rdma.h>
  
  #include "xprt_rdma.h"
@@@ -32,7 -30,6 +30,6 @@@ int svc_rdma_handle_bc_reply(struct rpc
        struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt);
        struct kvec *dst, *src = &rcvbuf->head[0];
        struct rpc_rqst *req;
-       unsigned long cwnd;
        u32 credits;
        size_t len;
        __be32 xid;
@@@ -56,7 -53,7 +53,7 @@@
        if (src->iov_len < 24)
                goto out_shortreply;
  
 -      spin_lock(&xprt->recv_lock);
 +      spin_lock(&xprt->queue_lock);
        req = xprt_lookup_rqst(xprt, xid);
        if (!req)
                goto out_notfound;
@@@ -66,6 -63,8 +63,8 @@@
        if (dst->iov_len < len)
                goto out_unlock;
        memcpy(dst->iov_base, p, len);
 -      spin_unlock(&xprt->recv_lock);
+       xprt_pin_rqst(req);
++      spin_unlock(&xprt->queue_lock);
  
        credits = be32_to_cpup(rdma_resp + 2);
        if (credits == 0)
                credits = r_xprt->rx_buf.rb_bc_max_requests;
  
        spin_lock_bh(&xprt->transport_lock);
-       cwnd = xprt->cwnd;
        xprt->cwnd = credits << RPC_CWNDSHIFT;
-       if (xprt->cwnd > cwnd)
-               xprt_release_rqst_cong(req->rq_task);
        spin_unlock_bh(&xprt->transport_lock);
  
 -      spin_lock(&xprt->recv_lock);
++      spin_lock(&xprt->queue_lock);
        ret = 0;
        xprt_complete_rqst(req->rq_task, rcvbuf->len);
+       xprt_unpin_rqst(req);
        rcvbuf->len = 0;
  
  out_unlock:
 -      spin_unlock(&xprt->recv_lock);
 +      spin_unlock(&xprt->queue_lock);
  out:
        return ret;
  
@@@ -215,8 -212,9 +212,8 @@@ drop_connection
   * connection.
   */
  static int
 -xprt_rdma_bc_send_request(struct rpc_task *task)
 +xprt_rdma_bc_send_request(struct rpc_rqst *rqst)
  {
 -      struct rpc_rqst *rqst = task->tk_rqstp;
        struct svc_xprt *sxprt = rqst->rq_xprt->bc_xprt;
        struct svcxprt_rdma *rdma;
        int ret;
        dprintk("svcrdma: sending bc call with xid: %08x\n",
                be32_to_cpu(rqst->rq_xid));
  
 -      if (!mutex_trylock(&sxprt->xpt_mutex)) {
 -              rpc_sleep_on(&sxprt->xpt_bc_pending, task, NULL);
 -              if (!mutex_trylock(&sxprt->xpt_mutex))
 -                      return -EAGAIN;
 -              rpc_wake_up_queued_task(&sxprt->xpt_bc_pending, task);
 -      }
 +      mutex_lock(&sxprt->xpt_mutex);
  
        ret = -ENOTCONN;
        rdma = container_of(sxprt, struct svcxprt_rdma, sc_xprt);
@@@ -242,7 -245,6 +239,7 @@@ static voi
  xprt_rdma_bc_close(struct rpc_xprt *xprt)
  {
        dprintk("svcrdma: %s: xprt %p\n", __func__, xprt);
 +      xprt->cwnd = RPC_CWNDSHIFT;
  }
  
  static void
@@@ -251,7 -253,6 +248,6 @@@ xprt_rdma_bc_put(struct rpc_xprt *xprt
        dprintk("svcrdma: %s: xprt %p\n", __func__, xprt);
  
        xprt_free(xprt);
-       module_put(THIS_MODULE);
  }
  
  static const struct rpc_xprt_ops xprt_rdma_bc_procs = {
@@@ -323,20 -324,9 +319,9 @@@ xprt_setup_rdma_bc(struct xprt_create *
        args->bc_xprt->xpt_bc_xprt = xprt;
        xprt->bc_xprt = args->bc_xprt;
  
-       if (!try_module_get(THIS_MODULE))
-               goto out_fail;
        /* Final put for backchannel xprt is in __svc_rdma_free */
        xprt_get(xprt);
        return xprt;
- out_fail:
-       xprt_rdma_free_addresses(xprt);
-       args->bc_xprt->xpt_bc_xprt = NULL;
-       args->bc_xprt->xpt_bc_xps = NULL;
-       xprt_put(xprt);
-       xprt_free(xprt);
-       return ERR_PTR(-EINVAL);
  }
  
  struct xprt_class xprt_rdma_bc = {