Merge tag 'nfsd-4.19-1' of git://linux-nfs.org/~bfields/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 23 Aug 2018 23:00:10 +0000 (16:00 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 23 Aug 2018 23:00:10 +0000 (16:00 -0700)
Pull nfsd updates from Bruce Fields:
 "Chuck Lever fixed a problem with NFSv4.0 callbacks over GSS from
  multi-homed servers.

  The only new feature is a minor bit of protocol (change_attr_type)
  which the client doesn't even use yet.

  Other than that, various bugfixes and cleanup"

* tag 'nfsd-4.19-1' of git://linux-nfs.org/~bfields/linux: (27 commits)
  sunrpc: Add comment defining gssd upcall API keywords
  nfsd: Remove callback_cred
  nfsd: Use correct credential for NFSv4.0 callback with GSS
  sunrpc: Extract target name into svc_cred
  sunrpc: Enable the kernel to specify the hostname part of service principals
  sunrpc: Don't use stack buffer with scatterlist
  rpc: remove unneeded variable 'ret' in rdma_listen_handler
  nfsd: use true and false for boolean values
  nfsd: constify write_op[]
  fs/nfsd: Delete invalid assignment statements in nfsd4_decode_exchange_id
  NFSD: Handle full-length symlinks
  NFSD: Refactor the generic write vector fill helper
  svcrdma: Clean up Read chunk path
  svcrdma: Avoid releasing a page in svc_xprt_release()
  nfsd: Mark expected switch fall-through
  sunrpc: remove redundant variables 'checksumlen','blocksize' and 'data'
  nfsd: fix leaked file lock with nfs exported overlayfs
  nfsd: don't advertise a SCSI layout for an unsupported request_queue
  nfsd: fix corrupted reply to badly ordered compound
  nfsd: clarify check_op_ordering
  ...

1  2 
net/sunrpc/auth_gss/auth_gss.c
net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
net/sunrpc/xprtrdma/svc_rdma_rw.c
net/sunrpc/xprtrdma/svc_rdma_sendto.c
net/sunrpc/xprtrdma/svc_rdma_transport.c

@@@ -284,7 -284,12 +284,12 @@@ err
        return p;
  }
  
