[PATCH v20 24/32] splice: Do splice read from a file without using ITER_PIPE
From: David Howells
Date: Fri May 19 2023 - 03:45:26 EST
Make generic_file_splice_read() use filemap_splice_read() and
direct_splice_read() rather than using an ITER_PIPE and call_read_iter().
With this, ITER_PIPE is no longer used.
Signed-off-by: David Howells <dhowells@xxxxxxxxxx>
Reviewed-by: Christoph Hellwig <hch@xxxxxx>
cc: Jens Axboe <axboe@xxxxxxxxx>
cc: Steve French <smfrench@xxxxxxxxx>
cc: Al Viro <viro@xxxxxxxxxxxxxxxxxx>
cc: David Hildenbrand <david@xxxxxxxxxx>
cc: John Hubbard <jhubbard@xxxxxxxxxx>
cc: linux-mm@xxxxxxxxx
cc: linux-block@xxxxxxxxxxxxxxx
cc: linux-cifs@xxxxxxxxxxxxxxx
cc: linux-fsdevel@xxxxxxxxxxxxxxx
---
Notes:
ver #20)
- Use s_maxbytes from the backing store (in->f_mapping), not the front
inode (especially for a blockdev).
ver #18)
- Split out the change to cifs to make it use generic_file_splice_read().
- Split out the unexport of filemap_splice_read() (still needed by cifs).
fs/splice.c | 31 +++++++------------------------
1 file changed, 7 insertions(+), 24 deletions(-)
diff --git a/fs/splice.c b/fs/splice.c
index 7b818b5b18d4..56d9802729d0 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -417,34 +417,17 @@ ssize_t generic_file_splice_read(struct file *in, loff_t *ppos,
struct pipe_inode_info *pipe, size_t len,
unsigned int flags)
{
- struct iov_iter to;
- struct kiocb kiocb;
- int ret;
-
+ if (unlikely(*ppos >= in->f_mapping->host->i_sb->s_maxbytes))
+ return 0;
+ if (unlikely(!len))
+ return 0;
#ifdef CONFIG_FS_DAX
if (IS_DAX(in->f_mapping->host))
return direct_splice_read(in, ppos, pipe, len, flags);
#endif
-
- iov_iter_pipe(&to, ITER_DEST, pipe, len);
- init_sync_kiocb(&kiocb, in);
- kiocb.ki_pos = *ppos;
- ret = call_read_iter(in, &kiocb, &to);
- if (ret > 0) {
- *ppos = kiocb.ki_pos;
- file_accessed(in);
- } else if (ret < 0) {
- /* free what was emitted */
- pipe_discard_from(pipe, to.start_head);
- /*
- * callers of ->splice_read() expect -EAGAIN on
- * "can't put anything in there", rather than -EFAULT.
- */
- if (ret == -EFAULT)
- ret = -EAGAIN;
- }
-
- return ret;
+ if ((in->f_flags & O_DIRECT))
+ return direct_splice_read(in, ppos, pipe, len, flags);
+ return filemap_splice_read(in, ppos, pipe, len, flags);
}
EXPORT_SYMBOL(generic_file_splice_read);