Merge tag 'nfs-for-5.11-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 17 Dec 2020 20:15:03 +0000 (12:15 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 17 Dec 2020 20:15:03 +0000 (12:15 -0800)
Pull NFS client updates from Trond Myklebust:
 "Highlights include:

  Features:

   - NFSv3: Add emulation of lookupp() to improve open_by_filehandle()
     support

   - A series of patches to improve readdir performance, particularly
     with large directories

   - Basic support for using NFS/RDMA with the pNFS files and flexfiles
     drivers

   - Micro-optimisations for RDMA

   - RDMA tracing improvements

  Bugfixes:

   - Fix a long standing bug with xs_read_xdr_buf() when receiving
     partial pages (Dan Aloni)

   - Various fixes for getxattr and listxattr, when used over non-TCP
     transports

   - Fixes for containerised NFS from Sargun Dhillon

   - switch nfsiod to be an UNBOUND workqueue (Neil Brown)

   - READDIR should not ask for security label information if there is
     no LSM policy (Olga Kornievskaia)

   - Avoid using interval-based rebinding with TCP in lockd (Calum
     Mackay)

   - A series of RPC and NFS layer fixes to support the NFSv4.2
     READ_PLUS code

   - A couple of fixes for pnfs/flexfiles read failover

  Cleanups:

   - Various cleanups for the SUNRPC xdr code in conjunction with the
     READ_PLUS fixes"

* tag 'nfs-for-5.11-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (90 commits)
  NFS/pNFS: Fix a typo in ff_layout_resend_pnfs_read()
  pNFS/flexfiles: Avoid spurious layout returns in ff_layout_choose_ds_for_read
  NFSv4/pnfs: Add tracing for the deviceid cache
  fs/lockd: convert comma to semicolon
  NFSv4.2: fix error return on memory allocation failure
  NFSv4.2/pnfs: Don't use READ_PLUS with pNFS yet
  NFSv4.2: Deal with potential READ_PLUS data extent buffer overflow
  NFSv4.2: Don't error when exiting early on a READ_PLUS buffer overflow
  NFSv4.2: Handle hole lengths that exceed the READ_PLUS read buffer
  NFSv4.2: decode_read_plus_hole() needs to check the extent offset
  NFSv4.2: decode_read_plus_data() must skip padding after data segment
  NFSv4.2: Ensure we always reset the result->count in decode_read_plus()
  SUNRPC: When expanding the buffer, we may need grow the sparse pages
  SUNRPC: Cleanup - constify a number of xdr_buf helpers
  SUNRPC: Clean up open coded setting of the xdr_stream 'nwords' field
  SUNRPC: _copy_to/from_pages() now check for zero length
  SUNRPC: Cleanup xdr_shrink_bufhead()
  SUNRPC: Fix xdr_expand_hole()
  SUNRPC: Fixes for xdr_align_data()
  SUNRPC: _shift_data_left/right_pages should check the shift length
  ...

1  2 
fs/nfs/dir.c
fs/nfs/flexfilelayout/flexfilelayout.c
fs/nfs/nfs42xdr.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4xdr.c
include/linux/sunrpc/xdr.h
include/trace/events/rpcrdma.h
net/sunrpc/xdr.c

diff --cc fs/nfs/dir.c
@@@ -572,11 -725,8 +725,8 @@@ static int nfs_readdir_page_filler(stru
        if (scratch == NULL)
                return -ENOMEM;
  
-       if (buflen == 0)
-               goto out_nopages;
        xdr_init_decode_pages(&stream, &buf, xdr_pages, buflen);
 -      xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE);
 +      xdr_set_scratch_page(&stream, scratch);
  
        do {
                if (entry->label)
Simple merge
@@@ -5309,18 -5319,18 +5319,18 @@@ static int nfs4_read_done(struct rpc_ta
                                    nfs4_read_done_cb(task, hdr);
  }
  
 -#ifdef CONFIG_NFS_V4_2
 +#if defined CONFIG_NFS_V4_2 && defined CONFIG_NFS_V4_2_READ_PLUS
- static void nfs42_read_plus_support(struct nfs_server *server, struct rpc_message *msg)
+ static void nfs42_read_plus_support(struct nfs_pgio_header *hdr,
+                                   struct rpc_message *msg)
  {
-       if (server->caps & NFS_CAP_READ_PLUS)
+       /* Note: We don't use READ_PLUS with pNFS yet */
+       if (nfs_server_capable(hdr->inode, NFS_CAP_READ_PLUS) && !hdr->ds_clp)
                msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ_PLUS];
-       else
-               msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ];
  }
  #else
