diff options
Diffstat (limited to 'fs/read_write.c')
-rw-r--r-- | fs/read_write.c | 24 |
1 files changed, 20 insertions, 4 deletions
diff --git a/fs/read_write.c b/fs/read_write.c index 4d03008f015b..47da8a4a0fbe 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/pipe_fs_i.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,8 @@ 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->sendfile && |
728 | !in_file->f_op->splice_read)) | ||
727 | goto fput_in; | 729 | goto fput_in; |
728 | retval = -ESPIPE; | 730 | retval = -ESPIPE; |
729 | if (!ppos) | 731 | if (!ppos) |
@@ -776,7 +778,21 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, | |||
776 | count = max - pos; | 778 | count = max - pos; |
777 | } | 779 | } |
778 | 780 | ||
779 | retval = in_file->f_op->sendfile(in_file, ppos, count, file_send_actor, out_file); | 781 | if (in_file->f_op->splice_read) { |
782 | fl = 0; | ||
783 | #if 0 | ||
784 | /* | ||
785 | * We need to debate whether we can enable this or not. The | ||
786 | * man page documents EAGAIN return for the output at least, | ||
787 | * and the application is arguably buggy if it doesn't expect | ||
788 | * EAGAIN on a non-blocking file descriptor. | ||
789 | */ | ||
790 | if (in_file->f_flags & O_NONBLOCK) | ||
791 | fl = SPLICE_F_NONBLOCK; | ||
792 | #endif | ||
793 | retval = do_splice_direct(in_file, ppos, out_file, count, fl); | ||
794 | } else | ||
795 | retval = in_file->f_op->sendfile(in_file, ppos, count, file_send_actor, out_file); | ||
780 | 796 | ||
781 | if (retval > 0) { | 797 | if (retval > 0) { |
782 | add_rchar(current, retval); | 798 | add_rchar(current, retval); |