Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cf8208d0 authored by Jens Axboe's avatar Jens Axboe
Browse files

sendfile: convert nfsd to splice_direct_to_actor()

parent f0930fff
Loading
Loading
Loading
Loading
+31 −16
Original line number Diff line number Diff line
@@ -23,7 +23,7 @@
#include <linux/file.h>
#include <linux/mount.h>
#include <linux/major.h>
#include <linux/ext2_fs.h>
#include <linux/pipe_fs_i.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
#include <linux/fcntl.h>
@@ -801,26 +801,32 @@ found:
}

/*
 * Grab and keep cached pages assosiated with a file in the svc_rqst
 * so that they can be passed to the netowork sendmsg/sendpage routines
 * directrly. They will be released after the sending has completed.
 * Grab and keep cached pages associated with a file in the svc_rqst
 * so that they can be passed to the network sendmsg/sendpage routines
 * directly. They will be released after the sending has completed.
 */
static int
nfsd_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset , unsigned long size)
nfsd_splice_actor(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
		  struct splice_desc *sd)
{
	unsigned long count = desc->count;
	struct svc_rqst *rqstp = desc->arg.data;
	struct svc_rqst *rqstp = sd->u.data;
	struct page **pp = rqstp->rq_respages + rqstp->rq_resused;
	struct page *page = buf->page;
	size_t size;
	int ret;

	ret = buf->ops->pin(pipe, buf);
	if (unlikely(ret))
		return ret;

	if (size > count)
		size = count;
	size = sd->len;

	if (rqstp->rq_res.page_len == 0) {
		get_page(page);
		put_page(*pp);
		*pp = page;
		rqstp->rq_resused++;
		rqstp->rq_res.page_base = offset;
		rqstp->rq_res.page_base = buf->offset;
		rqstp->rq_res.page_len = size;
	} else if (page != pp[-1]) {
		get_page(page);
@@ -832,11 +838,15 @@ nfsd_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset
	} else
		rqstp->rq_res.page_len += size;

	desc->count = count - size;
	desc->written += size;
	return size;
}

static int nfsd_direct_splice_actor(struct pipe_inode_info *pipe,
				    struct splice_desc *sd)
{
	return __splice_from_pipe(pipe, sd, nfsd_splice_actor);
}

static __be32
nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
              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,
	if (ra && ra->p_set)
		file->f_ra = ra->p_ra;

	if (file->f_op->sendfile && rqstp->rq_sendfile_ok) {
		rqstp->rq_resused = 1;
		host_err = file->f_op->sendfile(file, &offset, *count,
						 nfsd_read_actor, rqstp);
	if (file->f_op->splice_read && rqstp->rq_splice_ok) {
		struct splice_desc sd = {
			.len		= 0,
			.total_len	= *count,
			.pos		= offset,
			.u.data		= rqstp,
		};

		host_err = splice_direct_to_actor(file, &sd, nfsd_direct_splice_actor);
	} else {
		oldfs = get_fs();
		set_fs(KERNEL_DS);
+1 −1
Original line number Diff line number Diff line
@@ -253,7 +253,7 @@ struct svc_rqst {
						 * determine what device number
						 * to report (real or virtual)
						 */
	int			rq_sendfile_ok; /* turned off in gss privacy
	int			rq_splice_ok;   /* turned off in gss privacy
						 * to prevent encrypting page
						 * cache pages */
	wait_queue_head_t	rq_wait;	/* synchronization */
+1 −1
Original line number Diff line number Diff line
@@ -853,7 +853,7 @@ unwrap_priv_data(struct svc_rqst *rqstp, struct xdr_buf *buf, u32 seq, struct gs
	u32 priv_len, maj_stat;
	int pad, saved_len, remaining_len, offset;

	rqstp->rq_sendfile_ok = 0;
	rqstp->rq_splice_ok = 0;

	priv_len = svc_getnl(&buf->head[0]);
	if (rqstp->rq_deferred) {
+1 −1
Original line number Diff line number Diff line
@@ -814,7 +814,7 @@ svc_process(struct svc_rqst *rqstp)
	rqstp->rq_res.tail[0].iov_base = NULL;
	rqstp->rq_res.tail[0].iov_len = 0;
	/* Will be turned off only in gss privacy case: */
	rqstp->rq_sendfile_ok = 1;
	rqstp->rq_splice_ok = 1;
	/* tcp needs a space for the record length... */
	if (rqstp->rq_prot == IPPROTO_TCP)
		svc_putnl(resv, 0);