- static void nfs42_read_plus_support(struct nfs_server *server, struct rpc_message *msg)
+ static void nfs42_read_plus_support(struct nfs_pgio_header *hdr,
+                                   struct rpc_message *msg)
  {
-       msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ];
  }
  #endif /* CONFIG_NFS_V4_2 */
  
Simple merge
@@@ -251,54 -250,10 +250,54 @@@ extern void xdr_init_decode_pages(struc
  extern __be32 *xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes);
  extern unsigned int xdr_read_pages(struct xdr_stream *xdr, unsigned int len);
  extern void xdr_enter_page(struct xdr_stream *xdr, unsigned int len);
- extern int xdr_process_buf(struct xdr_buf *buf, unsigned int offset, unsigned int len, int (*actor)(struct scatterlist *, void *), void *data);
- extern uint64_t xdr_align_data(struct xdr_stream *, uint64_t, uint32_t);
- extern uint64_t xdr_expand_hole(struct xdr_stream *, uint64_t, uint64_t);
+ extern int xdr_process_buf(const struct xdr_buf *buf, unsigned int offset, unsigned int len, int (*actor)(struct scatterlist *, void *), void *data);
+ extern unsigned int xdr_align_data(struct xdr_stream *, unsigned int offset, unsigned int length);
+ extern unsigned int xdr_expand_hole(struct xdr_stream *, unsigned int offset, unsigned int length);
 +extern bool xdr_stream_subsegment(struct xdr_stream *xdr, struct xdr_buf *subbuf,
 +                                unsigned int len);
 +
 +/**
 + * xdr_set_scratch_buffer - Attach a scratch buffer for decoding data.
 + * @xdr: pointer to xdr_stream struct
 + * @buf: pointer to an empty buffer
 + * @buflen: size of 'buf'
 + *
 + * The scratch buffer is used when decoding from an array of pages.
 + * If an xdr_inline_decode() call spans across page boundaries, then
 + * we copy the data into the scratch buffer in order to allow linear
 + * access.
 + */
 +static inline void
 +xdr_set_scratch_buffer(struct xdr_stream *xdr, void *buf, size_t buflen)
 +{
 +      xdr->scratch.iov_base = buf;
 +      xdr->scratch.iov_len = buflen;
 +}
 +
 +/**
 + * xdr_set_scratch_page - Attach a scratch buffer for decoding data
 + * @xdr: pointer to xdr_stream struct
 + * @page: an anonymous page
 + *
 + * See xdr_set_scratch_buffer().
 + */
 +static inline void
 +xdr_set_scratch_page(struct xdr_stream *xdr, struct page *page)
 +{
 +      xdr_set_scratch_buffer(xdr, page_address(page), PAGE_SIZE);
 +}
 +
 +/**
 + * xdr_reset_scratch_buffer - Clear scratch buffer information
 + * @xdr: pointer to xdr_stream struct
 + *
 + * See xdr_set_scratch_buffer().
 + */
 +static inline void
 +xdr_reset_scratch_buffer(struct xdr_stream *xdr)
 +{
 +      xdr_set_scratch_buffer(xdr, NULL, 0);
 +}
  
  /**
   * xdr_stream_remaining - Return the number of bytes remaining in the stream
Simple merge
@@@ -1051,14 -1298,12 +1297,11 @@@ void xdr_init_decode(struct xdr_stream 
                     struct rpc_rqst *rqst)
  {
        xdr->buf = buf;
 -      xdr->scratch.iov_base = NULL;
 -      xdr->scratch.iov_len = 0;
 +      xdr_reset_scratch_buffer(xdr);
        xdr->nwords = XDR_QUADLEN(buf->len);
-       if (buf->head[0].iov_len != 0)
-               xdr_set_iov(xdr, buf->head, buf->len);
-       else if (buf->page_len != 0)
-               xdr_set_page_base(xdr, 0, buf->len);
-       else
-               xdr_set_iov(xdr, buf->head, buf->len);
+       if (xdr_set_iov(xdr, buf->head, 0, buf->len) == 0 &&
+           xdr_set_page_base(xdr, 0, buf->len) == 0)
+               xdr_set_iov(xdr, buf->tail, 0, buf->len);
        if (p != NULL && p > xdr->p && xdr->end >= p) {
                xdr->nwords -= p - xdr->p;
                xdr->p = p;