splice: Make splice from an O_DIRECT fd use copy_splice_read()
authorDavid Howells <dhowells@redhat.com>
Mon, 22 May 2023 13:49:54 +0000 (14:49 +0100)
committerJens Axboe <axboe@kernel.dk>
Wed, 24 May 2023 14:42:16 +0000 (08:42 -0600)
Make a read splice from a file descriptor that's open O_DIRECT use
copy_splice_read() to do the reading as filemap_splice_read() is unlikely
to find any pagecache to splice.

Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Christian Brauner <brauner@kernel.org>
cc: Al Viro <viro@zeniv.linux.org.uk>
cc: Jens Axboe <axboe@kernel.dk>
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-8-dhowells@redhat.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
fs/splice.c

index fe3309ffeb26cd169f1457d784a86aa1c9452e43..76126b1aafcbe6853b3029f28603be58b9e676bc 100644 (file)
@@ -907,6 +907,12 @@ long vfs_splice_read(struct file *in, loff_t *ppos,
 
        if (unlikely(!in->f_op->splice_read))
                return warn_unsupported(in, "read");
+       /*
+        * O_DIRECT doesn't deal with the pagecache, so we allocate a buffer,
+        * copy into it and splice that into the pipe.
+        */
+       if ((in->f_flags & O_DIRECT))
+               return copy_splice_read(in, ppos, pipe, len, flags);
        return in->f_op->splice_read(in, ppos, pipe, len, flags);
 }
 EXPORT_SYMBOL_GPL(vfs_splice_read);