Skip to content

Commit 3eccc0c

Browse files
committed
Merge tag 'for-6.5/splice-2023-06-23' of git://git.kernel.dk/linux
Pull splice updates from Jens Axboe: "This kills off ITER_PIPE to avoid a race between truncate, iov_iter_revert() on the pipe and an as-yet incomplete DMA to a bio with unpinned/unref'ed pages from an O_DIRECT splice read. This causes memory corruption. Instead, we either use (a) filemap_splice_read(), which invokes the buffered file reading code and splices from the pagecache into the pipe; (b) copy_splice_read(), which bulk-allocates a buffer, reads into it and then pushes the filled pages into the pipe; or (c) handle it in filesystem-specific code. Summary: - Rename direct_splice_read() to copy_splice_read() - Simplify the calculations for the number of pages to be reclaimed in copy_splice_read() - Turn do_splice_to() into a helper, vfs_splice_read(), so that it can be used by overlayfs and coda to perform the checks on the lower fs - Make vfs_splice_read() jump to copy_splice_read() to handle direct-I/O and DAX - Provide shmem with its own splice_read to handle non-existent pages in the pagecache. We don't want a ->read_folio() as we don't want to populate holes, but filemap_get_pages() requires it - Provide overlayfs with its own splice_read to call down to a lower layer as overlayfs doesn't provide ->read_folio() - Provide coda with its own splice_read to call down to a lower layer as coda doesn't provide ->read_folio() - Direct ->splice_read to copy_splice_read() in tty, procfs, kernfs and random files as they just copy to the output buffer and don't splice pages - Provide wrappers for afs, ceph, ecryptfs, ext4, f2fs, nfs, ntfs3, ocfs2, orangefs, xfs and zonefs to do locking and/or revalidation - Make cifs use filemap_splice_read() - Replace pointers to generic_file_splice_read() with pointers to filemap_splice_read() as DIO and DAX are handled in the caller; filesystems can still provide their own alternate ->splice_read() op - Remove generic_file_splice_read() - Remove ITER_PIPE and its paraphernalia as generic_file_splice_read was the only user" * tag 'for-6.5/splice-2023-06-23' of git://git.kernel.dk/linux: (31 commits) splice: kdoc for filemap_splice_read() and copy_splice_read() iov_iter: Kill ITER_PIPE splice: Remove generic_file_splice_read() splice: Use filemap_splice_read() instead of generic_file_splice_read() cifs: Use filemap_splice_read() trace: Convert trace/seq to use copy_splice_read() zonefs: Provide a splice-read wrapper xfs: Provide a splice-read wrapper orangefs: Provide a splice-read wrapper ocfs2: Provide a splice-read wrapper ntfs3: Provide a splice-read wrapper nfs: Provide a splice-read wrapper f2fs: Provide a splice-read wrapper ext4: Provide a splice-read wrapper ecryptfs: Provide a splice-read wrapper ceph: Provide a splice-read wrapper afs: Provide a splice-read wrapper 9p: Add splice_read wrapper net: Make sock_splice_read() use copy_splice_read() by default tty, proc, kernfs, random: Use copy_splice_read() ...
2 parents cc423f6 + 9eee8bd commit 3eccc0c

File tree

68 files changed

+694
-621
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+694
-621
lines changed

block/fops.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -701,7 +701,7 @@ const struct file_operations def_blk_fops = {
701701
#ifdef CONFIG_COMPAT
702702
.compat_ioctl = compat_blkdev_ioctl,
703703
#endif
704-
.splice_read = generic_file_splice_read,
704+
.splice_read = filemap_splice_read,
705705
.splice_write = iter_file_splice_write,
706706
.fallocate = blkdev_fallocate,
707707
};

drivers/char/random.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1546,7 +1546,7 @@ const struct file_operations random_fops = {
15461546
.compat_ioctl = compat_ptr_ioctl,
15471547
.fasync = random_fasync,
15481548
.llseek = noop_llseek,
1549-
.splice_read = generic_file_splice_read,
1549+
.splice_read = copy_splice_read,
15501550
.splice_write = iter_file_splice_write,
15511551
};
15521552

