Merge tag 'nfsd-6.1-6' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 26 Nov 2022 20:25:49 +0000 (12:25 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 26 Nov 2022 20:25:49 +0000 (12:25 -0800)
Pull nfsd fix from Chuck Lever:

 - Fix rare data corruption on READ operations

* tag 'nfsd-6.1-6' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux:
  NFSD: Fix reads with a non-zero offset that don't end on a page boundary

1  2 
fs/nfsd/vfs.c

diff --combined fs/nfsd/vfs.c
index f650afedd67fafc5d71bbfe41a845ae4a721afe6,31bc7cc82439ce7870fbd3ba95d1cbe152c3cb54..ac3c3844cfc6770ff7a840c0735fe38e6859531e
@@@ -871,10 -871,11 +871,11 @@@ nfsd_splice_actor(struct pipe_inode_inf
        struct svc_rqst *rqstp = sd->u.data;
        struct page *page = buf->page;  // may be a compound one
        unsigned offset = buf->offset;
+       struct page *last_page;
  
-       page += offset / PAGE_SIZE;
-       for (int i = sd->len; i > 0; i -= PAGE_SIZE)
-               svc_rqst_replace_page(rqstp, page++);
+       last_page = page + (offset + sd->len - 1) / PAGE_SIZE;
+       for (page += offset / PAGE_SIZE; page <= last_page; page++)
+               svc_rqst_replace_page(rqstp, page);
        if (rqstp->rq_res.page_len == 0)        // first call
                rqstp->rq_res.page_base = offset % PAGE_SIZE;
        rqstp->rq_res.page_len += sd->len;
@@@ -1854,7 -1855,7 +1855,7 @@@ struct readdir_data 
        int             full;
  };
  
 -static int nfsd_buffered_filldir(struct dir_context *ctx, const char *name,
 +static bool nfsd_buffered_filldir(struct dir_context *ctx, const char *name,
                                 int namlen, loff_t offset, u64 ino,
                                 unsigned int d_type)
  {
        reclen = ALIGN(sizeof(struct buffered_dirent) + namlen, sizeof(u64));
        if (buf->used + reclen > PAGE_SIZE) {
                buf->full = 1;
 -              return -EINVAL;
 +              return false;
        }
  
        de->namlen = namlen;
        memcpy(de->name, name, namlen);
        buf->used += reclen;
  
 -      return 0;
 +      return true;
  }
  
  static __be32 nfsd_buffered_readdir(struct file *file, struct svc_fh *fhp,