diff options
Diffstat (limited to 'fs/nfsd/vfs.c')
-rw-r--r-- | fs/nfsd/vfs.c | 47 |
1 files changed, 31 insertions, 16 deletions
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); |