xfs: Provide a splice-read wrapper
authorDavid Howells <dhowells@redhat.com>
Mon, 22 May 2023 13:50:11 +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 XFS.  This does a stat count and a
shutdown check before proceeding, then emits a new trace line and locks the
inode across the call to filemap_splice_read() and adds to the stats
afterwards.  Splicing from direct I/O or DAX is handled by the caller.

Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
cc: Al Viro <viro@zeniv.linux.org.uk>
cc: Jens Axboe <axboe@kernel.dk>
cc: Darrick J. Wong <djwong@kernel.org>
cc: linux-xfs@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-25-dhowells@redhat.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
fs/xfs/xfs_file.c
fs/xfs/xfs_trace.h

index aede746..08d6326 100644 (file)
@@ -306,6 +306,34 @@ xfs_file_read_iter(
        return ret;
 }
 
+STATIC ssize_t
+xfs_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);
+       struct xfs_inode        *ip = XFS_I(inode);
+       struct xfs_mount        *mp = ip->i_mount;
+       ssize_t                 ret = 0;
+
+       XFS_STATS_INC(mp, xs_read_calls);
+
+       if (xfs_is_shutdown(mp))
+               return -EIO;
+
+       trace_xfs_file_splice_read(ip, *ppos, len);
+
+       xfs_ilock(ip, XFS_IOLOCK_SHARED);
+       ret = filemap_splice_read(in, ppos, pipe, len, flags);
+       xfs_iunlock(ip, XFS_IOLOCK_SHARED);
+       if (ret > 0)
+               XFS_STATS_ADD(mp, xs_read_bytes, ret);
+       return ret;
+}
+
 /*
  * Common pre-write limit and setup checks.
  *
@@ -1423,7 +1451,7 @@ const struct file_operations xfs_file_operations = {
        .llseek         = xfs_file_llseek,
        .read_iter      = xfs_file_read_iter,
        .write_iter     = xfs_file_write_iter,
-       .splice_read    = generic_file_splice_read,
+       .splice_read    = xfs_file_splice_read,
        .splice_write   = iter_file_splice_write,
        .iopoll         = iocb_bio_iopoll,
        .unlocked_ioctl = xfs_file_ioctl,
index cd4ca5b..4db6692 100644 (file)
@@ -1445,7 +1445,6 @@ DEFINE_RW_EVENT(xfs_file_direct_write);
 DEFINE_RW_EVENT(xfs_file_dax_write);
 DEFINE_RW_EVENT(xfs_reflink_bounce_dio_write);
 
-
 DECLARE_EVENT_CLASS(xfs_imap_class,
        TP_PROTO(struct xfs_inode *ip, xfs_off_t offset, ssize_t count,
                 int whichfork, struct xfs_bmbt_irec *irec),
@@ -1535,6 +1534,7 @@ DEFINE_SIMPLE_IO_EVENT(xfs_zero_eof);
 DEFINE_SIMPLE_IO_EVENT(xfs_end_io_direct_write);
 DEFINE_SIMPLE_IO_EVENT(xfs_end_io_direct_write_unwritten);
 DEFINE_SIMPLE_IO_EVENT(xfs_end_io_direct_write_append);
+DEFINE_SIMPLE_IO_EVENT(xfs_file_splice_read);
 
 DECLARE_EVENT_CLASS(xfs_itrunc_class,
        TP_PROTO(struct xfs_inode *ip, xfs_fsize_t new_size),