- #define UPCALL_BUF_LEN 128
+ /* XXX: Need some documentation about why UPCALL_BUF_LEN is so small.
+  *    Is user space expecting no more than UPCALL_BUF_LEN bytes?
+  *    Note that there are now _two_ NI_MAXHOST sized data items
+  *    being passed in this string.
+  */
+ #define UPCALL_BUF_LEN        256
  
  struct gss_upcall_msg {
        refcount_t count;
@@@ -456,18 -461,44 +461,44 @@@ static int gss_encode_v1_msg(struct gss
        buflen -= len;
        p += len;
        gss_msg->msg.len = len;
+       /*
+        * target= is a full service principal that names the remote
+        * identity that we are authenticating to.
+        */
        if (target_name) {
                len = scnprintf(p, buflen, "target=%s ", target_name);
                buflen -= len;
                p += len;
                gss_msg->msg.len += len;
        }
-       if (service_name != NULL) {
-               len = scnprintf(p, buflen, "service=%s ", service_name);
+       /*
+        * gssd uses service= and srchost= to select a matching key from
+        * the system's keytab to use as the source principal.
+        *
+        * service= is the service name part of the source principal,
+        * or "*" (meaning choose any).
+        *
+        * srchost= is the hostname part of the source principal. When
+        * not provided, gssd uses the local hostname.
+        */
+       if (service_name) {
+               char *c = strchr(service_name, '@');
+               if (!c)
+                       len = scnprintf(p, buflen, "service=%s ",
+                                       service_name);
+               else
+                       len = scnprintf(p, buflen,
+                                       "service=%.*s srchost=%s ",
+                                       (int)(c - service_name),
+                                       service_name, c + 1);
                buflen -= len;
                p += len;
                gss_msg->msg.len += len;
        }
        if (mech->gm_upcall_enctypes) {
                len = scnprintf(p, buflen, "enctypes=%s ",
                                mech->gm_upcall_enctypes);
@@@ -517,7 -548,7 +548,7 @@@ gss_alloc_msg(struct gss_auth *gss_auth
                err = gss_encode_v1_msg(gss_msg, service_name, gss_auth->target_name);
                if (err)
                        goto err_put_pipe_version;
 -      };
 +      }
        kref_get(&gss_auth->kref);
        return gss_msg;
  err_put_pipe_version:
@@@ -229,10 -229,11 +229,10 @@@ void svc_rdma_recv_ctxt_put(struct svcx
  static int __svc_rdma_post_recv(struct svcxprt_rdma *rdma,
                                struct svc_rdma_recv_ctxt *ctxt)
  {
 -      struct ib_recv_wr *bad_recv_wr;
        int ret;
  
        svc_xprt_get(&rdma->sc_xprt);
 -      ret = ib_post_recv(rdma->sc_qp, &ctxt->rc_recv_wr, &bad_recv_wr);
 +      ret = ib_post_recv(rdma->sc_qp, &ctxt->rc_recv_wr, NULL);
        trace_svcrdma_post_recv(&ctxt->rc_recv_wr, ret);
        if (ret)
                goto err_post;
@@@ -365,9 -366,6 +365,6 @@@ static void svc_rdma_build_arg_xdr(stru
        arg->page_base = 0;
        arg->buflen = ctxt->rc_byte_len;
        arg->len = ctxt->rc_byte_len;
-       rqstp->rq_respages = &rqstp->rq_pages[0];
-       rqstp->rq_next_page = rqstp->rq_respages + 1;
  }
  
  /* This accommodates the largest possible Write chunk,
@@@ -729,6 -727,12 +726,12 @@@ int svc_rdma_recvfrom(struct svc_rqst *
  
        svc_rdma_build_arg_xdr(rqstp, ctxt);
  
+       /* Prevent svc_xprt_release from releasing pages in rq_pages
+        * if we return 0 or an error.
+        */
+       rqstp->rq_respages = rqstp->rq_pages;
+       rqstp->rq_next_page = rqstp->rq_respages;
        p = (__be32 *)rqstp->rq_arg.head[0].iov_base;
        ret = svc_rdma_xdr_decode_req(&rqstp->rq_arg);
        if (ret < 0)
@@@ -307,8 -307,7 +307,8 @@@ static int svc_rdma_post_chunk_ctxt(str
  {
        struct svcxprt_rdma *rdma = cc->cc_rdma;
        struct svc_xprt *xprt = &rdma->sc_xprt;
 -      struct ib_send_wr *first_wr, *bad_wr;
 +      struct ib_send_wr *first_wr;
 +      const struct ib_send_wr *bad_wr;
        struct list_head *tmp;
        struct ib_cqe *cqe;
        int ret;
@@@ -680,6 -679,7 +680,7 @@@ static int svc_rdma_build_read_chunk(st
                                     struct svc_rdma_read_info *info,
                                     __be32 *p)
  {
+       unsigned int i;
        int ret;
  
        ret = -EINVAL;
                info->ri_chunklen += rs_length;
        }
  
+       /* Pages under I/O have been copied to head->rc_pages.
+        * Prevent their premature release by svc_xprt_release() .
+        */
+       for (i = 0; i < info->ri_readctxt->rc_page_count; i++)
+               rqstp->rq_pages[i] = NULL;
        return ret;
  }
  
@@@ -817,7 -823,6 +824,6 @@@ int svc_rdma_recv_read_chunk(struct svc
                             struct svc_rdma_recv_ctxt *head, __be32 *p)
  {
        struct svc_rdma_read_info *info;
-       struct page **page;
        int ret;
  
        /* The request (with page list) is constructed in
                ret = svc_rdma_build_normal_read_chunk(rqstp, info, p);
        else
                ret = svc_rdma_build_pz_read_chunk(rqstp, info, p);
-       /* Mark the start of the pages that can be used for the reply */
-       if (info->ri_pageoff > 0)
-               info->ri_pageno++;
-       rqstp->rq_respages = &rqstp->rq_pages[info->ri_pageno];
-       rqstp->rq_next_page = rqstp->rq_respages + 1;
        if (ret < 0)
-               goto out;
+               goto out_err;
  
        ret = svc_rdma_post_chunk_ctxt(&info->ri_cc);
- out:
-       /* Read sink pages have been moved from rqstp->rq_pages to
-        * head->rc_arg.pages. Force svc_recv to refill those slots
-        * in rq_pages.
-        */
-       for (page = rqstp->rq_pages; page < rqstp->rq_respages; page++)
-               *page = NULL;
        if (ret < 0)
-               svc_rdma_read_info_free(info);
+               goto out_err;
+       return 0;
+ out_err:
+       svc_rdma_read_info_free(info);
        return ret;
  }
@@@ -291,6 -291,7 +291,6 @@@ static void svc_rdma_wc_send(struct ib_
   */
  int svc_rdma_send(struct svcxprt_rdma *rdma, struct ib_send_wr *wr)
  {
 -      struct ib_send_wr *bad_wr;
        int ret;
  
        might_sleep();
                }
  
                svc_xprt_get(&rdma->sc_xprt);
 -              ret = ib_post_send(rdma->sc_qp, wr, &bad_wr);
 +              ret = ib_post_send(rdma->sc_qp, wr, NULL);
                trace_svcrdma_post_send(wr, ret);
                if (ret) {
                        set_bit(XPT_CLOSE, &rdma->sc_xprt.xpt_flags);
@@@ -656,7 -657,9 +656,9 @@@ static void svc_rdma_save_io_pages(stru
                ctxt->sc_pages[i] = rqstp->rq_respages[i];
                rqstp->rq_respages[i] = NULL;
        }
-       rqstp->rq_next_page = rqstp->rq_respages + 1;
+       /* Prevent svc_xprt_release from releasing pages in rq_pages */
+       rqstp->rq_next_page = rqstp->rq_respages;
  }
  
  /* Prepare the portion of the RPC Reply that will be transmitted
@@@ -296,7 -296,6 +296,6 @@@ static int rdma_listen_handler(struct r
                               struct rdma_cm_event *event)
  {
        struct sockaddr *sap = (struct sockaddr *)&cma_id->route.addr.src_addr;
-       int ret = 0;
  
        trace_svcrdma_cm_event(event, sap);
  
                break;
        }
  
-       return ret;
+       return 0;
  }
  
  static int rdma_cma_handler(struct rdma_cm_id *cma_id,
@@@ -476,7 -475,7 +475,7 @@@ static struct svc_xprt *svc_rdma_accept
  
        /* Qualify the transport resource defaults with the
         * capabilities of this particular device */
 -      newxprt->sc_max_send_sges = dev->attrs.max_sge;
 +      newxprt->sc_max_send_sges = dev->attrs.max_send_sge;
        /* transport hdr, head iovec, one page list entry, tail iovec */
        if (newxprt->sc_max_send_sges < 4) {
                pr_err("svcrdma: too few Send SGEs available (%d)\n",