nfs: Provide a splice-read wrapper
authorDavid Howells <dhowells@redhat.com>
Mon, 22 May 2023 13:50:07 +0000 (14:50 +0100)
committerJens Axboe <axboe@kernel.dk>
Wed, 24 May 2023 14:42:16 +0000 (08:42 -0600)
Provide a splice_read wrapper for NFS.  This locks the inode around
filemap_splice_read() and revalidates the mapping.  Splicing from direct
I/O is handled by the caller.

Signed-off-by: David Howells <dhowells@redhat.com>
cc: Christoph Hellwig <hch@lst.de>
cc: Al Viro <viro@zeniv.linux.org.uk>
cc: Jens Axboe <axboe@kernel.dk>
cc: Trond Myklebust <trond.myklebust@hammerspace.com>
cc: Anna Schumaker <anna@kernel.org>
cc: linux-nfs@vger.kernel.org
cc: linux-fsdevel@vger.kernel.org
cc: linux-block@vger.kernel.org
cc: linux-mm@kvack.org
Link: https://lore.kernel.org/r/20230522135018.2742245-21-dhowells@redhat.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
fs/nfs/file.c
fs/nfs/internal.h
fs/nfs/nfs4file.c

index f0edf5a36237d1465e717e12ca6ea962f52b2000..3855f3ce8d2defd21e68a06d6c1bdcd0e37696c4 100644 (file)
@@ -178,6 +178,27 @@ nfs_file_read(struct kiocb *iocb, struct iov_iter *to)
 }
 EXPORT_SYMBOL_GPL(nfs_file_read);
 
+ssize_t
+nfs_file_splice_read(struct file *in, loff_t *ppos, struct pipe_inode_info *pipe,
+                    size_t len, unsigned int flags)
+{
+       struct inode *inode = file_inode(in);
+       ssize_t result;
+
+       dprintk("NFS: splice_read(%pD2, %zu@%llu)\n", in, len, *ppos);
+
+       nfs_start_io_read(inode);
+       result = nfs_revalidate_mapping(inode, in->f_mapping);
+       if (!result) {
+               result = filemap_splice_read(in, ppos, pipe, len, flags);
+               if (result > 0)
+                       nfs_add_stats(inode, NFSIOS_NORMALREADBYTES, result);
+       }
+       nfs_end_io_read(inode);
+       return result;
+}
+EXPORT_SYMBOL_GPL(nfs_file_splice_read);
+
 int
 nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
 {
@@ -879,7 +900,7 @@ const struct file_operations nfs_file_operations = {
        .fsync          = nfs_file_fsync,
        .lock           = nfs_lock,
        .flock          = nfs_flock,
-       .splice_read    = generic_file_splice_read,
+       .splice_read    = nfs_file_splice_read,
        .splice_write   = iter_file_splice_write,
        .check_flags    = nfs_check_flags,
        .setlease       = simple_nosetlease,
index 3cc027d3bd588a0631be6b3ee4efd057ccc8dfa1..b5f21d35d30e84249b76184cd3c35ff21e4a61fe 100644 (file)
@@ -416,6 +416,8 @@ static inline __u32 nfs_access_xattr_mask(const struct nfs_server *server)
 int nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync);
 loff_t nfs_file_llseek(struct file *, loff_t, int);
 ssize_t nfs_file_read(struct kiocb *, struct iov_iter *);
+ssize_t nfs_file_splice_read(struct file *in, loff_t *ppos, struct pipe_inode_info *pipe,
+                            size_t len, unsigned int flags);
 int nfs_file_mmap(struct file *, struct vm_area_struct *);
 ssize_t nfs_file_write(struct kiocb *, struct iov_iter *);
 int nfs_file_release(struct inode *, struct file *);
index 2563ed8580f37045cfbc791b95234e1dd927d9a2..4aeadd6e1a6dbbbe4a7511b6f03c4db703c83d5d 100644 (file)
@@ -454,7 +454,7 @@ const struct file_operations nfs4_file_operations = {
        .fsync          = nfs_file_fsync,
        .lock           = nfs_lock,
        .flock          = nfs_flock,
-       .splice_read    = generic_file_splice_read,
+       .splice_read    = nfs_file_splice_read,
        .splice_write   = iter_file_splice_write,
        .check_flags    = nfs_check_flags,
        .setlease       = nfs4_setlease,