@@ -1557,7 +1557,7 @@ const struct file_operations urandom_fops = {
15571557
.compat_ioctl = compat_ptr_ioctl,
15581558
.fasync = random_fasync,
15591559
.llseek = noop_llseek,
1560-
.splice_read = generic_file_splice_read,
1560+
.splice_read = copy_splice_read,
15611561
.splice_write = iter_file_splice_write,
15621562
};
15631563

drivers/tty/tty_io.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,7 @@ static const struct file_operations tty_fops = {
466466
.llseek = no_llseek,
467467
.read_iter = tty_read,
468468
.write_iter = tty_write,
469-
.splice_read = generic_file_splice_read,
469+
.splice_read = copy_splice_read,
470470
.splice_write = iter_file_splice_write,
471471
.poll = tty_poll,
472472
.unlocked_ioctl = tty_ioctl,
@@ -481,7 +481,7 @@ static const struct file_operations console_fops = {
481481
.llseek = no_llseek,
482482
.read_iter = tty_read,
483483
.write_iter = redirected_tty_write,
484-
.splice_read = generic_file_splice_read,
484+
.splice_read = copy_splice_read,
485485
.splice_write = iter_file_splice_write,
486486
.poll = tty_poll,
487487
.unlocked_ioctl = tty_ioctl,

fs/9p/vfs_file.c

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,28 @@ v9fs_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
374374
return ret;
375375
}
376376

377+
/*
378+
* v9fs_file_splice_read - splice-read from a file
379+
* @in: The 9p file to read from
380+
* @ppos: Where to find/update the file position
381+
* @pipe: The pipe to splice into
382+
* @len: The maximum amount of data to splice
383+
* @flags: SPLICE_F_* flags
384+
*/
385+
static ssize_t v9fs_file_splice_read(struct file *in, loff_t *ppos,
386+
struct pipe_inode_info *pipe,
387+
size_t len, unsigned int flags)
388+
{
389+
struct p9_fid *fid = in->private_data;
390+
391+
p9_debug(P9_DEBUG_VFS, "fid %d count %zu offset %lld\n",
392+
fid->fid, len, *ppos);
393+
394+
if (fid->mode & P9L_DIRECT)
395+
return copy_splice_read(in, ppos, pipe, len, flags);
396+
return filemap_splice_read(in, ppos, pipe, len, flags);
397+
}
398+
377399
/**
378400
* v9fs_file_write_iter - write to a file
379401
* @iocb: The operation parameters
@@ -569,7 +591,7 @@ const struct file_operations v9fs_file_operations = {
569591
.release = v9fs_dir_release,
570592
.lock = v9fs_file_lock,
571593
.mmap = generic_file_readonly_mmap,
572-
.splice_read = generic_file_splice_read,
594+
.splice_read = v9fs_file_splice_read,
573595
.splice_write = iter_file_splice_write,
574596
.fsync = v9fs_file_fsync,
575597
};
@@ -583,7 +605,7 @@ const struct file_operations v9fs_file_operations_dotl = {
583605
.lock = v9fs_file_lock_dotl,
584606
.flock = v9fs_file_flock_dotl,
585607
.mmap = v9fs_file_mmap,
586-
.splice_read = generic_file_splice_read,
608+
.splice_read = v9fs_file_splice_read,
587609
.splice_write = iter_file_splice_write,
588610
.fsync = v9fs_file_fsync_dotl,
589611
};

fs/adfs/file.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ const struct file_operations adfs_file_operations = {
2828
.mmap = generic_file_mmap,
2929
.fsync = generic_file_fsync,
3030
.write_iter = generic_file_write_iter,
31-
.splice_read = generic_file_splice_read,
31+
.splice_read = filemap_splice_read,
3232
};
3333

3434
const struct inode_operations adfs_file_inode_operations = {

fs/affs/file.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1001,7 +1001,7 @@ const struct file_operations affs_file_operations = {
10011001
.open = affs_file_open,
10021002
.release = affs_file_release,
10031003
.fsync = affs_file_fsync,
1004-
.splice_read = generic_file_splice_read,
1004+
.splice_read = filemap_splice_read,
10051005
};
10061006

10071007
const struct inode_operations affs_file_inode_operations = {

fs/afs/file.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ static void afs_invalidate_folio(struct folio *folio, size_t offset,
2525
static bool afs_release_folio(struct folio *folio, gfp_t gfp_flags);
2626

2727
static ssize_t afs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter);
28+
static ssize_t afs_file_splice_read(struct file *in, loff_t *ppos,
29+
struct pipe_inode_info *pipe,
30+
size_t len, unsigned int flags);
2831
static void afs_vm_open(struct vm_area_struct *area);
2932
static void afs_vm_close(struct vm_area_struct *area);
3033
static vm_fault_t afs_vm_map_pages(struct vm_fault *vmf, pgoff_t start_pgoff, pgoff_t end_pgoff);
@@ -36,7 +39,7 @@ const struct file_operations afs_file_operations = {
3639
.read_iter = afs_file_read_iter,
3740
.write_iter = afs_file_write,
3841
.mmap = afs_file_mmap,
39-
.splice_read = generic_file_splice_read,
42+
.splice_read = afs_file_splice_read,
4043
.splice_write = iter_file_splice_write,
4144
.fsync = afs_fsync,
4245
.lock = afs_lock,
@@ -587,3 +590,18 @@ static ssize_t afs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
587590

588591
return generic_file_read_iter(iocb, iter);
589592
}
593+
594+
static ssize_t afs_file_splice_read(struct file *in, loff_t *ppos,
595+
struct pipe_inode_info *pipe,
596+
size_t len, unsigned int flags)
597+
{
598+
struct afs_vnode *vnode = AFS_FS_I(file_inode(in));
599+
struct afs_file *af = in->private_data;
600+
int ret;
601+
602+
ret = afs_validate(vnode, af->key);
603+
if (ret < 0)
604+
return ret;
605+
606+
return filemap_splice_read(in, ppos, pipe, len, flags);
607+
}

fs/bfs/file.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ const struct file_operations bfs_file_operations = {
2727
.read_iter = generic_file_read_iter,
2828
.write_iter = generic_file_write_iter,
2929
.mmap = generic_file_mmap,
30-
.splice_read = generic_file_splice_read,
30+
.splice_read = filemap_splice_read,
3131
};
3232

3333
static int bfs_move_block(unsigned long from, unsigned long to,

fs/btrfs/file.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3817,7 +3817,7 @@ static ssize_t btrfs_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
38173817
const struct file_operations btrfs_file_operations = {
38183818
.llseek = btrfs_file_llseek,
38193819
.read_iter = btrfs_file_read_iter,
3820-
.splice_read = generic_file_splice_read,
3820+
.splice_read = filemap_splice_read,
38213821
.write_iter = btrfs_file_write_iter,
38223822
.splice_write = iter_file_splice_write,
38233823
.mmap = btrfs_file_mmap,

fs/ceph/file.c

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1745,6 +1745,69 @@ static ssize_t ceph_read_iter(struct kiocb *iocb, struct iov_iter *to)
17451745
return ret;
17461746
}
17471747

1748+
/*
1749+
* Wrap filemap_splice_read with checks for cap bits on the inode.
1750+
* Atomically grab references, so that those bits are not released
1751+
* back to the MDS mid-read.
1752+
*/
1753+
static ssize_t ceph_splice_read(struct file *in, loff_t *ppos,
1754+
struct pipe_inode_info *pipe,
1755+
size_t len, unsigned int flags)
1756+
{
1757+
struct ceph_file_info *fi = in->private_data;
1758+
struct inode *inode = file_inode(in);
1759+
struct ceph_inode_info *ci = ceph_inode(inode);
1760+
ssize_t ret;
1761+
int want = 0, got = 0;
1762+
CEPH_DEFINE_RW_CONTEXT(rw_ctx, 0);
1763+
1764+
dout("splice_read %p %llx.%llx %llu~%zu trying to get caps on %p\n",
1765+
inode, ceph_vinop(inode), *ppos, len, inode);
1766+
1767+
if (ceph_inode_is_shutdown(inode))
1768+
return -ESTALE;
1769+
1770+
if (ceph_has_inline_data(ci) ||
1771+
(fi->flags & CEPH_F_SYNC))
1772+
return copy_splice_read(in, ppos, pipe, len, flags);
1773+
1774+
ceph_start_io_read(inode);
1775+
1776+
want = CEPH_CAP_FILE_CACHE;
1777+
if (fi->fmode & CEPH_FILE_MODE_LAZY)
1778+
want |= CEPH_CAP_FILE_LAZYIO;
1779+
1780+
ret = ceph_get_caps(in, CEPH_CAP_FILE_RD, want, -1, &got);
1781+
if (ret < 0)
1782+
goto out_end;
1783+
1784+
if ((got & (CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_LAZYIO)) == 0) {
1785+
dout("splice_read/sync %p %llx.%llx %llu~%zu got cap refs on %s\n",
1786+
inode, ceph_vinop(inode), *ppos, len,
1787+
ceph_cap_string(got));
1788+
1789+
ceph_put_cap_refs(ci, got);
1790+
ceph_end_io_read(inode);
1791+
return copy_splice_read(in, ppos, pipe, len, flags);
1792+
}
1793+
1794+
dout("splice_read %p %llx.%llx %llu~%zu got cap refs on %s\n",
1795+
inode, ceph_vinop(inode), *ppos, len, ceph_cap_string(got));
1796+
1797+
rw_ctx.caps = got;
1798+
ceph_add_rw_context(fi, &rw_ctx);
1799+
ret = filemap_splice_read(in, ppos, pipe, len, flags);
1800+
ceph_del_rw_context(fi, &rw_ctx);
1801+
1802+
dout("splice_read %p %llx.%llx dropping cap refs on %s = %zd\n",
1803+
inode, ceph_vinop(inode), ceph_cap_string(got), ret);
1804+
1805+
ceph_put_cap_refs(ci, got);
1806+
out_end:
1807+
ceph_end_io_read(inode);
1808+
return ret;
1809+
}
1810+
17481811
/*
17491812
* Take cap references to avoid releasing caps to MDS mid-write.
17501813
*
@@ -2593,7 +2656,7 @@ const struct file_operations ceph_file_fops = {
25932656
.lock = ceph_lock,
25942657
.setlease = simple_nosetlease,
25952658
.flock = ceph_flock,
2596-
.splice_read = generic_file_splice_read,
2659+
.splice_read = ceph_splice_read,
25972660
.splice_write = iter_file_splice_write,
25982661
.unlocked_ioctl = ceph_ioctl,
25992662
.compat_ioctl = compat_ptr_ioctl,

fs/coda/file.c

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <linux/slab.h>
2424
#include <linux/uaccess.h>
2525
#include <linux/uio.h>
26+
#include <linux/splice.h>
2627

2728
#include <linux/coda.h>
2829
#include "coda_psdev.h"
@@ -94,6 +95,32 @@ coda_file_write_iter(struct kiocb *iocb, struct iov_iter *to)
9495
return ret;
9596
}
9697

98+
static ssize_t
99+
coda_file_splice_read(struct file *coda_file, loff_t *ppos,
100+
struct pipe_inode_info *pipe,
101+
size_t len, unsigned int flags)
102+
{
103+
struct inode *coda_inode = file_inode(coda_file);
104+
struct coda_file_info *cfi = coda_ftoc(coda_file);
105+
struct file *in = cfi->cfi_container;
106+
loff_t ki_pos = *ppos;
107+
ssize_t ret;
108+
109+
ret = venus_access_intent(coda_inode->i_sb, coda_i2f(coda_inode),
110+
&cfi->cfi_access_intent,
111+
len, ki_pos, CODA_ACCESS_TYPE_READ);
112+
if (ret)
113+
goto finish_read;
114+
115+
ret = vfs_splice_read(in, ppos, pipe, len, flags);
116+
117+
finish_read:
118+
venus_access_intent(coda_inode->i_sb, coda_i2f(coda_inode),
119+
&cfi->cfi_access_intent,
120+
len, ki_pos, CODA_ACCESS_TYPE_READ_FINISH);
121+
return ret;
122+
}
123+
97124
static void
98125
coda_vm_open(struct vm_area_struct *vma)
99126
{
@@ -302,5 +329,5 @@ const struct file_operations coda_file_operations = {
302329
.open = coda_open,
303330
.release = coda_release,
304331
.fsync = coda_fsync,
305-
.splice_read = generic_file_splice_read,
332+
.splice_read = coda_file_splice_read,
306333
};

fs/cramfs/inode.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,7 @@ static unsigned int cramfs_physmem_mmap_capabilities(struct file *file)
473473
static const struct file_operations cramfs_physmem_fops = {
474474
.llseek = generic_file_llseek,
475475
.read_iter = generic_file_read_iter,
476-
.splice_read = generic_file_splice_read,
476+
.splice_read = filemap_splice_read,
477477
.mmap = cramfs_physmem_mmap,
478478
#ifndef CONFIG_MMU
479479
.get_unmapped_area = cramfs_physmem_get_unmapped_area,

fs/ecryptfs/file.c

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,31 @@ static ssize_t ecryptfs_read_update_atime(struct kiocb *iocb,
4444
return rc;
4545
}
4646

47+
/*
48+
* ecryptfs_splice_read_update_atime
49+
*
50+
* filemap_splice_read updates the atime of upper layer inode. But, it
51+
* doesn't give us a chance to update the atime of the lower layer inode. This
52+
* function is a wrapper to generic_file_read. It updates the atime of the
53+
* lower level inode if generic_file_read returns without any errors. This is
54+
* to be used only for file reads. The function to be used for directory reads
55+
* is ecryptfs_read.
56+
*/
57+
static ssize_t ecryptfs_splice_read_update_atime(struct file *in, loff_t *ppos,
58+
struct pipe_inode_info *pipe,
59+
size_t len, unsigned int flags)
60+
{
61+
ssize_t rc;
62+
const struct path *path;
63+
64+
rc = filemap_splice_read(in, ppos, pipe, len, flags);
65+
if (rc >= 0) {
66+
path = ecryptfs_dentry_to_lower_path(in->f_path.dentry);
67+
touch_atime(path);
68+
}
69+
return rc;
70+
}
71+
4772
struct ecryptfs_getdents_callback {
4873
struct dir_context ctx;
4974
struct dir_context *caller;
@@ -414,5 +439,5 @@ const struct file_operations ecryptfs_main_fops = {
414439
.release = ecryptfs_release,
415440
.fsync = ecryptfs_fsync,
416441
.fasync = ecryptfs_fasync,
417-
.splice_read = generic_file_splice_read,
442+
.splice_read = ecryptfs_splice_read_update_atime,
418443
};

fs/erofs/data.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -448,5 +448,5 @@ const struct file_operations erofs_file_fops = {
448448
.llseek = generic_file_llseek,
449449
.read_iter = erofs_file_read_iter,
450450
.mmap = erofs_file_mmap,
451-
.splice_read = generic_file_splice_read,
451+
.splice_read = filemap_splice_read,
452452
};

fs/exfat/file.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,7 @@ const struct file_operations exfat_file_operations = {
389389
#endif
390390
.mmap = generic_file_mmap,
391391
.fsync = exfat_file_fsync,
392-
.splice_read = generic_file_splice_read,
392+
.splice_read = filemap_splice_read,
393393
.splice_write = iter_file_splice_write,
394394
};
395395

fs/ext2/file.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ const struct file_operations ext2_file_operations = {
192192
.release = ext2_release_file,
193193
.fsync = ext2_fsync,
194194
.get_unmapped_area = thp_get_unmapped_area,
195-
.splice_read = generic_file_splice_read,
195+
.splice_read = filemap_splice_read,
196196
.splice_write = iter_file_splice_write,
197197
};
198198

fs/ext4/file.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,17 @@ static ssize_t ext4_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
147147
return generic_file_read_iter(iocb, to);
148148
}
149149

150+
static ssize_t ext4_file_splice_read(struct file *in, loff_t *ppos,
151+
struct pipe_inode_info *pipe,
152+
size_t len, unsigned int flags)
153+
{
154+
struct inode *inode = file_inode(in);
155+
156+
if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
157+
return -EIO;
158+
return filemap_splice_read(in, ppos, pipe, len, flags);
159+
}
160+
150161
/*
151162
* Called when an inode is released. Note that this is different
152163
* from ext4_file_open: open gets called at every open, but release
@@ -957,7 +968,7 @@ const struct file_operations ext4_file_operations = {
957968
.release = ext4_release_file,
958969
.fsync = ext4_sync_file,
959970
.get_unmapped_area = thp_get_unmapped_area,
960-
.splice_read = generic_file_splice_read,
971+
.splice_read = ext4_file_splice_read,
961972
.splice_write = iter_file_splice_write,
962973
.fallocate = ext4_fallocate,
963974
};

0 commit comments

Comments
 (0)