diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-10 16:51:06 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-10 16:51:06 -0400 |
commit | 01370f0603f8435d415a19f7e62d1bab826c3589 (patch) | |
tree | d3ce7c36c6f9e33bd1d8328ef58f2fca41a18cb3 /fs | |
parent | 5cbc39a726eafa1198c18adb3cf56ccee371dba1 (diff) | |
parent | 0845718dafea3e16041d270c256e8516acf4e13d (diff) |
Merge branch 'splice-2.6.23' of git://git.kernel.dk/data/git/linux-2.6-block
* 'splice-2.6.23' of git://git.kernel.dk/data/git/linux-2.6-block:
pipe: add documentation and comments
pipe: change the ->pin() operation to ->confirm()
Remove remnants of sendfile()
xip sendfile removal
splice: completely document external interface with kerneldoc
sendfile: remove bad_sendfile() from bad_file_ops
shmem: convert to using splice instead of sendfile()
relay: use splice_to_pipe() instead of open-coding the pipe loop
pipe: allow passing around of ops private pointer
splice: divorce the splice structure/function definitions from the pipe header
splice: relay support
sendfile: convert nfsd to splice_direct_to_actor()
sendfile: convert nfs to using splice_read()
loop: convert to using splice_direct_to_actor() instead of sendfile()
splice: add void cookie to the actor data
sendfile: kill generic_file_sendfile()
sendfile: remove .sendfile from filesystems that use generic_file_sendfile()
sys_sendfile: switch to using ->splice_read, if available
vmsplice: add vmsplice-to-user support
splice: abstract out actor data
Diffstat (limited to 'fs')
43 files changed, 488 insertions, 276 deletions
diff --git a/fs/adfs/file.c b/fs/adfs/file.c index f544a2855923..36e381c6a99a 100644 --- a/fs/adfs/file.c +++ b/fs/adfs/file.c | |||
@@ -33,7 +33,7 @@ const struct file_operations adfs_file_operations = { | |||
33 | .fsync = file_fsync, | 33 | .fsync = file_fsync, |
34 | .write = do_sync_write, | 34 | .write = do_sync_write, |
35 | .aio_write = generic_file_aio_write, | 35 | .aio_write = generic_file_aio_write, |
36 | .sendfile = generic_file_sendfile, | 36 | .splice_read = generic_file_splice_read, |
37 | }; | 37 | }; |
38 | 38 | ||
39 | const struct inode_operations adfs_file_inode_operations = { | 39 | const struct inode_operations adfs_file_inode_operations = { |
diff --git a/fs/affs/file.c b/fs/affs/file.c index c8796906f584..c314a35f0918 100644 --- a/fs/affs/file.c +++ b/fs/affs/file.c | |||
@@ -35,7 +35,7 @@ const struct file_operations affs_file_operations = { | |||
35 | .open = affs_file_open, | 35 | .open = affs_file_open, |
36 | .release = affs_file_release, | 36 | .release = affs_file_release, |
37 | .fsync = file_fsync, | 37 | .fsync = file_fsync, |
38 | .sendfile = generic_file_sendfile, | 38 | .splice_read = generic_file_splice_read, |
39 | }; | 39 | }; |
40 | 40 | ||
41 | const struct inode_operations affs_file_inode_operations = { | 41 | const struct inode_operations affs_file_inode_operations = { |
diff --git a/fs/afs/file.c b/fs/afs/file.c index 9c0e721d9fc2..aede7eb66dd4 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c | |||
@@ -32,7 +32,7 @@ const struct file_operations afs_file_operations = { | |||
32 | .aio_read = generic_file_aio_read, | 32 | .aio_read = generic_file_aio_read, |
33 | .aio_write = afs_file_write, | 33 | .aio_write = afs_file_write, |
34 | .mmap = generic_file_readonly_mmap, | 34 | .mmap = generic_file_readonly_mmap, |
35 | .sendfile = generic_file_sendfile, | 35 | .splice_read = generic_file_splice_read, |
36 | .fsync = afs_fsync, | 36 | .fsync = afs_fsync, |
37 | }; | 37 | }; |
38 | 38 | ||
diff --git a/fs/bad_inode.c b/fs/bad_inode.c index 329ee473eede..521ff7caadbd 100644 --- a/fs/bad_inode.c +++ b/fs/bad_inode.c | |||
@@ -114,12 +114,6 @@ static int bad_file_lock(struct file *file, int cmd, struct file_lock *fl) | |||
114 | return -EIO; | 114 | return -EIO; |
115 | } | 115 | } |
116 | 116 | ||
117 | static ssize_t bad_file_sendfile(struct file *in_file, loff_t *ppos, | ||
118 | size_t count, read_actor_t actor, void *target) | ||
119 | { | ||
120 | return -EIO; | ||
121 | } | ||
122 | |||
123 | static ssize_t bad_file_sendpage(struct file *file, struct page *page, | 117 | static ssize_t bad_file_sendpage(struct file *file, struct page *page, |
124 | int off, size_t len, loff_t *pos, int more) | 118 | int off, size_t len, loff_t *pos, int more) |
125 | { | 119 | { |
@@ -182,7 +176,6 @@ static const struct file_operations bad_file_ops = | |||
182 | .aio_fsync = bad_file_aio_fsync, | 176 | .aio_fsync = bad_file_aio_fsync, |
183 | .fasync = bad_file_fasync, | 177 | .fasync = bad_file_fasync, |
184 | .lock = bad_file_lock, | 178 | .lock = bad_file_lock, |
185 | .sendfile = bad_file_sendfile, | ||
186 | .sendpage = bad_file_sendpage, | 179 | .sendpage = bad_file_sendpage, |
187 | .get_unmapped_area = bad_file_get_unmapped_area, | 180 | .get_unmapped_area = bad_file_get_unmapped_area, |
188 | .check_flags = bad_file_check_flags, | 181 | .check_flags = bad_file_check_flags, |
diff --git a/fs/bfs/file.c b/fs/bfs/file.c index ef4d1fa04e65..24310e9ee05a 100644 --- a/fs/bfs/file.c +++ b/fs/bfs/file.c | |||
@@ -24,7 +24,7 @@ const struct file_operations bfs_file_operations = { | |||
24 | .write = do_sync_write, | 24 | .write = do_sync_write, |
25 | .aio_write = generic_file_aio_write, | 25 | .aio_write = generic_file_aio_write, |
26 | .mmap = generic_file_mmap, | 26 | .mmap = generic_file_mmap, |
27 | .sendfile = generic_file_sendfile, | 27 | .splice_read = generic_file_splice_read, |
28 | }; | 28 | }; |
29 | 29 | ||
30 | static int bfs_move_block(unsigned long from, unsigned long to, struct super_block *sb) | 30 | static int bfs_move_block(unsigned long from, unsigned long to, struct super_block *sb) |
diff --git a/fs/block_dev.c b/fs/block_dev.c index ea1480a16f51..b3e9bfa748cf 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
@@ -1346,7 +1346,6 @@ const struct file_operations def_blk_fops = { | |||
1346 | #ifdef CONFIG_COMPAT | 1346 | #ifdef CONFIG_COMPAT |
1347 | .compat_ioctl = compat_blkdev_ioctl, | 1347 | .compat_ioctl = compat_blkdev_ioctl, |
1348 | #endif | 1348 | #endif |
1349 | .sendfile = generic_file_sendfile, | ||
1350 | .splice_read = generic_file_splice_read, | 1349 | .splice_read = generic_file_splice_read, |
1351 | .splice_write = generic_file_splice_write, | 1350 | .splice_write = generic_file_splice_write, |
1352 | }; | 1351 | }; |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 7c04752b76cb..8b0cbf4a4ad0 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -616,7 +616,7 @@ const struct file_operations cifs_file_ops = { | |||
616 | .fsync = cifs_fsync, | 616 | .fsync = cifs_fsync, |
617 | .flush = cifs_flush, | 617 | .flush = cifs_flush, |
618 | .mmap = cifs_file_mmap, | 618 | .mmap = cifs_file_mmap, |
619 | .sendfile = generic_file_sendfile, | 619 | .splice_read = generic_file_splice_read, |
620 | .llseek = cifs_llseek, | 620 | .llseek = cifs_llseek, |
621 | #ifdef CONFIG_CIFS_POSIX | 621 | #ifdef CONFIG_CIFS_POSIX |
622 | .ioctl = cifs_ioctl, | 622 | .ioctl = cifs_ioctl, |
@@ -637,7 +637,7 @@ const struct file_operations cifs_file_direct_ops = { | |||
637 | .lock = cifs_lock, | 637 | .lock = cifs_lock, |
638 | .fsync = cifs_fsync, | 638 | .fsync = cifs_fsync, |
639 | .flush = cifs_flush, | 639 | .flush = cifs_flush, |
640 | .sendfile = generic_file_sendfile, /* BB removeme BB */ | 640 | .splice_read = generic_file_splice_read, |
641 | #ifdef CONFIG_CIFS_POSIX | 641 | #ifdef CONFIG_CIFS_POSIX |
642 | .ioctl = cifs_ioctl, | 642 | .ioctl = cifs_ioctl, |
643 | #endif /* CONFIG_CIFS_POSIX */ | 643 | #endif /* CONFIG_CIFS_POSIX */ |
@@ -656,7 +656,7 @@ const struct file_operations cifs_file_nobrl_ops = { | |||
656 | .fsync = cifs_fsync, | 656 | .fsync = cifs_fsync, |
657 | .flush = cifs_flush, | 657 | .flush = cifs_flush, |
658 | .mmap = cifs_file_mmap, | 658 | .mmap = cifs_file_mmap, |
659 | .sendfile = generic_file_sendfile, | 659 | .splice_read = generic_file_splice_read, |
660 | .llseek = cifs_llseek, | 660 | .llseek = cifs_llseek, |
661 | #ifdef CONFIG_CIFS_POSIX | 661 | #ifdef CONFIG_CIFS_POSIX |
662 | .ioctl = cifs_ioctl, | 662 | .ioctl = cifs_ioctl, |
@@ -676,7 +676,7 @@ const struct file_operations cifs_file_direct_nobrl_ops = { | |||
676 | .release = cifs_close, | 676 | .release = cifs_close, |
677 | .fsync = cifs_fsync, | 677 | .fsync = cifs_fsync, |
678 | .flush = cifs_flush, | 678 | .flush = cifs_flush, |
679 | .sendfile = generic_file_sendfile, /* BB removeme BB */ | 679 | .splice_read = generic_file_splice_read, |
680 | #ifdef CONFIG_CIFS_POSIX | 680 | #ifdef CONFIG_CIFS_POSIX |
681 | .ioctl = cifs_ioctl, | 681 | .ioctl = cifs_ioctl, |
682 | #endif /* CONFIG_CIFS_POSIX */ | 682 | #endif /* CONFIG_CIFS_POSIX */ |
diff --git a/fs/coda/file.c b/fs/coda/file.c index 5ef2b609ec7d..99dbe866816d 100644 --- a/fs/coda/file.c +++ b/fs/coda/file.c | |||
@@ -47,8 +47,9 @@ coda_file_read(struct file *coda_file, char __user *buf, size_t count, loff_t *p | |||
47 | } | 47 | } |
48 | 48 | ||
49 | static ssize_t | 49 | static ssize_t |
50 | coda_file_sendfile(struct file *coda_file, loff_t *ppos, size_t count, | 50 | coda_file_splice_read(struct file *coda_file, loff_t *ppos, |
51 | read_actor_t actor, void *target) | 51 | struct pipe_inode_info *pipe, size_t count, |
52 | unsigned int flags) | ||
52 | { | 53 | { |
53 | struct coda_file_info *cfi; | 54 | struct coda_file_info *cfi; |
54 | struct file *host_file; | 55 | struct file *host_file; |
@@ -57,10 +58,10 @@ coda_file_sendfile(struct file *coda_file, loff_t *ppos, size_t count, | |||
57 | BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC); | 58 | BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC); |
58 | host_file = cfi->cfi_container; | 59 | host_file = cfi->cfi_container; |
59 | 60 | ||
60 | if (!host_file->f_op || !host_file->f_op->sendfile) | 61 | if (!host_file->f_op || !host_file->f_op->splice_read) |
61 | return -EINVAL; | 62 | return -EINVAL; |
62 | 63 | ||
63 | return host_file->f_op->sendfile(host_file, ppos, count, actor, target); | 64 | return host_file->f_op->splice_read(host_file, ppos, pipe, count,flags); |
64 | } | 65 | } |
65 | 66 | ||
66 | static ssize_t | 67 | static ssize_t |
@@ -295,6 +296,6 @@ const struct file_operations coda_file_operations = { | |||
295 | .flush = coda_flush, | 296 | .flush = coda_flush, |
296 | .release = coda_release, | 297 | .release = coda_release, |
297 | .fsync = coda_fsync, | 298 | .fsync = coda_fsync, |
298 | .sendfile = coda_file_sendfile, | 299 | .splice_read = coda_file_splice_read, |
299 | }; | 300 | }; |
300 | 301 | ||
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c index 59288d817078..94f456fe4d9b 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c | |||
@@ -338,16 +338,17 @@ static int ecryptfs_fasync(int fd, struct file *file, int flag) | |||
338 | return rc; | 338 | return rc; |
339 | } | 339 | } |
340 | 340 | ||
341 | static ssize_t ecryptfs_sendfile(struct file *file, loff_t * ppos, | 341 | static ssize_t ecryptfs_splice_read(struct file *file, loff_t * ppos, |
342 | size_t count, read_actor_t actor, void *target) | 342 | struct pipe_inode_info *pipe, size_t count, |
343 | unsigned int flags) | ||
343 | { | 344 | { |
344 | struct file *lower_file = NULL; | 345 | struct file *lower_file = NULL; |
345 | int rc = -EINVAL; | 346 | int rc = -EINVAL; |
346 | 347 | ||
347 | lower_file = ecryptfs_file_to_lower(file); | 348 | lower_file = ecryptfs_file_to_lower(file); |
348 | if (lower_file->f_op && lower_file->f_op->sendfile) | 349 | if (lower_file->f_op && lower_file->f_op->splice_read) |
349 | rc = lower_file->f_op->sendfile(lower_file, ppos, count, | 350 | rc = lower_file->f_op->splice_read(lower_file, ppos, pipe, |
350 | actor, target); | 351 | count, flags); |
351 | 352 | ||
352 | return rc; | 353 | return rc; |
353 | } | 354 | } |
@@ -364,7 +365,7 @@ const struct file_operations ecryptfs_dir_fops = { | |||
364 | .release = ecryptfs_release, | 365 | .release = ecryptfs_release, |
365 | .fsync = ecryptfs_fsync, | 366 | .fsync = ecryptfs_fsync, |
366 | .fasync = ecryptfs_fasync, | 367 | .fasync = ecryptfs_fasync, |
367 | .sendfile = ecryptfs_sendfile, | 368 | .splice_read = ecryptfs_splice_read, |
368 | }; | 369 | }; |
369 | 370 | ||
370 | const struct file_operations ecryptfs_main_fops = { | 371 | const struct file_operations ecryptfs_main_fops = { |
@@ -381,7 +382,7 @@ const struct file_operations ecryptfs_main_fops = { | |||
381 | .release = ecryptfs_release, | 382 | .release = ecryptfs_release, |
382 | .fsync = ecryptfs_fsync, | 383 | .fsync = ecryptfs_fsync, |
383 | .fasync = ecryptfs_fasync, | 384 | .fasync = ecryptfs_fasync, |
384 | .sendfile = ecryptfs_sendfile, | 385 | .splice_read = ecryptfs_splice_read, |
385 | }; | 386 | }; |
386 | 387 | ||
387 | static int | 388 | static int |
diff --git a/fs/ext2/file.c b/fs/ext2/file.c index 566d4e2d3852..04afeecaaef3 100644 --- a/fs/ext2/file.c +++ b/fs/ext2/file.c | |||
@@ -53,7 +53,6 @@ const struct file_operations ext2_file_operations = { | |||
53 | .open = generic_file_open, | 53 | .open = generic_file_open, |
54 | .release = ext2_release_file, | 54 | .release = ext2_release_file, |
55 | .fsync = ext2_sync_file, | 55 | .fsync = ext2_sync_file, |
56 | .sendfile = generic_file_sendfile, | ||
57 | .splice_read = generic_file_splice_read, | 56 | .splice_read = generic_file_splice_read, |
58 | .splice_write = generic_file_splice_write, | 57 | .splice_write = generic_file_splice_write, |
59 | }; | 58 | }; |
@@ -71,7 +70,6 @@ const struct file_operations ext2_xip_file_operations = { | |||
71 | .open = generic_file_open, | 70 | .open = generic_file_open, |
72 | .release = ext2_release_file, | 71 | .release = ext2_release_file, |
73 | .fsync = ext2_sync_file, | 72 | .fsync = ext2_sync_file, |
74 | .sendfile = xip_file_sendfile, | ||
75 | }; | 73 | }; |
76 | #endif | 74 | #endif |
77 | 75 | ||
diff --git a/fs/ext3/file.c b/fs/ext3/file.c index 1e6f13864536..acc4913d3019 100644 --- a/fs/ext3/file.c +++ b/fs/ext3/file.c | |||
@@ -120,7 +120,6 @@ const struct file_operations ext3_file_operations = { | |||
120 | .open = generic_file_open, | 120 | .open = generic_file_open, |
121 | .release = ext3_release_file, | 121 | .release = ext3_release_file, |
122 | .fsync = ext3_sync_file, | 122 | .fsync = ext3_sync_file, |
123 | .sendfile = generic_file_sendfile, | ||
124 | .splice_read = generic_file_splice_read, | 123 | .splice_read = generic_file_splice_read, |
125 | .splice_write = generic_file_splice_write, | 124 | .splice_write = generic_file_splice_write, |
126 | }; | 125 | }; |
diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 3c6c1fd2be90..d4c8186aed64 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c | |||
@@ -120,7 +120,6 @@ const struct file_operations ext4_file_operations = { | |||
120 | .open = generic_file_open, | 120 | .open = generic_file_open, |
121 | .release = ext4_release_file, | 121 | .release = ext4_release_file, |
122 | .fsync = ext4_sync_file, | 122 | .fsync = ext4_sync_file, |
123 | .sendfile = generic_file_sendfile, | ||
124 | .splice_read = generic_file_splice_read, | 123 | .splice_read = generic_file_splice_read, |
125 | .splice_write = generic_file_splice_write, | 124 | .splice_write = generic_file_splice_write, |
126 | }; | 125 | }; |
diff --git a/fs/fat/file.c b/fs/fat/file.c index 55d3c7461c5b..69a83b59dce8 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c | |||
@@ -134,7 +134,7 @@ const struct file_operations fat_file_operations = { | |||
134 | .release = fat_file_release, | 134 | .release = fat_file_release, |
135 | .ioctl = fat_generic_ioctl, | 135 | .ioctl = fat_generic_ioctl, |
136 | .fsync = file_fsync, | 136 | .fsync = file_fsync, |
137 | .sendfile = generic_file_sendfile, | 137 | .splice_read = generic_file_splice_read, |
138 | }; | 138 | }; |
139 | 139 | ||
140 | static int fat_cont_expand(struct inode *inode, loff_t size) | 140 | static int fat_cont_expand(struct inode *inode, loff_t size) |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index adf7995232b8..f79de7c8cdfa 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -802,7 +802,7 @@ static const struct file_operations fuse_file_operations = { | |||
802 | .release = fuse_release, | 802 | .release = fuse_release, |
803 | .fsync = fuse_fsync, | 803 | .fsync = fuse_fsync, |
804 | .lock = fuse_file_lock, | 804 | .lock = fuse_file_lock, |
805 | .sendfile = generic_file_sendfile, | 805 | .splice_read = generic_file_splice_read, |
806 | }; | 806 | }; |
807 | 807 | ||
808 | static const struct file_operations fuse_direct_io_file_operations = { | 808 | static const struct file_operations fuse_direct_io_file_operations = { |
@@ -814,7 +814,7 @@ static const struct file_operations fuse_direct_io_file_operations = { | |||
814 | .release = fuse_release, | 814 | .release = fuse_release, |
815 | .fsync = fuse_fsync, | 815 | .fsync = fuse_fsync, |
816 | .lock = fuse_file_lock, | 816 | .lock = fuse_file_lock, |
817 | /* no mmap and sendfile */ | 817 | /* no mmap and splice_read */ |
818 | }; | 818 | }; |
819 | 819 | ||
820 | static const struct address_space_operations fuse_file_aops = { | 820 | static const struct address_space_operations fuse_file_aops = { |
diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c index 064df8804582..7dc3be108204 100644 --- a/fs/gfs2/ops_file.c +++ b/fs/gfs2/ops_file.c | |||
@@ -635,7 +635,6 @@ const struct file_operations gfs2_file_fops = { | |||
635 | .release = gfs2_close, | 635 | .release = gfs2_close, |
636 | .fsync = gfs2_fsync, | 636 | .fsync = gfs2_fsync, |
637 | .lock = gfs2_lock, | 637 | .lock = gfs2_lock, |
638 | .sendfile = generic_file_sendfile, | ||
639 | .flock = gfs2_flock, | 638 | .flock = gfs2_flock, |
640 | .splice_read = generic_file_splice_read, | 639 | .splice_read = generic_file_splice_read, |
641 | .splice_write = generic_file_splice_write, | 640 | .splice_write = generic_file_splice_write, |
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c index 9a934db0bd8a..bc835f272a6e 100644 --- a/fs/hfs/inode.c +++ b/fs/hfs/inode.c | |||
@@ -607,7 +607,7 @@ static const struct file_operations hfs_file_operations = { | |||
607 | .write = do_sync_write, | 607 | .write = do_sync_write, |
608 | .aio_write = generic_file_aio_write, | 608 | .aio_write = generic_file_aio_write, |
609 | .mmap = generic_file_mmap, | 609 | .mmap = generic_file_mmap, |
610 | .sendfile = generic_file_sendfile, | 610 | .splice_read = generic_file_splice_read, |
611 | .fsync = file_fsync, | 611 | .fsync = file_fsync, |
612 | .open = hfs_file_open, | 612 | .open = hfs_file_open, |
613 | .release = hfs_file_release, | 613 | .release = hfs_file_release, |
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index 45dab5d6cc10..409ce5429c91 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c | |||
@@ -288,7 +288,7 @@ static const struct file_operations hfsplus_file_operations = { | |||
288 | .write = do_sync_write, | 288 | .write = do_sync_write, |
289 | .aio_write = generic_file_aio_write, | 289 | .aio_write = generic_file_aio_write, |
290 | .mmap = generic_file_mmap, | 290 | .mmap = generic_file_mmap, |
291 | .sendfile = generic_file_sendfile, | 291 | .splice_read = generic_file_splice_read, |
292 | .fsync = file_fsync, | 292 | .fsync = file_fsync, |
293 | .open = hfsplus_file_open, | 293 | .open = hfsplus_file_open, |
294 | .release = hfsplus_file_release, | 294 | .release = hfsplus_file_release, |
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index 8286491dbf31..c77862032e84 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c | |||
@@ -390,7 +390,7 @@ int hostfs_fsync(struct file *file, struct dentry *dentry, int datasync) | |||
390 | static const struct file_operations hostfs_file_fops = { | 390 | static const struct file_operations hostfs_file_fops = { |
391 | .llseek = generic_file_llseek, | 391 | .llseek = generic_file_llseek, |
392 | .read = do_sync_read, | 392 | .read = do_sync_read, |
393 | .sendfile = generic_file_sendfile, | 393 | .splice_read = generic_file_splice_read, |
394 | .aio_read = generic_file_aio_read, | 394 | .aio_read = generic_file_aio_read, |
395 | .aio_write = generic_file_aio_write, | 395 | .aio_write = generic_file_aio_write, |
396 | .write = do_sync_write, | 396 | .write = do_sync_write, |
diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c index b4eafc0f1e54..5b53e5c5d8df 100644 --- a/fs/hpfs/file.c +++ b/fs/hpfs/file.c | |||
@@ -129,7 +129,7 @@ const struct file_operations hpfs_file_ops = | |||
129 | .mmap = generic_file_mmap, | 129 | .mmap = generic_file_mmap, |
130 | .release = hpfs_file_release, | 130 | .release = hpfs_file_release, |
131 | .fsync = hpfs_file_fsync, | 131 | .fsync = hpfs_file_fsync, |
132 | .sendfile = generic_file_sendfile, | 132 | .splice_read = generic_file_splice_read, |
133 | }; | 133 | }; |
134 | 134 | ||
135 | const struct inode_operations hpfs_file_iops = | 135 | const struct inode_operations hpfs_file_iops = |
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c index 99871279a1ed..c2530197be0c 100644 --- a/fs/jffs2/file.c +++ b/fs/jffs2/file.c | |||
@@ -47,7 +47,7 @@ const struct file_operations jffs2_file_operations = | |||
47 | .ioctl = jffs2_ioctl, | 47 | .ioctl = jffs2_ioctl, |
48 | .mmap = generic_file_readonly_mmap, | 48 | .mmap = generic_file_readonly_mmap, |
49 | .fsync = jffs2_fsync, | 49 | .fsync = jffs2_fsync, |
50 | .sendfile = generic_file_sendfile | 50 | .splice_read = generic_file_splice_read, |
51 | }; | 51 | }; |
52 | 52 | ||
53 | /* jffs2_file_inode_operations */ | 53 | /* jffs2_file_inode_operations */ |
diff --git a/fs/jfs/file.c b/fs/jfs/file.c index f7f8eff19b7b..87eb93694af7 100644 --- a/fs/jfs/file.c +++ b/fs/jfs/file.c | |||
@@ -108,7 +108,6 @@ const struct file_operations jfs_file_operations = { | |||
108 | .aio_read = generic_file_aio_read, | 108 | .aio_read = generic_file_aio_read, |
109 | .aio_write = generic_file_aio_write, | 109 | .aio_write = generic_file_aio_write, |
110 | .mmap = generic_file_mmap, | 110 | .mmap = generic_file_mmap, |
111 | .sendfile = generic_file_sendfile, | ||
112 | .splice_read = generic_file_splice_read, | 111 | .splice_read = generic_file_splice_read, |
113 | .splice_write = generic_file_splice_write, | 112 | .splice_write = generic_file_splice_write, |
114 | .fsync = jfs_fsync, | 113 | .fsync = jfs_fsync, |
diff --git a/fs/minix/file.c b/fs/minix/file.c index f92baa1d7570..17765f697e50 100644 --- a/fs/minix/file.c +++ b/fs/minix/file.c | |||
@@ -23,7 +23,7 @@ const struct file_operations minix_file_operations = { | |||
23 | .aio_write = generic_file_aio_write, | 23 | .aio_write = generic_file_aio_write, |
24 | .mmap = generic_file_mmap, | 24 | .mmap = generic_file_mmap, |
25 | .fsync = minix_sync_file, | 25 | .fsync = minix_sync_file, |
26 | .sendfile = generic_file_sendfile, | 26 | .splice_read = generic_file_splice_read, |
27 | }; | 27 | }; |
28 | 28 | ||
29 | const struct inode_operations minix_file_inode_operations = { | 29 | const struct inode_operations minix_file_inode_operations = { |
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 9eb8eb4e4a08..8689b736fdd9 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -41,7 +41,9 @@ static int nfs_file_open(struct inode *, struct file *); | |||
41 | static int nfs_file_release(struct inode *, struct file *); | 41 | static int nfs_file_release(struct inode *, struct file *); |
42 | static loff_t nfs_file_llseek(struct file *file, loff_t offset, int origin); | 42 | static loff_t nfs_file_llseek(struct file *file, loff_t offset, int origin); |
43 | static int nfs_file_mmap(struct file *, struct vm_area_struct *); | 43 | static int nfs_file_mmap(struct file *, struct vm_area_struct *); |
44 | static ssize_t nfs_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *); | 44 | static ssize_t nfs_file_splice_read(struct file *filp, loff_t *ppos, |
45 | struct pipe_inode_info *pipe, | ||
46 | size_t count, unsigned int flags); | ||
45 | static ssize_t nfs_file_read(struct kiocb *, const struct iovec *iov, | 47 | static ssize_t nfs_file_read(struct kiocb *, const struct iovec *iov, |
46 | unsigned long nr_segs, loff_t pos); | 48 | unsigned long nr_segs, loff_t pos); |
47 | static ssize_t nfs_file_write(struct kiocb *, const struct iovec *iov, | 49 | static ssize_t nfs_file_write(struct kiocb *, const struct iovec *iov, |
@@ -65,7 +67,7 @@ const struct file_operations nfs_file_operations = { | |||
65 | .fsync = nfs_fsync, | 67 | .fsync = nfs_fsync, |
66 | .lock = nfs_lock, | 68 | .lock = nfs_lock, |
67 | .flock = nfs_flock, | 69 | .flock = nfs_flock, |
68 | .sendfile = nfs_file_sendfile, | 70 | .splice_read = nfs_file_splice_read, |
69 | .check_flags = nfs_check_flags, | 71 | .check_flags = nfs_check_flags, |
70 | }; | 72 | }; |
71 | 73 | ||
@@ -224,20 +226,21 @@ nfs_file_read(struct kiocb *iocb, const struct iovec *iov, | |||
224 | } | 226 | } |
225 | 227 | ||
226 | static ssize_t | 228 | static ssize_t |
227 | nfs_file_sendfile(struct file *filp, loff_t *ppos, size_t count, | 229 | nfs_file_splice_read(struct file *filp, loff_t *ppos, |
228 | read_actor_t actor, void *target) | 230 | struct pipe_inode_info *pipe, size_t count, |
231 | unsigned int flags) | ||
229 | { | 232 | { |
230 | struct dentry *dentry = filp->f_path.dentry; | 233 | struct dentry *dentry = filp->f_path.dentry; |
231 | struct inode *inode = dentry->d_inode; | 234 | struct inode *inode = dentry->d_inode; |
232 | ssize_t res; | 235 | ssize_t res; |
233 | 236 | ||
234 | dfprintk(VFS, "nfs: sendfile(%s/%s, %lu@%Lu)\n", | 237 | dfprintk(VFS, "nfs: splice_read(%s/%s, %lu@%Lu)\n", |
235 | dentry->d_parent->d_name.name, dentry->d_name.name, | 238 | dentry->d_parent->d_name.name, dentry->d_name.name, |
236 | (unsigned long) count, (unsigned long long) *ppos); | 239 | (unsigned long) count, (unsigned long long) *ppos); |
237 | 240 | ||
238 | res = nfs_revalidate_mapping(inode, filp->f_mapping); | 241 | res = nfs_revalidate_mapping(inode, filp->f_mapping); |
239 | if (!res) | 242 | if (!res) |
240 | res = generic_file_sendfile(filp, ppos, count, actor, target); | 243 | res = generic_file_splice_read(filp, ppos, pipe, count, flags); |
241 | return res; | 244 | return res; |
242 | } | 245 | } |
243 | 246 | ||
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 7e6aa245b5d5..8604e35bd48e 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -23,7 +23,7 @@ | |||
23 | #include <linux/file.h> | 23 | #include <linux/file.h> |
24 | #include <linux/mount.h> | 24 | #include <linux/mount.h> |
25 | #include <linux/major.h> | 25 | #include <linux/major.h> |
26 | #include <linux/ext2_fs.h> | 26 | #include <linux/splice.h> |
27 | #include <linux/proc_fs.h> | 27 | #include <linux/proc_fs.h> |
28 | #include <linux/stat.h> | 28 | #include <linux/stat.h> |
29 | #include <linux/fcntl.h> | 29 | #include <linux/fcntl.h> |
@@ -801,26 +801,32 @@ found: | |||
801 | } | 801 | } |
802 | 802 | ||
803 | /* | 803 | /* |
804 | * Grab and keep cached pages assosiated with a file in the svc_rqst | 804 | * Grab and keep cached pages associated with a file in the svc_rqst |
805 | * so that they can be passed to the netowork sendmsg/sendpage routines | 805 | * so that they can be passed to the network sendmsg/sendpage routines |
806 | * directrly. They will be released after the sending has completed. | 806 | * directly. They will be released after the sending has completed. |
807 | */ | 807 | */ |
808 | static int | 808 | static int |
809 | nfsd_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset , unsigned long size) | 809 | nfsd_splice_actor(struct pipe_inode_info *pipe, struct pipe_buffer *buf, |
810 | struct splice_desc *sd) | ||
810 | { | 811 | { |
811 | unsigned long count = desc->count; | 812 | struct svc_rqst *rqstp = sd->u.data; |
812 | struct svc_rqst *rqstp = desc->arg.data; | ||
813 | struct page **pp = rqstp->rq_respages + rqstp->rq_resused; | 813 | struct page **pp = rqstp->rq_respages + rqstp->rq_resused; |
814 | struct page *page = buf->page; | ||
815 | size_t size; | ||
816 | int ret; | ||
817 | |||
818 | ret = buf->ops->confirm(pipe, buf); | ||
819 | if (unlikely(ret)) | ||
820 | return ret; | ||
814 | 821 | ||
815 | if (size > count) | 822 | size = sd->len; |
816 | size = count; | ||
817 | 823 | ||
818 | if (rqstp->rq_res.page_len == 0) { | 824 | if (rqstp->rq_res.page_len == 0) { |
819 | get_page(page); | 825 | get_page(page); |
820 | put_page(*pp); | 826 | put_page(*pp); |
821 | *pp = page; | 827 | *pp = page; |
822 | rqstp->rq_resused++; | 828 | rqstp->rq_resused++; |
823 | rqstp->rq_res.page_base = offset; | 829 | rqstp->rq_res.page_base = buf->offset; |
824 | rqstp->rq_res.page_len = size; | 830 | rqstp->rq_res.page_len = size; |
825 | } else if (page != pp[-1]) { | 831 | } else if (page != pp[-1]) { |
826 | get_page(page); | 832 | get_page(page); |
@@ -832,11 +838,15 @@ nfsd_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset | |||
832 | } else | 838 | } else |
833 | rqstp->rq_res.page_len += size; | 839 | rqstp->rq_res.page_len += size; |
834 | 840 | ||
835 | desc->count = count - size; | ||
836 | desc->written += size; | ||
837 | return size; | 841 | return size; |
838 | } | 842 | } |
839 | 843 | ||
844 | static int nfsd_direct_splice_actor(struct pipe_inode_info *pipe, | ||
845 | struct splice_desc *sd) | ||
846 | { | ||
847 | return __splice_from_pipe(pipe, sd, nfsd_splice_actor); | ||
848 | } | ||
849 | |||
840 | static __be32 | 850 | static __be32 |
841 | nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | 851 | nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, |
842 | loff_t offset, struct kvec *vec, int vlen, unsigned long *count) | 852 | loff_t offset, struct kvec *vec, int vlen, unsigned long *count) |
@@ -861,10 +871,15 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | |||
861 | if (ra && ra->p_set) | 871 | if (ra && ra->p_set) |
862 | file->f_ra = ra->p_ra; | 872 | file->f_ra = ra->p_ra; |
863 | 873 | ||
864 | if (file->f_op->sendfile && rqstp->rq_sendfile_ok) { | 874 | if (file->f_op->splice_read && rqstp->rq_splice_ok) { |
865 | rqstp->rq_resused = 1; | 875 | struct splice_desc sd = { |
866 | host_err = file->f_op->sendfile(file, &offset, *count, | 876 | .len = 0, |
867 | nfsd_read_actor, rqstp); | 877 | .total_len = *count, |
878 | .pos = offset, | ||
879 | .u.data = rqstp, | ||
880 | }; | ||
881 | |||
882 | host_err = splice_direct_to_actor(file, &sd, nfsd_direct_splice_actor); | ||
868 | } else { | 883 | } else { |
869 | oldfs = get_fs(); | 884 | oldfs = get_fs(); |
870 | set_fs(KERNEL_DS); | 885 | set_fs(KERNEL_DS); |
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c index 7ed56390b582..ffcc504a1667 100644 --- a/fs/ntfs/file.c +++ b/fs/ntfs/file.c | |||
@@ -2276,7 +2276,7 @@ const struct file_operations ntfs_file_ops = { | |||
2276 | mounted filesystem. */ | 2276 | mounted filesystem. */ |
2277 | .mmap = generic_file_mmap, /* Mmap file. */ | 2277 | .mmap = generic_file_mmap, /* Mmap file. */ |
2278 | .open = ntfs_file_open, /* Open file. */ | 2278 | .open = ntfs_file_open, /* Open file. */ |
2279 | .sendfile = generic_file_sendfile, /* Zero-copy data send with | 2279 | .splice_read = generic_file_splice_read /* Zero-copy data send with |
2280 | the data source being on | 2280 | the data source being on |
2281 | the ntfs partition. We do | 2281 | the ntfs partition. We do |
2282 | not need to care about the | 2282 | not need to care about the |
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index ac6c96431bbc..4979b6675717 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
@@ -31,7 +31,7 @@ | |||
31 | #include <linux/pagemap.h> | 31 | #include <linux/pagemap.h> |
32 | #include <linux/uio.h> | 32 | #include <linux/uio.h> |
33 | #include <linux/sched.h> | 33 | #include <linux/sched.h> |
34 | #include <linux/pipe_fs_i.h> | 34 | #include <linux/splice.h> |
35 | #include <linux/mount.h> | 35 | #include <linux/mount.h> |
36 | #include <linux/writeback.h> | 36 | #include <linux/writeback.h> |
37 | 37 | ||
@@ -1583,7 +1583,7 @@ static int ocfs2_splice_write_actor(struct pipe_inode_info *pipe, | |||
1583 | ssize_t copied = 0; | 1583 | ssize_t copied = 0; |
1584 | struct ocfs2_splice_write_priv sp; | 1584 | struct ocfs2_splice_write_priv sp; |
1585 | 1585 | ||
1586 | ret = buf->ops->pin(pipe, buf); | 1586 | ret = buf->ops->confirm(pipe, buf); |
1587 | if (ret) | 1587 | if (ret) |
1588 | goto out; | 1588 | goto out; |
1589 | 1589 | ||
@@ -1604,7 +1604,7 @@ static int ocfs2_splice_write_actor(struct pipe_inode_info *pipe, | |||
1604 | * might enter ocfs2_buffered_write_cluster() more | 1604 | * might enter ocfs2_buffered_write_cluster() more |
1605 | * than once, so keep track of our progress here. | 1605 | * than once, so keep track of our progress here. |
1606 | */ | 1606 | */ |
1607 | copied = ocfs2_buffered_write_cluster(sd->file, | 1607 | copied = ocfs2_buffered_write_cluster(sd->u.file, |
1608 | (loff_t)sd->pos + total, | 1608 | (loff_t)sd->pos + total, |
1609 | count, | 1609 | count, |
1610 | ocfs2_map_and_write_splice_data, | 1610 | ocfs2_map_and_write_splice_data, |
@@ -1636,9 +1636,14 @@ static ssize_t __ocfs2_file_splice_write(struct pipe_inode_info *pipe, | |||
1636 | int ret, err; | 1636 | int ret, err; |
1637 | struct address_space *mapping = out->f_mapping; | 1637 | struct address_space *mapping = out->f_mapping; |
1638 | struct inode *inode = mapping->host; | 1638 | struct inode *inode = mapping->host; |
1639 | 1639 | struct splice_desc sd = { | |
1640 | ret = __splice_from_pipe(pipe, out, ppos, len, flags, | 1640 | .total_len = len, |
1641 | ocfs2_splice_write_actor); | 1641 | .flags = flags, |
1642 | .pos = *ppos, | ||
1643 | .u.file = out, | ||
1644 | }; | ||
1645 | |||
1646 | ret = __splice_from_pipe(pipe, &sd, ocfs2_splice_write_actor); | ||
1642 | if (ret > 0) { | 1647 | if (ret > 0) { |
1643 | *ppos += ret; | 1648 | *ppos += ret; |
1644 | 1649 | ||
@@ -1817,7 +1822,6 @@ const struct inode_operations ocfs2_special_file_iops = { | |||
1817 | const struct file_operations ocfs2_fops = { | 1822 | const struct file_operations ocfs2_fops = { |
1818 | .read = do_sync_read, | 1823 | .read = do_sync_read, |
1819 | .write = do_sync_write, | 1824 | .write = do_sync_write, |
1820 | .sendfile = generic_file_sendfile, | ||
1821 | .mmap = ocfs2_mmap, | 1825 | .mmap = ocfs2_mmap, |
1822 | .fsync = ocfs2_sync_file, | 1826 | .fsync = ocfs2_sync_file, |
1823 | .release = ocfs2_file_release, | 1827 | .release = ocfs2_file_release, |
@@ -164,6 +164,20 @@ static void anon_pipe_buf_release(struct pipe_inode_info *pipe, | |||
164 | page_cache_release(page); | 164 | page_cache_release(page); |
165 | } | 165 | } |
166 | 166 | ||
167 | /** | ||
168 | * generic_pipe_buf_map - virtually map a pipe buffer | ||
169 | * @pipe: the pipe that the buffer belongs to | ||
170 | * @buf: the buffer that should be mapped | ||
171 | * @atomic: whether to use an atomic map | ||
172 | * | ||
173 | * Description: | ||
174 | * This function returns a kernel virtual address mapping for the | ||
175 | * passed in @pipe_buffer. If @atomic is set, an atomic map is provided | ||
176 | * and the caller has to be careful not to fault before calling | ||
177 | * the unmap function. | ||
178 | * | ||
179 | * Note that this function occupies KM_USER0 if @atomic != 0. | ||
180 | */ | ||
167 | void *generic_pipe_buf_map(struct pipe_inode_info *pipe, | 181 | void *generic_pipe_buf_map(struct pipe_inode_info *pipe, |
168 | struct pipe_buffer *buf, int atomic) | 182 | struct pipe_buffer *buf, int atomic) |
169 | { | 183 | { |
@@ -175,6 +189,15 @@ void *generic_pipe_buf_map(struct pipe_inode_info *pipe, | |||
175 | return kmap(buf->page); | 189 | return kmap(buf->page); |
176 | } | 190 | } |
177 | 191 | ||
192 | /** | ||
193 | * generic_pipe_buf_unmap - unmap a previously mapped pipe buffer | ||
194 | * @pipe: the pipe that the buffer belongs to | ||
195 | * @buf: the buffer that should be unmapped | ||
196 | * @map_data: the data that the mapping function returned | ||
197 | * | ||
198 | * Description: | ||
199 | * This function undoes the mapping that ->map() provided. | ||
200 | */ | ||
178 | void generic_pipe_buf_unmap(struct pipe_inode_info *pipe, | 201 | void generic_pipe_buf_unmap(struct pipe_inode_info *pipe, |
179 | struct pipe_buffer *buf, void *map_data) | 202 | struct pipe_buffer *buf, void *map_data) |
180 | { | 203 | { |
@@ -185,11 +208,28 @@ void generic_pipe_buf_unmap(struct pipe_inode_info *pipe, | |||
185 | kunmap(buf->page); | 208 | kunmap(buf->page); |
186 | } | 209 | } |
187 | 210 | ||
211 | /** | ||
212 | * generic_pipe_buf_steal - attempt to take ownership of a @pipe_buffer | ||
213 | * @pipe: the pipe that the buffer belongs to | ||
214 | * @buf: the buffer to attempt to steal | ||
215 | * | ||
216 | * Description: | ||
217 | * This function attempts to steal the @struct page attached to | ||
218 | * @buf. If successful, this function returns 0 and returns with | ||
219 | * the page locked. The caller may then reuse the page for whatever | ||
220 | * he wishes, the typical use is insertion into a different file | ||
221 | * page cache. | ||
222 | */ | ||
188 | int generic_pipe_buf_steal(struct pipe_inode_info *pipe, | 223 | int generic_pipe_buf_steal(struct pipe_inode_info *pipe, |
189 | struct pipe_buffer *buf) | 224 | struct pipe_buffer *buf) |
190 | { | 225 | { |
191 | struct page *page = buf->page; | 226 | struct page *page = buf->page; |
192 | 227 | ||
228 | /* | ||
229 | * A reference of one is golden, that means that the owner of this | ||
230 | * page is the only one holding a reference to it. lock the page | ||
231 | * and return OK. | ||
232 | */ | ||
193 | if (page_count(page) == 1) { | 233 | if (page_count(page) == 1) { |
194 | lock_page(page); | 234 | lock_page(page); |
195 | return 0; | 235 | return 0; |
@@ -198,12 +238,32 @@ int generic_pipe_buf_steal(struct pipe_inode_info *pipe, | |||
198 | return 1; | 238 | return 1; |
199 | } | 239 | } |
200 | 240 | ||
201 | void generic_pipe_buf_get(struct pipe_inode_info *info, struct pipe_buffer *buf) | 241 | /** |
242 | * generic_pipe_buf_get - get a reference to a @struct pipe_buffer | ||
243 | * @pipe: the pipe that the buffer belongs to | ||
244 | * @buf: the buffer to get a reference to | ||
245 | * | ||
246 | * Description: | ||
247 | * This function grabs an extra reference to @buf. It's used in | ||
248 | * in the tee() system call, when we duplicate the buffers in one | ||
249 | * pipe into another. | ||
250 | */ | ||
251 | void generic_pipe_buf_get(struct pipe_inode_info *pipe, struct pipe_buffer *buf) | ||
202 | { | 252 | { |
203 | page_cache_get(buf->page); | 253 | page_cache_get(buf->page); |
204 | } | 254 | } |
205 | 255 | ||
206 | int generic_pipe_buf_pin(struct pipe_inode_info *info, struct pipe_buffer *buf) | 256 | /** |
257 | * generic_pipe_buf_confirm - verify contents of the pipe buffer | ||
258 | * @pipe: the pipe that the buffer belongs to | ||
259 | * @buf: the buffer to confirm | ||
260 | * | ||
261 | * Description: | ||
262 | * This function does nothing, because the generic pipe code uses | ||
263 | * pages that are always good when inserted into the pipe. | ||
264 | */ | ||
265 | int generic_pipe_buf_confirm(struct pipe_inode_info *info, | ||
266 | struct pipe_buffer *buf) | ||
207 | { | 267 | { |
208 | return 0; | 268 | return 0; |
209 | } | 269 | } |
@@ -212,7 +272,7 @@ static const struct pipe_buf_operations anon_pipe_buf_ops = { | |||
212 | .can_merge = 1, | 272 | .can_merge = 1, |
213 | .map = generic_pipe_buf_map, | 273 | .map = generic_pipe_buf_map, |
214 | .unmap = generic_pipe_buf_unmap, | 274 | .unmap = generic_pipe_buf_unmap, |
215 | .pin = generic_pipe_buf_pin, | 275 | .confirm = generic_pipe_buf_confirm, |
216 | .release = anon_pipe_buf_release, | 276 | .release = anon_pipe_buf_release, |
217 | .steal = generic_pipe_buf_steal, | 277 | .steal = generic_pipe_buf_steal, |
218 | .get = generic_pipe_buf_get, | 278 | .get = generic_pipe_buf_get, |
@@ -252,7 +312,7 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov, | |||
252 | if (chars > total_len) | 312 | if (chars > total_len) |
253 | chars = total_len; | 313 | chars = total_len; |
254 | 314 | ||
255 | error = ops->pin(pipe, buf); | 315 | error = ops->confirm(pipe, buf); |
256 | if (error) { | 316 | if (error) { |
257 | if (!ret) | 317 | if (!ret) |
258 | error = ret; | 318 | error = ret; |
@@ -373,7 +433,7 @@ pipe_write(struct kiocb *iocb, const struct iovec *_iov, | |||
373 | int error, atomic = 1; | 433 | int error, atomic = 1; |
374 | void *addr; | 434 | void *addr; |
375 | 435 | ||
376 | error = ops->pin(pipe, buf); | 436 | error = ops->confirm(pipe, buf); |
377 | if (error) | 437 | if (error) |
378 | goto out; | 438 | goto out; |
379 | 439 | ||
diff --git a/fs/qnx4/file.c b/fs/qnx4/file.c index 44649981bbc8..867f42b02035 100644 --- a/fs/qnx4/file.c +++ b/fs/qnx4/file.c | |||
@@ -25,7 +25,7 @@ const struct file_operations qnx4_file_operations = | |||
25 | .read = do_sync_read, | 25 | .read = do_sync_read, |
26 | .aio_read = generic_file_aio_read, | 26 | .aio_read = generic_file_aio_read, |
27 | .mmap = generic_file_mmap, | 27 | .mmap = generic_file_mmap, |
28 | .sendfile = generic_file_sendfile, | 28 | .splice_read = generic_file_splice_read, |
29 | #ifdef CONFIG_QNX4FS_RW | 29 | #ifdef CONFIG_QNX4FS_RW |
30 | .write = do_sync_write, | 30 | .write = do_sync_write, |
31 | .aio_write = generic_file_aio_write, | 31 | .aio_write = generic_file_aio_write, |
diff --git a/fs/ramfs/file-mmu.c b/fs/ramfs/file-mmu.c index 2f14774a124f..97bdc0b2f9d2 100644 --- a/fs/ramfs/file-mmu.c +++ b/fs/ramfs/file-mmu.c | |||
@@ -41,7 +41,7 @@ const struct file_operations ramfs_file_operations = { | |||
41 | .aio_write = generic_file_aio_write, | 41 | .aio_write = generic_file_aio_write, |
42 | .mmap = generic_file_mmap, | 42 | .mmap = generic_file_mmap, |
43 | .fsync = simple_sync_file, | 43 | .fsync = simple_sync_file, |
44 | .sendfile = generic_file_sendfile, | 44 | .splice_read = generic_file_splice_read, |
45 | .llseek = generic_file_llseek, | 45 | .llseek = generic_file_llseek, |
46 | }; | 46 | }; |
47 | 47 | ||
diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c index 5d258c40a2fd..cad2b7ace630 100644 --- a/fs/ramfs/file-nommu.c +++ b/fs/ramfs/file-nommu.c | |||
@@ -42,7 +42,7 @@ const struct file_operations ramfs_file_operations = { | |||
42 | .write = do_sync_write, | 42 | .write = do_sync_write, |
43 | .aio_write = generic_file_aio_write, | 43 | .aio_write = generic_file_aio_write, |
44 | .fsync = simple_sync_file, | 44 | .fsync = simple_sync_file, |
45 | .sendfile = generic_file_sendfile, | 45 | .splice_read = generic_file_splice_read, |
46 | .llseek = generic_file_llseek, | 46 | .llseek = generic_file_llseek, |
47 | }; | 47 | }; |
48 | 48 | ||
diff --git a/fs/read_write.c b/fs/read_write.c index 4d03008f015b..507ddff48a9a 100644 --- a/fs/read_write.c +++ b/fs/read_write.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/syscalls.h> | 16 | #include <linux/syscalls.h> |
17 | #include <linux/pagemap.h> | 17 | #include <linux/pagemap.h> |
18 | #include <linux/splice.h> | ||
18 | #include "read_write.h" | 19 | #include "read_write.h" |
19 | 20 | ||
20 | #include <asm/uaccess.h> | 21 | #include <asm/uaccess.h> |
@@ -25,7 +26,7 @@ const struct file_operations generic_ro_fops = { | |||
25 | .read = do_sync_read, | 26 | .read = do_sync_read, |
26 | .aio_read = generic_file_aio_read, | 27 | .aio_read = generic_file_aio_read, |
27 | .mmap = generic_file_readonly_mmap, | 28 | .mmap = generic_file_readonly_mmap, |
28 | .sendfile = generic_file_sendfile, | 29 | .splice_read = generic_file_splice_read, |
29 | }; | 30 | }; |
30 | 31 | ||
31 | EXPORT_SYMBOL(generic_ro_fops); | 32 | EXPORT_SYMBOL(generic_ro_fops); |
@@ -708,7 +709,7 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, | |||
708 | struct inode * in_inode, * out_inode; | 709 | struct inode * in_inode, * out_inode; |
709 | loff_t pos; | 710 | loff_t pos; |
710 | ssize_t retval; | 711 | ssize_t retval; |
711 | int fput_needed_in, fput_needed_out; | 712 | int fput_needed_in, fput_needed_out, fl; |
712 | 713 | ||
713 | /* | 714 | /* |
714 | * Get input file, and verify that it is ok.. | 715 | * Get input file, and verify that it is ok.. |
@@ -723,7 +724,7 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, | |||
723 | in_inode = in_file->f_path.dentry->d_inode; | 724 | in_inode = in_file->f_path.dentry->d_inode; |
724 | if (!in_inode) | 725 | if (!in_inode) |
725 | goto fput_in; | 726 | goto fput_in; |
726 | if (!in_file->f_op || !in_file->f_op->sendfile) | 727 | if (!in_file->f_op || !in_file->f_op->splice_read) |
727 | goto fput_in; | 728 | goto fput_in; |
728 | retval = -ESPIPE; | 729 | retval = -ESPIPE; |
729 | if (!ppos) | 730 | if (!ppos) |
@@ -776,7 +777,18 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, | |||
776 | count = max - pos; | 777 | count = max - pos; |
777 | } | 778 | } |
778 | 779 | ||
779 | retval = in_file->f_op->sendfile(in_file, ppos, count, file_send_actor, out_file); | 780 | fl = 0; |
781 | #if 0 | ||
782 | /* | ||
783 | * We need to debate whether we can enable this or not. The | ||
784 | * man page documents EAGAIN return for the output at least, | ||
785 | * and the application is arguably buggy if it doesn't expect | ||
786 | * EAGAIN on a non-blocking file descriptor. | ||
787 | */ | ||
788 | if (in_file->f_flags & O_NONBLOCK) | ||
789 | fl = SPLICE_F_NONBLOCK; | ||
790 | #endif | ||
791 | retval = do_splice_direct(in_file, ppos, out_file, count, fl); | ||
780 | 792 | ||
781 | if (retval > 0) { | 793 | if (retval > 0) { |
782 | add_rchar(current, retval); | 794 | add_rchar(current, retval); |
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c index 9e451a68580f..30eebfb1b2d8 100644 --- a/fs/reiserfs/file.c +++ b/fs/reiserfs/file.c | |||
@@ -1531,7 +1531,6 @@ const struct file_operations reiserfs_file_operations = { | |||
1531 | .open = generic_file_open, | 1531 | .open = generic_file_open, |
1532 | .release = reiserfs_file_release, | 1532 | .release = reiserfs_file_release, |
1533 | .fsync = reiserfs_sync_file, | 1533 | .fsync = reiserfs_sync_file, |
1534 | .sendfile = generic_file_sendfile, | ||
1535 | .aio_read = generic_file_aio_read, | 1534 | .aio_read = generic_file_aio_read, |
1536 | .aio_write = generic_file_aio_write, | 1535 | .aio_write = generic_file_aio_write, |
1537 | .splice_read = generic_file_splice_read, | 1536 | .splice_read = generic_file_splice_read, |
diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c index aea3f8aa54c0..c5d78a7e492b 100644 --- a/fs/smbfs/file.c +++ b/fs/smbfs/file.c | |||
@@ -262,8 +262,9 @@ out: | |||
262 | } | 262 | } |
263 | 263 | ||
264 | static ssize_t | 264 | static ssize_t |
265 | smb_file_sendfile(struct file *file, loff_t *ppos, | 265 | smb_file_splice_read(struct file *file, loff_t *ppos, |
266 | size_t count, read_actor_t actor, void *target) | 266 | struct pipe_inode_info *pipe, size_t count, |
267 | unsigned int flags) | ||
267 | { | 268 | { |
268 | struct dentry *dentry = file->f_path.dentry; | 269 | struct dentry *dentry = file->f_path.dentry; |
269 | ssize_t status; | 270 | ssize_t status; |
@@ -277,7 +278,7 @@ smb_file_sendfile(struct file *file, loff_t *ppos, | |||
277 | DENTRY_PATH(dentry), status); | 278 | DENTRY_PATH(dentry), status); |
278 | goto out; | 279 | goto out; |
279 | } | 280 | } |
280 | status = generic_file_sendfile(file, ppos, count, actor, target); | 281 | status = generic_file_splice_read(file, ppos, pipe, count, flags); |
281 | out: | 282 | out: |
282 | return status; | 283 | return status; |
283 | } | 284 | } |
@@ -416,7 +417,7 @@ const struct file_operations smb_file_operations = | |||
416 | .open = smb_file_open, | 417 | .open = smb_file_open, |
417 | .release = smb_file_release, | 418 | .release = smb_file_release, |
418 | .fsync = smb_fsync, | 419 | .fsync = smb_fsync, |
419 | .sendfile = smb_file_sendfile, | 420 | .splice_read = smb_file_splice_read, |
420 | }; | 421 | }; |
421 | 422 | ||
422 | const struct inode_operations smb_file_inode_operations = | 423 | const struct inode_operations smb_file_inode_operations = |
diff --git a/fs/splice.c b/fs/splice.c index e7d7080de2f9..ed2ce995475c 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
@@ -20,7 +20,7 @@ | |||
20 | #include <linux/fs.h> | 20 | #include <linux/fs.h> |
21 | #include <linux/file.h> | 21 | #include <linux/file.h> |
22 | #include <linux/pagemap.h> | 22 | #include <linux/pagemap.h> |
23 | #include <linux/pipe_fs_i.h> | 23 | #include <linux/splice.h> |
24 | #include <linux/mm_inline.h> | 24 | #include <linux/mm_inline.h> |
25 | #include <linux/swap.h> | 25 | #include <linux/swap.h> |
26 | #include <linux/writeback.h> | 26 | #include <linux/writeback.h> |
@@ -29,22 +29,6 @@ | |||
29 | #include <linux/syscalls.h> | 29 | #include <linux/syscalls.h> |
30 | #include <linux/uio.h> | 30 | #include <linux/uio.h> |
31 | 31 | ||
32 | struct partial_page { | ||
33 | unsigned int offset; | ||
34 | unsigned int len; | ||
35 | }; | ||
36 | |||
37 | /* | ||
38 | * Passed to splice_to_pipe | ||
39 | */ | ||
40 | struct splice_pipe_desc { | ||
41 | struct page **pages; /* page map */ | ||
42 | struct partial_page *partial; /* pages[] may not be contig */ | ||
43 | int nr_pages; /* number of pages in map */ | ||
44 | unsigned int flags; /* splice flags */ | ||
45 | const struct pipe_buf_operations *ops;/* ops associated with output pipe */ | ||
46 | }; | ||
47 | |||
48 | /* | 32 | /* |
49 | * Attempt to steal a page from a pipe buffer. This should perhaps go into | 33 | * Attempt to steal a page from a pipe buffer. This should perhaps go into |
50 | * a vm helper function, it's already simplified quite a bit by the | 34 | * a vm helper function, it's already simplified quite a bit by the |
@@ -101,8 +85,12 @@ static void page_cache_pipe_buf_release(struct pipe_inode_info *pipe, | |||
101 | buf->flags &= ~PIPE_BUF_FLAG_LRU; | 85 | buf->flags &= ~PIPE_BUF_FLAG_LRU; |
102 | } | 86 | } |
103 | 87 | ||
104 | static int page_cache_pipe_buf_pin(struct pipe_inode_info *pipe, | 88 | /* |
105 | struct pipe_buffer *buf) | 89 | * Check whether the contents of buf is OK to access. Since the content |
90 | * is a page cache page, IO may be in flight. | ||
91 | */ | ||
92 | static int page_cache_pipe_buf_confirm(struct pipe_inode_info *pipe, | ||
93 | struct pipe_buffer *buf) | ||
106 | { | 94 | { |
107 | struct page *page = buf->page; | 95 | struct page *page = buf->page; |
108 | int err; | 96 | int err; |
@@ -143,7 +131,7 @@ static const struct pipe_buf_operations page_cache_pipe_buf_ops = { | |||
143 | .can_merge = 0, | 131 | .can_merge = 0, |
144 | .map = generic_pipe_buf_map, | 132 | .map = generic_pipe_buf_map, |
145 | .unmap = generic_pipe_buf_unmap, | 133 | .unmap = generic_pipe_buf_unmap, |
146 | .pin = page_cache_pipe_buf_pin, | 134 | .confirm = page_cache_pipe_buf_confirm, |
147 | .release = page_cache_pipe_buf_release, | 135 | .release = page_cache_pipe_buf_release, |
148 | .steal = page_cache_pipe_buf_steal, | 136 | .steal = page_cache_pipe_buf_steal, |
149 | .get = generic_pipe_buf_get, | 137 | .get = generic_pipe_buf_get, |
@@ -163,18 +151,25 @@ static const struct pipe_buf_operations user_page_pipe_buf_ops = { | |||
163 | .can_merge = 0, | 151 | .can_merge = 0, |
164 | .map = generic_pipe_buf_map, | 152 | .map = generic_pipe_buf_map, |
165 | .unmap = generic_pipe_buf_unmap, | 153 | .unmap = generic_pipe_buf_unmap, |
166 | .pin = generic_pipe_buf_pin, | 154 | .confirm = generic_pipe_buf_confirm, |
167 | .release = page_cache_pipe_buf_release, | 155 | .release = page_cache_pipe_buf_release, |
168 | .steal = user_page_pipe_buf_steal, | 156 | .steal = user_page_pipe_buf_steal, |
169 | .get = generic_pipe_buf_get, | 157 | .get = generic_pipe_buf_get, |
170 | }; | 158 | }; |
171 | 159 | ||
172 | /* | 160 | /** |
173 | * Pipe output worker. This sets up our pipe format with the page cache | 161 | * splice_to_pipe - fill passed data into a pipe |
174 | * pipe buffer operations. Otherwise very similar to the regular pipe_writev(). | 162 | * @pipe: pipe to fill |
163 | * @spd: data to fill | ||
164 | * | ||
165 | * Description: | ||
166 | * @spd contains a map of pages and len/offset tupples, a long with | ||
167 | * the struct pipe_buf_operations associated with these pages. This | ||
168 | * function will link that data to the pipe. | ||
169 | * | ||
175 | */ | 170 | */ |
176 | static ssize_t splice_to_pipe(struct pipe_inode_info *pipe, | 171 | ssize_t splice_to_pipe(struct pipe_inode_info *pipe, |
177 | struct splice_pipe_desc *spd) | 172 | struct splice_pipe_desc *spd) |
178 | { | 173 | { |
179 | unsigned int spd_pages = spd->nr_pages; | 174 | unsigned int spd_pages = spd->nr_pages; |
180 | int ret, do_wakeup, page_nr; | 175 | int ret, do_wakeup, page_nr; |
@@ -201,6 +196,7 @@ static ssize_t splice_to_pipe(struct pipe_inode_info *pipe, | |||
201 | buf->page = spd->pages[page_nr]; | 196 | buf->page = spd->pages[page_nr]; |
202 | buf->offset = spd->partial[page_nr].offset; | 197 | buf->offset = spd->partial[page_nr].offset; |
203 | buf->len = spd->partial[page_nr].len; | 198 | buf->len = spd->partial[page_nr].len; |
199 | buf->private = spd->partial[page_nr].private; | ||
204 | buf->ops = spd->ops; | 200 | buf->ops = spd->ops; |
205 | if (spd->flags & SPLICE_F_GIFT) | 201 | if (spd->flags & SPLICE_F_GIFT) |
206 | buf->flags |= PIPE_BUF_FLAG_GIFT; | 202 | buf->flags |= PIPE_BUF_FLAG_GIFT; |
@@ -296,19 +292,15 @@ __generic_file_splice_read(struct file *in, loff_t *ppos, | |||
296 | page_cache_readahead(mapping, &in->f_ra, in, index, nr_pages); | 292 | page_cache_readahead(mapping, &in->f_ra, in, index, nr_pages); |
297 | 293 | ||
298 | /* | 294 | /* |
299 | * Now fill in the holes: | ||
300 | */ | ||
301 | error = 0; | ||
302 | |||
303 | /* | ||
304 | * Lookup the (hopefully) full range of pages we need. | 295 | * Lookup the (hopefully) full range of pages we need. |
305 | */ | 296 | */ |
306 | spd.nr_pages = find_get_pages_contig(mapping, index, nr_pages, pages); | 297 | spd.nr_pages = find_get_pages_contig(mapping, index, nr_pages, pages); |
307 | 298 | ||
308 | /* | 299 | /* |
309 | * If find_get_pages_contig() returned fewer pages than we needed, | 300 | * If find_get_pages_contig() returned fewer pages than we needed, |
310 | * allocate the rest. | 301 | * allocate the rest and fill in the holes. |
311 | */ | 302 | */ |
303 | error = 0; | ||
312 | index += spd.nr_pages; | 304 | index += spd.nr_pages; |
313 | while (spd.nr_pages < nr_pages) { | 305 | while (spd.nr_pages < nr_pages) { |
314 | /* | 306 | /* |
@@ -470,11 +462,16 @@ fill_it: | |||
470 | /** | 462 | /** |
471 | * generic_file_splice_read - splice data from file to a pipe | 463 | * generic_file_splice_read - splice data from file to a pipe |
472 | * @in: file to splice from | 464 | * @in: file to splice from |
465 | * @ppos: position in @in | ||
473 | * @pipe: pipe to splice to | 466 | * @pipe: pipe to splice to |
474 | * @len: number of bytes to splice | 467 | * @len: number of bytes to splice |
475 | * @flags: splice modifier flags | 468 | * @flags: splice modifier flags |
476 | * | 469 | * |
477 | * Will read pages from given file and fill them into a pipe. | 470 | * Description: |
471 | * Will read pages from given file and fill them into a pipe. Can be | ||
472 | * used as long as the address_space operations for the source implements | ||
473 | * a readpage() hook. | ||
474 | * | ||
478 | */ | 475 | */ |
479 | ssize_t generic_file_splice_read(struct file *in, loff_t *ppos, | 476 | ssize_t generic_file_splice_read(struct file *in, loff_t *ppos, |
480 | struct pipe_inode_info *pipe, size_t len, | 477 | struct pipe_inode_info *pipe, size_t len, |
@@ -528,11 +525,11 @@ EXPORT_SYMBOL(generic_file_splice_read); | |||
528 | static int pipe_to_sendpage(struct pipe_inode_info *pipe, | 525 | static int pipe_to_sendpage(struct pipe_inode_info *pipe, |
529 | struct pipe_buffer *buf, struct splice_desc *sd) | 526 | struct pipe_buffer *buf, struct splice_desc *sd) |
530 | { | 527 | { |
531 | struct file *file = sd->file; | 528 | struct file *file = sd->u.file; |
532 | loff_t pos = sd->pos; | 529 | loff_t pos = sd->pos; |
533 | int ret, more; | 530 | int ret, more; |
534 | 531 | ||
535 | ret = buf->ops->pin(pipe, buf); | 532 | ret = buf->ops->confirm(pipe, buf); |
536 | if (!ret) { | 533 | if (!ret) { |
537 | more = (sd->flags & SPLICE_F_MORE) || sd->len < sd->total_len; | 534 | more = (sd->flags & SPLICE_F_MORE) || sd->len < sd->total_len; |
538 | 535 | ||
@@ -566,7 +563,7 @@ static int pipe_to_sendpage(struct pipe_inode_info *pipe, | |||
566 | static int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf, | 563 | static int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf, |
567 | struct splice_desc *sd) | 564 | struct splice_desc *sd) |
568 | { | 565 | { |
569 | struct file *file = sd->file; | 566 | struct file *file = sd->u.file; |
570 | struct address_space *mapping = file->f_mapping; | 567 | struct address_space *mapping = file->f_mapping; |
571 | unsigned int offset, this_len; | 568 | unsigned int offset, this_len; |
572 | struct page *page; | 569 | struct page *page; |
@@ -576,7 +573,7 @@ static int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf, | |||
576 | /* | 573 | /* |
577 | * make sure the data in this buffer is uptodate | 574 | * make sure the data in this buffer is uptodate |
578 | */ | 575 | */ |
579 | ret = buf->ops->pin(pipe, buf); | 576 | ret = buf->ops->confirm(pipe, buf); |
580 | if (unlikely(ret)) | 577 | if (unlikely(ret)) |
581 | return ret; | 578 | return ret; |
582 | 579 | ||
@@ -663,36 +660,37 @@ out_ret: | |||
663 | return ret; | 660 | return ret; |
664 | } | 661 | } |
665 | 662 | ||
666 | /* | 663 | /** |
667 | * Pipe input worker. Most of this logic works like a regular pipe, the | 664 | * __splice_from_pipe - splice data from a pipe to given actor |
668 | * key here is the 'actor' worker passed in that actually moves the data | 665 | * @pipe: pipe to splice from |
669 | * to the wanted destination. See pipe_to_file/pipe_to_sendpage above. | 666 | * @sd: information to @actor |
667 | * @actor: handler that splices the data | ||
668 | * | ||
669 | * Description: | ||
670 | * This function does little more than loop over the pipe and call | ||
671 | * @actor to do the actual moving of a single struct pipe_buffer to | ||
672 | * the desired destination. See pipe_to_file, pipe_to_sendpage, or | ||
673 | * pipe_to_user. | ||
674 | * | ||
670 | */ | 675 | */ |
671 | ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, | 676 | ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, struct splice_desc *sd, |
672 | struct file *out, loff_t *ppos, size_t len, | 677 | splice_actor *actor) |
673 | unsigned int flags, splice_actor *actor) | ||
674 | { | 678 | { |
675 | int ret, do_wakeup, err; | 679 | int ret, do_wakeup, err; |
676 | struct splice_desc sd; | ||
677 | 680 | ||
678 | ret = 0; | 681 | ret = 0; |
679 | do_wakeup = 0; | 682 | do_wakeup = 0; |
680 | 683 | ||
681 | sd.total_len = len; | ||
682 | sd.flags = flags; | ||
683 | sd.file = out; | ||
684 | sd.pos = *ppos; | ||
685 | |||
686 | for (;;) { | 684 | for (;;) { |
687 | if (pipe->nrbufs) { | 685 | if (pipe->nrbufs) { |
688 | struct pipe_buffer *buf = pipe->bufs + pipe->curbuf; | 686 | struct pipe_buffer *buf = pipe->bufs + pipe->curbuf; |
689 | const struct pipe_buf_operations *ops = buf->ops; | 687 | const struct pipe_buf_operations *ops = buf->ops; |
690 | 688 | ||
691 | sd.len = buf->len; | 689 | sd->len = buf->len; |
692 | if (sd.len > sd.total_len) | 690 | if (sd->len > sd->total_len) |
693 | sd.len = sd.total_len; | 691 | sd->len = sd->total_len; |
694 | 692 | ||
695 | err = actor(pipe, buf, &sd); | 693 | err = actor(pipe, buf, sd); |
696 | if (err <= 0) { | 694 | if (err <= 0) { |
697 | if (!ret && err != -ENODATA) | 695 | if (!ret && err != -ENODATA) |
698 | ret = err; | 696 | ret = err; |
@@ -704,10 +702,10 @@ ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, | |||
704 | buf->offset += err; | 702 | buf->offset += err; |
705 | buf->len -= err; | 703 | buf->len -= err; |
706 | 704 | ||
707 | sd.len -= err; | 705 | sd->len -= err; |
708 | sd.pos += err; | 706 | sd->pos += err; |
709 | sd.total_len -= err; | 707 | sd->total_len -= err; |
710 | if (sd.len) | 708 | if (sd->len) |
711 | continue; | 709 | continue; |
712 | 710 | ||
713 | if (!buf->len) { | 711 | if (!buf->len) { |
@@ -719,7 +717,7 @@ ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, | |||
719 | do_wakeup = 1; | 717 | do_wakeup = 1; |
720 | } | 718 | } |
721 | 719 | ||
722 | if (!sd.total_len) | 720 | if (!sd->total_len) |
723 | break; | 721 | break; |
724 | } | 722 | } |
725 | 723 | ||
@@ -732,7 +730,7 @@ ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, | |||
732 | break; | 730 | break; |
733 | } | 731 | } |
734 | 732 | ||
735 | if (flags & SPLICE_F_NONBLOCK) { | 733 | if (sd->flags & SPLICE_F_NONBLOCK) { |
736 | if (!ret) | 734 | if (!ret) |
737 | ret = -EAGAIN; | 735 | ret = -EAGAIN; |
738 | break; | 736 | break; |
@@ -766,12 +764,32 @@ ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, | |||
766 | } | 764 | } |
767 | EXPORT_SYMBOL(__splice_from_pipe); | 765 | EXPORT_SYMBOL(__splice_from_pipe); |
768 | 766 | ||
767 | /** | ||
768 | * splice_from_pipe - splice data from a pipe to a file | ||
769 | * @pipe: pipe to splice from | ||
770 | * @out: file to splice to | ||
771 | * @ppos: position in @out | ||
772 | * @len: how many bytes to splice | ||
773 | * @flags: splice modifier flags | ||
774 | * @actor: handler that splices the data | ||
775 | * | ||
776 | * Description: | ||
777 | * See __splice_from_pipe. This function locks the input and output inodes, | ||
778 | * otherwise it's identical to __splice_from_pipe(). | ||
779 | * | ||
780 | */ | ||
769 | ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out, | 781 | ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out, |
770 | loff_t *ppos, size_t len, unsigned int flags, | 782 | loff_t *ppos, size_t len, unsigned int flags, |
771 | splice_actor *actor) | 783 | splice_actor *actor) |
772 | { | 784 | { |
773 | ssize_t ret; | 785 | ssize_t ret; |
774 | struct inode *inode = out->f_mapping->host; | 786 | struct inode *inode = out->f_mapping->host; |
787 | struct splice_desc sd = { | ||
788 | .total_len = len, | ||
789 | .flags = flags, | ||
790 | .pos = *ppos, | ||
791 | .u.file = out, | ||
792 | }; | ||
775 | 793 | ||
776 | /* | 794 | /* |
777 | * The actor worker might be calling ->prepare_write and | 795 | * The actor worker might be calling ->prepare_write and |
@@ -780,7 +798,7 @@ ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out, | |||
780 | * pipe->inode, we have to order lock acquiry here. | 798 | * pipe->inode, we have to order lock acquiry here. |
781 | */ | 799 | */ |
782 | inode_double_lock(inode, pipe->inode); | 800 | inode_double_lock(inode, pipe->inode); |
783 | ret = __splice_from_pipe(pipe, out, ppos, len, flags, actor); | 801 | ret = __splice_from_pipe(pipe, &sd, actor); |
784 | inode_double_unlock(inode, pipe->inode); | 802 | inode_double_unlock(inode, pipe->inode); |
785 | 803 | ||
786 | return ret; | 804 | return ret; |
@@ -790,12 +808,14 @@ ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out, | |||
790 | * generic_file_splice_write_nolock - generic_file_splice_write without mutexes | 808 | * generic_file_splice_write_nolock - generic_file_splice_write without mutexes |
791 | * @pipe: pipe info | 809 | * @pipe: pipe info |
792 | * @out: file to write to | 810 | * @out: file to write to |
811 | * @ppos: position in @out | ||
793 | * @len: number of bytes to splice | 812 | * @len: number of bytes to splice |
794 | * @flags: splice modifier flags | 813 | * @flags: splice modifier flags |
795 | * | 814 | * |
796 | * Will either move or copy pages (determined by @flags options) from | 815 | * Description: |
797 | * the given pipe inode to the given file. The caller is responsible | 816 | * Will either move or copy pages (determined by @flags options) from |
798 | * for acquiring i_mutex on both inodes. | 817 | * the given pipe inode to the given file. The caller is responsible |
818 | * for acquiring i_mutex on both inodes. | ||
799 | * | 819 | * |
800 | */ | 820 | */ |
801 | ssize_t | 821 | ssize_t |
@@ -804,6 +824,12 @@ generic_file_splice_write_nolock(struct pipe_inode_info *pipe, struct file *out, | |||
804 | { | 824 | { |
805 | struct address_space *mapping = out->f_mapping; | 825 | struct address_space *mapping = out->f_mapping; |
806 | struct inode *inode = mapping->host; | 826 | struct inode *inode = mapping->host; |
827 | struct splice_desc sd = { | ||
828 | .total_len = len, | ||
829 | .flags = flags, | ||
830 | .pos = *ppos, | ||
831 | .u.file = out, | ||
832 | }; | ||
807 | ssize_t ret; | 833 | ssize_t ret; |
808 | int err; | 834 | int err; |
809 | 835 | ||
@@ -811,7 +837,7 @@ generic_file_splice_write_nolock(struct pipe_inode_info *pipe, struct file *out, | |||
811 | if (unlikely(err)) | 837 | if (unlikely(err)) |
812 | return err; | 838 | return err; |
813 | 839 | ||
814 | ret = __splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_file); | 840 | ret = __splice_from_pipe(pipe, &sd, pipe_to_file); |
815 | if (ret > 0) { | 841 | if (ret > 0) { |
816 | unsigned long nr_pages; | 842 | unsigned long nr_pages; |
817 | 843 | ||
@@ -841,11 +867,13 @@ EXPORT_SYMBOL(generic_file_splice_write_nolock); | |||
841 | * generic_file_splice_write - splice data from a pipe to a file | 867 | * generic_file_splice_write - splice data from a pipe to a file |
842 | * @pipe: pipe info | 868 | * @pipe: pipe info |
843 | * @out: file to write to | 869 | * @out: file to write to |
870 | * @ppos: position in @out | ||
844 | * @len: number of bytes to splice | 871 | * @len: number of bytes to splice |
845 | * @flags: splice modifier flags | 872 | * @flags: splice modifier flags |
846 | * | 873 | * |
847 | * Will either move or copy pages (determined by @flags options) from | 874 | * Description: |
848 | * the given pipe inode to the given file. | 875 | * Will either move or copy pages (determined by @flags options) from |
876 | * the given pipe inode to the given file. | ||
849 | * | 877 | * |
850 | */ | 878 | */ |
851 | ssize_t | 879 | ssize_t |
@@ -896,13 +924,15 @@ EXPORT_SYMBOL(generic_file_splice_write); | |||
896 | 924 | ||
897 | /** | 925 | /** |
898 | * generic_splice_sendpage - splice data from a pipe to a socket | 926 | * generic_splice_sendpage - splice data from a pipe to a socket |
899 | * @inode: pipe inode | 927 | * @pipe: pipe to splice from |
900 | * @out: socket to write to | 928 | * @out: socket to write to |
929 | * @ppos: position in @out | ||
901 | * @len: number of bytes to splice | 930 | * @len: number of bytes to splice |
902 | * @flags: splice modifier flags | 931 | * @flags: splice modifier flags |
903 | * | 932 | * |
904 | * Will send @len bytes from the pipe to a network socket. No data copying | 933 | * Description: |
905 | * is involved. | 934 | * Will send @len bytes from the pipe to a network socket. No data copying |
935 | * is involved. | ||
906 | * | 936 | * |
907 | */ | 937 | */ |
908 | ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe, struct file *out, | 938 | ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe, struct file *out, |
@@ -956,14 +986,27 @@ static long do_splice_to(struct file *in, loff_t *ppos, | |||
956 | return in->f_op->splice_read(in, ppos, pipe, len, flags); | 986 | return in->f_op->splice_read(in, ppos, pipe, len, flags); |
957 | } | 987 | } |
958 | 988 | ||
959 | long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, | 989 | /** |
960 | size_t len, unsigned int flags) | 990 | * splice_direct_to_actor - splices data directly between two non-pipes |
991 | * @in: file to splice from | ||
992 | * @sd: actor information on where to splice to | ||
993 | * @actor: handles the data splicing | ||
994 | * | ||
995 | * Description: | ||
996 | * This is a special case helper to splice directly between two | ||
997 | * points, without requiring an explicit pipe. Internally an allocated | ||
998 | * pipe is cached in the process, and reused during the life time of | ||
999 | * that process. | ||
1000 | * | ||
1001 | */ | ||
1002 | ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd, | ||
1003 | splice_direct_actor *actor) | ||
961 | { | 1004 | { |
962 | struct pipe_inode_info *pipe; | 1005 | struct pipe_inode_info *pipe; |
963 | long ret, bytes; | 1006 | long ret, bytes; |
964 | loff_t out_off; | ||
965 | umode_t i_mode; | 1007 | umode_t i_mode; |
966 | int i; | 1008 | size_t len; |
1009 | int i, flags; | ||
967 | 1010 | ||
968 | /* | 1011 | /* |
969 | * We require the input being a regular file, as we don't want to | 1012 | * We require the input being a regular file, as we don't want to |
@@ -999,7 +1042,13 @@ long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, | |||
999 | */ | 1042 | */ |
1000 | ret = 0; | 1043 | ret = 0; |
1001 | bytes = 0; | 1044 | bytes = 0; |
1002 | out_off = 0; | 1045 | len = sd->total_len; |
1046 | flags = sd->flags; | ||
1047 | |||
1048 | /* | ||
1049 | * Don't block on output, we have to drain the direct pipe. | ||
1050 | */ | ||
1051 | sd->flags &= ~SPLICE_F_NONBLOCK; | ||
1003 | 1052 | ||
1004 | while (len) { | 1053 | while (len) { |
1005 | size_t read_len, max_read_len; | 1054 | size_t read_len, max_read_len; |
@@ -1009,19 +1058,19 @@ long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, | |||
1009 | */ | 1058 | */ |
1010 | max_read_len = min(len, (size_t)(PIPE_BUFFERS*PAGE_SIZE)); | 1059 | max_read_len = min(len, (size_t)(PIPE_BUFFERS*PAGE_SIZE)); |
1011 | 1060 | ||
1012 | ret = do_splice_to(in, ppos, pipe, max_read_len, flags); | 1061 | ret = do_splice_to(in, &sd->pos, pipe, max_read_len, flags); |
1013 | if (unlikely(ret < 0)) | 1062 | if (unlikely(ret < 0)) |
1014 | goto out_release; | 1063 | goto out_release; |
1015 | 1064 | ||
1016 | read_len = ret; | 1065 | read_len = ret; |
1066 | sd->total_len = read_len; | ||
1017 | 1067 | ||
1018 | /* | 1068 | /* |
1019 | * NOTE: nonblocking mode only applies to the input. We | 1069 | * NOTE: nonblocking mode only applies to the input. We |
1020 | * must not do the output in nonblocking mode as then we | 1070 | * must not do the output in nonblocking mode as then we |
1021 | * could get stuck data in the internal pipe: | 1071 | * could get stuck data in the internal pipe: |
1022 | */ | 1072 | */ |
1023 | ret = do_splice_from(pipe, out, &out_off, read_len, | 1073 | ret = actor(pipe, sd); |
1024 | flags & ~SPLICE_F_NONBLOCK); | ||
1025 | if (unlikely(ret < 0)) | 1074 | if (unlikely(ret < 0)) |
1026 | goto out_release; | 1075 | goto out_release; |
1027 | 1076 | ||
@@ -1066,6 +1115,48 @@ out_release: | |||
1066 | return bytes; | 1115 | return bytes; |
1067 | 1116 | ||
1068 | return ret; | 1117 | return ret; |
1118 | |||
1119 | } | ||
1120 | EXPORT_SYMBOL(splice_direct_to_actor); | ||
1121 | |||
1122 | static int direct_splice_actor(struct pipe_inode_info *pipe, | ||
1123 | struct splice_desc *sd) | ||
1124 | { | ||
1125 | struct file *file = sd->u.file; | ||
1126 | |||
1127 | return do_splice_from(pipe, file, &sd->pos, sd->total_len, sd->flags); | ||
1128 | } | ||
1129 | |||
1130 | /** | ||
1131 | * do_splice_direct - splices data directly between two files | ||
1132 | * @in: file to splice from | ||
1133 | * @ppos: input file offset | ||
1134 | * @out: file to splice to | ||
1135 | * @len: number of bytes to splice | ||
1136 | * @flags: splice modifier flags | ||
1137 | * | ||
1138 | * Description: | ||
1139 | * For use by do_sendfile(). splice can easily emulate sendfile, but | ||
1140 | * doing it in the application would incur an extra system call | ||
1141 | * (splice in + splice out, as compared to just sendfile()). So this helper | ||
1142 | * can splice directly through a process-private pipe. | ||
1143 | * | ||
1144 | */ | ||
1145 | long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, | ||
1146 | size_t len, unsigned int flags) | ||
1147 | { | ||
1148 | struct splice_desc sd = { | ||
1149 | .len = len, | ||
1150 | .total_len = len, | ||
1151 | .flags = flags, | ||
1152 | .pos = *ppos, | ||
1153 | .u.file = out, | ||
1154 | }; | ||
1155 | size_t ret; | ||
1156 | |||
1157 | ret = splice_direct_to_actor(in, &sd, direct_splice_actor); | ||
1158 | *ppos = sd.pos; | ||
1159 | return ret; | ||
1069 | } | 1160 | } |
1070 | 1161 | ||
1071 | /* | 1162 | /* |
@@ -1248,28 +1339,131 @@ static int get_iovec_page_array(const struct iovec __user *iov, | |||
1248 | return error; | 1339 | return error; |
1249 | } | 1340 | } |
1250 | 1341 | ||
1342 | static int pipe_to_user(struct pipe_inode_info *pipe, struct pipe_buffer *buf, | ||
1343 | struct splice_desc *sd) | ||
1344 | { | ||
1345 | char *src; | ||
1346 | int ret; | ||
1347 | |||
1348 | ret = buf->ops->confirm(pipe, buf); | ||
1349 | if (unlikely(ret)) | ||
1350 | return ret; | ||
1351 | |||
1352 | /* | ||
1353 | * See if we can use the atomic maps, by prefaulting in the | ||
1354 | * pages and doing an atomic copy | ||
1355 | */ | ||
1356 | if (!fault_in_pages_writeable(sd->u.userptr, sd->len)) { | ||
1357 | src = buf->ops->map(pipe, buf, 1); | ||
1358 | ret = __copy_to_user_inatomic(sd->u.userptr, src + buf->offset, | ||
1359 | sd->len); | ||
1360 | buf->ops->unmap(pipe, buf, src); | ||
1361 | if (!ret) { | ||
1362 | ret = sd->len; | ||
1363 | goto out; | ||
1364 | } | ||
1365 | } | ||
1366 | |||
1367 | /* | ||
1368 | * No dice, use slow non-atomic map and copy | ||
1369 | */ | ||
1370 | src = buf->ops->map(pipe, buf, 0); | ||
1371 | |||
1372 | ret = sd->len; | ||
1373 | if (copy_to_user(sd->u.userptr, src + buf->offset, sd->len)) | ||
1374 | ret = -EFAULT; | ||
1375 | |||
1376 | out: | ||
1377 | if (ret > 0) | ||
1378 | sd->u.userptr += ret; | ||
1379 | buf->ops->unmap(pipe, buf, src); | ||
1380 | return ret; | ||
1381 | } | ||
1382 | |||
1383 | /* | ||
1384 | * For lack of a better implementation, implement vmsplice() to userspace | ||
1385 | * as a simple copy of the pipes pages to the user iov. | ||
1386 | */ | ||
1387 | static long vmsplice_to_user(struct file *file, const struct iovec __user *iov, | ||
1388 | unsigned long nr_segs, unsigned int flags) | ||
1389 | { | ||
1390 | struct pipe_inode_info *pipe; | ||
1391 | struct splice_desc sd; | ||
1392 | ssize_t size; | ||
1393 | int error; | ||
1394 | long ret; | ||
1395 | |||
1396 | pipe = pipe_info(file->f_path.dentry->d_inode); | ||
1397 | if (!pipe) | ||
1398 | return -EBADF; | ||
1399 | |||
1400 | if (pipe->inode) | ||
1401 | mutex_lock(&pipe->inode->i_mutex); | ||
1402 | |||
1403 | error = ret = 0; | ||
1404 | while (nr_segs) { | ||
1405 | void __user *base; | ||
1406 | size_t len; | ||
1407 | |||
1408 | /* | ||
1409 | * Get user address base and length for this iovec. | ||
1410 | */ | ||
1411 | error = get_user(base, &iov->iov_base); | ||
1412 | if (unlikely(error)) | ||
1413 | break; | ||
1414 | error = get_user(len, &iov->iov_len); | ||
1415 | if (unlikely(error)) | ||
1416 | break; | ||
1417 | |||
1418 | /* | ||
1419 | * Sanity check this iovec. 0 read succeeds. | ||
1420 | */ | ||
1421 | if (unlikely(!len)) | ||
1422 | break; | ||
1423 | if (unlikely(!base)) { | ||
1424 | error = -EFAULT; | ||
1425 | break; | ||
1426 | } | ||
1427 | |||
1428 | sd.len = 0; | ||
1429 | sd.total_len = len; | ||
1430 | sd.flags = flags; | ||
1431 | sd.u.userptr = base; | ||
1432 | sd.pos = 0; | ||
1433 | |||
1434 | size = __splice_from_pipe(pipe, &sd, pipe_to_user); | ||
1435 | if (size < 0) { | ||
1436 | if (!ret) | ||
1437 | ret = size; | ||
1438 | |||
1439 | break; | ||
1440 | } | ||
1441 | |||
1442 | ret += size; | ||
1443 | |||
1444 | if (size < len) | ||
1445 | break; | ||
1446 | |||
1447 | nr_segs--; | ||
1448 | iov++; | ||
1449 | } | ||
1450 | |||
1451 | if (pipe->inode) | ||
1452 | mutex_unlock(&pipe->inode->i_mutex); | ||
1453 | |||
1454 | if (!ret) | ||
1455 | ret = error; | ||
1456 | |||
1457 | return ret; | ||
1458 | } | ||
1459 | |||
1251 | /* | 1460 | /* |
1252 | * vmsplice splices a user address range into a pipe. It can be thought of | 1461 | * vmsplice splices a user address range into a pipe. It can be thought of |
1253 | * as splice-from-memory, where the regular splice is splice-from-file (or | 1462 | * as splice-from-memory, where the regular splice is splice-from-file (or |
1254 | * to file). In both cases the output is a pipe, naturally. | 1463 | * to file). In both cases the output is a pipe, naturally. |
1255 | * | ||
1256 | * Note that vmsplice only supports splicing _from_ user memory to a pipe, | ||
1257 | * not the other way around. Splicing from user memory is a simple operation | ||
1258 | * that can be supported without any funky alignment restrictions or nasty | ||
1259 | * vm tricks. We simply map in the user memory and fill them into a pipe. | ||
1260 | * The reverse isn't quite as easy, though. There are two possible solutions | ||
1261 | * for that: | ||
1262 | * | ||
1263 | * - memcpy() the data internally, at which point we might as well just | ||
1264 | * do a regular read() on the buffer anyway. | ||
1265 | * - Lots of nasty vm tricks, that are neither fast nor flexible (it | ||
1266 | * has restriction limitations on both ends of the pipe). | ||
1267 | * | ||
1268 | * Alas, it isn't here. | ||
1269 | * | ||
1270 | */ | 1464 | */ |
1271 | static long do_vmsplice(struct file *file, const struct iovec __user *iov, | 1465 | static long vmsplice_to_pipe(struct file *file, const struct iovec __user *iov, |
1272 | unsigned long nr_segs, unsigned int flags) | 1466 | unsigned long nr_segs, unsigned int flags) |
1273 | { | 1467 | { |
1274 | struct pipe_inode_info *pipe; | 1468 | struct pipe_inode_info *pipe; |
1275 | struct page *pages[PIPE_BUFFERS]; | 1469 | struct page *pages[PIPE_BUFFERS]; |
@@ -1284,10 +1478,6 @@ static long do_vmsplice(struct file *file, const struct iovec __user *iov, | |||
1284 | pipe = pipe_info(file->f_path.dentry->d_inode); | 1478 | pipe = pipe_info(file->f_path.dentry->d_inode); |
1285 | if (!pipe) | 1479 | if (!pipe) |
1286 | return -EBADF; | 1480 | return -EBADF; |
1287 | if (unlikely(nr_segs > UIO_MAXIOV)) | ||
1288 | return -EINVAL; | ||
1289 | else if (unlikely(!nr_segs)) | ||
1290 | return 0; | ||
1291 | 1481 | ||
1292 | spd.nr_pages = get_iovec_page_array(iov, nr_segs, pages, partial, | 1482 | spd.nr_pages = get_iovec_page_array(iov, nr_segs, pages, partial, |
1293 | flags & SPLICE_F_GIFT); | 1483 | flags & SPLICE_F_GIFT); |
@@ -1297,6 +1487,22 @@ static long do_vmsplice(struct file *file, const struct iovec __user *iov, | |||
1297 | return splice_to_pipe(pipe, &spd); | 1487 | return splice_to_pipe(pipe, &spd); |
1298 | } | 1488 | } |
1299 | 1489 | ||
1490 | /* | ||
1491 | * Note that vmsplice only really supports true splicing _from_ user memory | ||
1492 | * to a pipe, not the other way around. Splicing from user memory is a simple | ||
1493 | * operation that can be supported without any funky alignment restrictions | ||
1494 | * or nasty vm tricks. We simply map in the user memory and fill them into | ||
1495 | * a pipe. The reverse isn't quite as easy, though. There are two possible | ||
1496 | * solutions for that: | ||
1497 | * | ||
1498 | * - memcpy() the data internally, at which point we might as well just | ||
1499 | * do a regular read() on the buffer anyway. | ||
1500 | * - Lots of nasty vm tricks, that are neither fast nor flexible (it | ||
1501 | * has restriction limitations on both ends of the pipe). | ||
1502 | * | ||
1503 | * Currently we punt and implement it as a normal copy, see pipe_to_user(). | ||
1504 | * | ||
1505 | */ | ||
1300 | asmlinkage long sys_vmsplice(int fd, const struct iovec __user *iov, | 1506 | asmlinkage long sys_vmsplice(int fd, const struct iovec __user *iov, |
1301 | unsigned long nr_segs, unsigned int flags) | 1507 | unsigned long nr_segs, unsigned int flags) |
1302 | { | 1508 | { |
@@ -1304,11 +1510,18 @@ asmlinkage long sys_vmsplice(int fd, const struct iovec __user *iov, | |||
1304 | long error; | 1510 | long error; |
1305 | int fput; | 1511 | int fput; |
1306 | 1512 | ||
1513 | if (unlikely(nr_segs > UIO_MAXIOV)) | ||
1514 | return -EINVAL; | ||
1515 | else if (unlikely(!nr_segs)) | ||
1516 | return 0; | ||
1517 | |||
1307 | error = -EBADF; | 1518 | error = -EBADF; |
1308 | file = fget_light(fd, &fput); | 1519 | file = fget_light(fd, &fput); |
1309 | if (file) { | 1520 | if (file) { |
1310 | if (file->f_mode & FMODE_WRITE) | 1521 | if (file->f_mode & FMODE_WRITE) |
1311 | error = do_vmsplice(file, iov, nr_segs, flags); | 1522 | error = vmsplice_to_pipe(file, iov, nr_segs, flags); |
1523 | else if (file->f_mode & FMODE_READ) | ||
1524 | error = vmsplice_to_user(file, iov, nr_segs, flags); | ||
1312 | 1525 | ||
1313 | fput_light(file, fput); | 1526 | fput_light(file, fput); |
1314 | } | 1527 | } |
diff --git a/fs/sysv/file.c b/fs/sysv/file.c index 0732ddb9020b..589be21d884e 100644 --- a/fs/sysv/file.c +++ b/fs/sysv/file.c | |||
@@ -27,7 +27,7 @@ const struct file_operations sysv_file_operations = { | |||
27 | .aio_write = generic_file_aio_write, | 27 | .aio_write = generic_file_aio_write, |
28 | .mmap = generic_file_mmap, | 28 | .mmap = generic_file_mmap, |
29 | .fsync = sysv_sync_file, | 29 | .fsync = sysv_sync_file, |
30 | .sendfile = generic_file_sendfile, | 30 | .splice_read = generic_file_splice_read, |
31 | }; | 31 | }; |
32 | 32 | ||
33 | const struct inode_operations sysv_file_inode_operations = { | 33 | const struct inode_operations sysv_file_inode_operations = { |
diff --git a/fs/udf/file.c b/fs/udf/file.c index 51b5764685e7..df070bee8d4f 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c | |||
@@ -261,7 +261,7 @@ const struct file_operations udf_file_operations = { | |||
261 | .aio_write = udf_file_aio_write, | 261 | .aio_write = udf_file_aio_write, |
262 | .release = udf_release_file, | 262 | .release = udf_release_file, |
263 | .fsync = udf_fsync_file, | 263 | .fsync = udf_fsync_file, |
264 | .sendfile = generic_file_sendfile, | 264 | .splice_read = generic_file_splice_read, |
265 | }; | 265 | }; |
266 | 266 | ||
267 | const struct inode_operations udf_file_inode_operations = { | 267 | const struct inode_operations udf_file_inode_operations = { |
diff --git a/fs/ufs/file.c b/fs/ufs/file.c index 1e096323bad4..6705d74c6d2d 100644 --- a/fs/ufs/file.c +++ b/fs/ufs/file.c | |||
@@ -60,5 +60,5 @@ const struct file_operations ufs_file_operations = { | |||
60 | .mmap = generic_file_mmap, | 60 | .mmap = generic_file_mmap, |
61 | .open = generic_file_open, | 61 | .open = generic_file_open, |
62 | .fsync = ufs_sync_file, | 62 | .fsync = ufs_sync_file, |
63 | .sendfile = generic_file_sendfile, | 63 | .splice_read = generic_file_splice_read, |
64 | }; | 64 | }; |
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index cb51dc961355..8c43cd2e237a 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c | |||
@@ -124,30 +124,6 @@ xfs_file_aio_write_invis( | |||
124 | } | 124 | } |
125 | 125 | ||
126 | STATIC ssize_t | 126 | STATIC ssize_t |
127 | xfs_file_sendfile( | ||
128 | struct file *filp, | ||
129 | loff_t *pos, | ||
130 | size_t count, | ||
131 | read_actor_t actor, | ||
132 | void *target) | ||
133 | { | ||
134 | return bhv_vop_sendfile(vn_from_inode(filp->f_path.dentry->d_inode), | ||
135 | filp, pos, 0, count, actor, target, NULL); | ||
136 | } | ||
137 | |||
138 | STATIC ssize_t | ||
139 | xfs_file_sendfile_invis( | ||
140 | struct file *filp, | ||
141 | loff_t *pos, | ||
142 | size_t count, | ||
143 | read_actor_t actor, | ||
144 | void *target) | ||
145 | { | ||
146 | return bhv_vop_sendfile(vn_from_inode(filp->f_path.dentry->d_inode), | ||
147 | filp, pos, IO_INVIS, count, actor, target, NULL); | ||
148 | } | ||
149 | |||
150 | STATIC ssize_t | ||
151 | xfs_file_splice_read( | 127 | xfs_file_splice_read( |
152 | struct file *infilp, | 128 | struct file *infilp, |
153 | loff_t *ppos, | 129 | loff_t *ppos, |
@@ -452,7 +428,6 @@ const struct file_operations xfs_file_operations = { | |||
452 | .write = do_sync_write, | 428 | .write = do_sync_write, |
453 | .aio_read = xfs_file_aio_read, | 429 | .aio_read = xfs_file_aio_read, |
454 | .aio_write = xfs_file_aio_write, | 430 | .aio_write = xfs_file_aio_write, |
455 | .sendfile = xfs_file_sendfile, | ||
456 | .splice_read = xfs_file_splice_read, | 431 | .splice_read = xfs_file_splice_read, |
457 | .splice_write = xfs_file_splice_write, | 432 | .splice_write = xfs_file_splice_write, |
458 | .unlocked_ioctl = xfs_file_ioctl, | 433 | .unlocked_ioctl = xfs_file_ioctl, |
@@ -475,7 +450,6 @@ const struct file_operations xfs_invis_file_operations = { | |||
475 | .write = do_sync_write, | 450 | .write = do_sync_write, |
476 | .aio_read = xfs_file_aio_read_invis, | 451 | .aio_read = xfs_file_aio_read_invis, |
477 | .aio_write = xfs_file_aio_write_invis, | 452 | .aio_write = xfs_file_aio_write_invis, |
478 | .sendfile = xfs_file_sendfile_invis, | ||
479 | .splice_read = xfs_file_splice_read_invis, | 453 | .splice_read = xfs_file_splice_read_invis, |
480 | .splice_write = xfs_file_splice_write_invis, | 454 | .splice_write = xfs_file_splice_write_invis, |
481 | .unlocked_ioctl = xfs_file_ioctl_invis, | 455 | .unlocked_ioctl = xfs_file_ioctl_invis, |
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h index 715adad7dd4d..af24a457d3a3 100644 --- a/fs/xfs/linux-2.6/xfs_linux.h +++ b/fs/xfs/linux-2.6/xfs_linux.h | |||
@@ -101,7 +101,6 @@ | |||
101 | * Feature macros (disable/enable) | 101 | * Feature macros (disable/enable) |
102 | */ | 102 | */ |
103 | #undef HAVE_REFCACHE /* reference cache not needed for NFS in 2.6 */ | 103 | #undef HAVE_REFCACHE /* reference cache not needed for NFS in 2.6 */ |
104 | #define HAVE_SENDFILE /* sendfile(2) exists in 2.6, but not in 2.4 */ | ||
105 | #define HAVE_SPLICE /* a splice(2) exists in 2.6, but not in 2.4 */ | 104 | #define HAVE_SPLICE /* a splice(2) exists in 2.6, but not in 2.4 */ |
106 | #ifdef CONFIG_SMP | 105 | #ifdef CONFIG_SMP |
107 | #define HAVE_PERCPU_SB /* per cpu superblock counters are a 2.6 feature */ | 106 | #define HAVE_PERCPU_SB /* per cpu superblock counters are a 2.6 feature */ |
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c index ed90403f0ee7..765ec16a6e39 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.c +++ b/fs/xfs/linux-2.6/xfs_lrw.c | |||
@@ -287,50 +287,6 @@ xfs_read( | |||
287 | } | 287 | } |
288 | 288 | ||
289 | ssize_t | 289 | ssize_t |
290 | xfs_sendfile( | ||
291 | bhv_desc_t *bdp, | ||
292 | struct file *filp, | ||
293 | loff_t *offset, | ||
294 | int ioflags, | ||
295 | size_t count, | ||
296 | read_actor_t actor, | ||
297 | void *target, | ||
298 | cred_t *credp) | ||
299 | { | ||
300 | xfs_inode_t *ip = XFS_BHVTOI(bdp); | ||
301 | xfs_mount_t *mp = ip->i_mount; | ||
302 | ssize_t ret; | ||
303 | |||
304 | XFS_STATS_INC(xs_read_calls); | ||
305 | if (XFS_FORCED_SHUTDOWN(mp)) | ||
306 | return -EIO; | ||
307 | |||
308 | xfs_ilock(ip, XFS_IOLOCK_SHARED); | ||
309 | |||
310 | if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_READ) && | ||
311 | (!(ioflags & IO_INVIS))) { | ||
312 | bhv_vrwlock_t locktype = VRWLOCK_READ; | ||
313 | int error; | ||
314 | |||
315 | error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp), | ||
316 | *offset, count, | ||
317 | FILP_DELAY_FLAG(filp), &locktype); | ||
318 | if (error) { | ||
319 | xfs_iunlock(ip, XFS_IOLOCK_SHARED); | ||
320 | return -error; | ||
321 | } | ||
322 | } | ||
323 | xfs_rw_enter_trace(XFS_SENDFILE_ENTER, &ip->i_iocore, | ||
324 | (void *)(unsigned long)target, count, *offset, ioflags); | ||
325 | ret = generic_file_sendfile(filp, offset, count, actor, target); | ||
326 | if (ret > 0) | ||
327 | XFS_STATS_ADD(xs_read_bytes, ret); | ||
328 | |||
329 | xfs_iunlock(ip, XFS_IOLOCK_SHARED); | ||
330 | return ret; | ||
331 | } | ||
332 | |||
333 | ssize_t | ||
334 | xfs_splice_read( | 290 | xfs_splice_read( |
335 | bhv_desc_t *bdp, | 291 | bhv_desc_t *bdp, |
336 | struct file *infilp, | 292 | struct file *infilp, |
diff --git a/fs/xfs/linux-2.6/xfs_lrw.h b/fs/xfs/linux-2.6/xfs_lrw.h index 7ac51b1d2161..7c60a1eed88b 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.h +++ b/fs/xfs/linux-2.6/xfs_lrw.h | |||
@@ -90,9 +90,6 @@ extern ssize_t xfs_read(struct bhv_desc *, struct kiocb *, | |||
90 | extern ssize_t xfs_write(struct bhv_desc *, struct kiocb *, | 90 | extern ssize_t xfs_write(struct bhv_desc *, struct kiocb *, |
91 | const struct iovec *, unsigned int, | 91 | const struct iovec *, unsigned int, |
92 | loff_t *, int, struct cred *); | 92 | loff_t *, int, struct cred *); |
93 | extern ssize_t xfs_sendfile(struct bhv_desc *, struct file *, | ||
94 | loff_t *, int, size_t, read_actor_t, | ||
95 | void *, struct cred *); | ||
96 | extern ssize_t xfs_splice_read(struct bhv_desc *, struct file *, loff_t *, | 93 | extern ssize_t xfs_splice_read(struct bhv_desc *, struct file *, loff_t *, |
97 | struct pipe_inode_info *, size_t, int, int, | 94 | struct pipe_inode_info *, size_t, int, int, |
98 | struct cred *); | 95 | struct cred *); |
diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h index d1b2d01843d1..013048a92643 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.h +++ b/fs/xfs/linux-2.6/xfs_vnode.h | |||
@@ -139,9 +139,6 @@ typedef ssize_t (*vop_read_t)(bhv_desc_t *, struct kiocb *, | |||
139 | typedef ssize_t (*vop_write_t)(bhv_desc_t *, struct kiocb *, | 139 | typedef ssize_t (*vop_write_t)(bhv_desc_t *, struct kiocb *, |
140 | const struct iovec *, unsigned int, | 140 | const struct iovec *, unsigned int, |
141 | loff_t *, int, struct cred *); | 141 | loff_t *, int, struct cred *); |
142 | typedef ssize_t (*vop_sendfile_t)(bhv_desc_t *, struct file *, | ||
143 | loff_t *, int, size_t, read_actor_t, | ||
144 | void *, struct cred *); | ||
145 | typedef ssize_t (*vop_splice_read_t)(bhv_desc_t *, struct file *, loff_t *, | 142 | typedef ssize_t (*vop_splice_read_t)(bhv_desc_t *, struct file *, loff_t *, |
146 | struct pipe_inode_info *, size_t, int, int, | 143 | struct pipe_inode_info *, size_t, int, int, |
147 | struct cred *); | 144 | struct cred *); |
@@ -206,7 +203,6 @@ typedef struct bhv_vnodeops { | |||
206 | vop_close_t vop_close; | 203 | vop_close_t vop_close; |
207 | vop_read_t vop_read; | 204 | vop_read_t vop_read; |
208 | vop_write_t vop_write; | 205 | vop_write_t vop_write; |
209 | vop_sendfile_t vop_sendfile; | ||
210 | vop_splice_read_t vop_splice_read; | 206 | vop_splice_read_t vop_splice_read; |
211 | vop_splice_write_t vop_splice_write; | 207 | vop_splice_write_t vop_splice_write; |
212 | vop_ioctl_t vop_ioctl; | 208 | vop_ioctl_t vop_ioctl; |
@@ -254,8 +250,6 @@ typedef struct bhv_vnodeops { | |||
254 | VOP(vop_read, vp)(VNHEAD(vp),file,iov,segs,offset,ioflags,cr) | 250 | VOP(vop_read, vp)(VNHEAD(vp),file,iov,segs,offset,ioflags,cr) |
255 | #define bhv_vop_write(vp,file,iov,segs,offset,ioflags,cr) \ | 251 | #define bhv_vop_write(vp,file,iov,segs,offset,ioflags,cr) \ |
256 | VOP(vop_write, vp)(VNHEAD(vp),file,iov,segs,offset,ioflags,cr) | 252 | VOP(vop_write, vp)(VNHEAD(vp),file,iov,segs,offset,ioflags,cr) |
257 | #define bhv_vop_sendfile(vp,f,off,ioflags,cnt,act,targ,cr) \ | ||
258 | VOP(vop_sendfile, vp)(VNHEAD(vp),f,off,ioflags,cnt,act,targ,cr) | ||
259 | #define bhv_vop_splice_read(vp,f,o,pipe,cnt,fl,iofl,cr) \ | 253 | #define bhv_vop_splice_read(vp,f,o,pipe,cnt,fl,iofl,cr) \ |
260 | VOP(vop_splice_read, vp)(VNHEAD(vp),f,o,pipe,cnt,fl,iofl,cr) | 254 | VOP(vop_splice_read, vp)(VNHEAD(vp),f,o,pipe,cnt,fl,iofl,cr) |
261 | #define bhv_vop_splice_write(vp,f,o,pipe,cnt,fl,iofl,cr) \ | 255 | #define bhv_vop_splice_write(vp,f,o,pipe,cnt,fl,iofl,cr) \ |
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index de17aed578f0..70bc82f65311 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c | |||
@@ -4680,9 +4680,6 @@ bhv_vnodeops_t xfs_vnodeops = { | |||
4680 | .vop_open = xfs_open, | 4680 | .vop_open = xfs_open, |
4681 | .vop_close = xfs_close, | 4681 | .vop_close = xfs_close, |
4682 | .vop_read = xfs_read, | 4682 | .vop_read = xfs_read, |
4683 | #ifdef HAVE_SENDFILE | ||
4684 | .vop_sendfile = xfs_sendfile, | ||
4685 | #endif | ||
4686 | #ifdef HAVE_SPLICE | 4683 | #ifdef HAVE_SPLICE |
4687 | .vop_splice_read = xfs_splice_read, | 4684 | .vop_splice_read = xfs_splice_read, |
4688 | .vop_splice_write = xfs_splice_write, | 4685 | .vop_splice_write = xfs_splice_write, |