aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfsd/vfs.c47
-rw-r--r--include/linux/sunrpc/svc.h2
-rw-r--r--net/sunrpc/auth_gss/svcauth_gss.c2
-rw-r--r--net/sunrpc/svc.c2
4 files changed, 34 insertions, 19 deletions
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 7e6aa245b5d5..15471a9efe0e 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/pipe_fs_i.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 */
808static int 808static int
809nfsd_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset , unsigned long size) 809nfsd_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->pin(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
844static 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
840static __be32 850static __be32
841nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, 851nfsd_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/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 4a7ae8ab6eb8..129d50f2225c 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -253,7 +253,7 @@ struct svc_rqst {
253 * determine what device number 253 * determine what device number
254 * to report (real or virtual) 254 * to report (real or virtual)
255 */ 255 */
256 int rq_sendfile_ok; /* turned off in gss privacy 256 int rq_splice_ok; /* turned off in gss privacy
257 * to prevent encrypting page 257 * to prevent encrypting page
258 * cache pages */ 258 * cache pages */
259 wait_queue_head_t rq_wait; /* synchronization */ 259 wait_queue_head_t rq_wait; /* synchronization */
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index 099a983797da..c094583386fd 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -853,7 +853,7 @@ unwrap_priv_data(struct svc_rqst *rqstp, struct xdr_buf *buf, u32 seq, struct gs
853 u32 priv_len, maj_stat; 853 u32 priv_len, maj_stat;
854 int pad, saved_len, remaining_len, offset; 854 int pad, saved_len, remaining_len, offset;
855 855
856 rqstp->rq_sendfile_ok = 0; 856 rqstp->rq_splice_ok = 0;
857 857
858 priv_len = svc_getnl(&buf->head[0]); 858 priv_len = svc_getnl(&buf->head[0]);
859 if (rqstp->rq_deferred) { 859 if (rqstp->rq_deferred) {
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index e673ef993904..55ea6df069de 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -814,7 +814,7 @@ svc_process(struct svc_rqst *rqstp)
814 rqstp->rq_res.tail[0].iov_base = NULL; 814 rqstp->rq_res.tail[0].iov_base = NULL;
815 rqstp->rq_res.tail[0].iov_len = 0; 815 rqstp->rq_res.tail[0].iov_len = 0;
816 /* Will be turned off only in gss privacy case: */ 816 /* Will be turned off only in gss privacy case: */
817 rqstp->rq_sendfile_ok = 1; 817 rqstp->rq_splice_ok = 1;
818 /* tcp needs a space for the record length... */ 818 /* tcp needs a space for the record length... */
819 if (rqstp->rq_prot == IPPROTO_TCP) 819 if (rqstp->rq_prot == IPPROTO_TCP)
820 svc_putnl(resv, 0); 820 svc_putnl(resv, 0);