mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Jens Axboe <jens.axboe@oracle.com>
To: linux-kernel@vger.kernel.org
Cc: Jens Axboe <jens.axboe@oracle.com>
Subject: [PATCH 13/18] relay: use splice_to_pipe() instead of open-coding the pipe loop
Date: Tue, 12 Jun 2007 08:58:09 +0200	[thread overview]
Message-ID: <1181631495919-git-send-email-jens.axboe@oracle.com> (raw)
In-Reply-To: <11816314942627-git-send-email-jens.axboe@oracle.com>

It cleans up the relay splice implementation a lot, and gets rid of
a lot of internal pipe knowledge that should not be in there.

Plus fixes for padding and partial first page (and lots more) from
Tom Zanussi.

Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
---
 kernel/relay.c |  146 +++++++++++++++++++++-----------------------------------
 1 files changed, 55 insertions(+), 91 deletions(-)

diff --git a/kernel/relay.c b/kernel/relay.c
index ae13040..0c2971e 100644
--- a/kernel/relay.c
+++ b/kernel/relay.c
@@ -1025,19 +1025,23 @@ static ssize_t relay_file_read(struct file *filp,
 				       NULL, &desc);
 }
 
+static void relay_consume_bytes(struct rchan_buf *rbuf, int bytes_consumed)
+{
+	rbuf->bytes_consumed += bytes_consumed;
+
+	if (rbuf->bytes_consumed >= rbuf->chan->subbuf_size) {
+		relay_subbufs_consumed(rbuf->chan, rbuf->cpu, 1);
+		rbuf->bytes_consumed %= rbuf->chan->subbuf_size;
+	}
+}
+
 static void relay_pipe_buf_release(struct pipe_inode_info *pipe,
 				   struct pipe_buffer *buf)
 {
 	struct rchan_buf *rbuf;
 
 	rbuf = (struct rchan_buf *)page_private(buf->page);
-
-	rbuf->bytes_consumed += PAGE_SIZE;
-
-	if (rbuf->bytes_consumed == rbuf->chan->subbuf_size) {
-		relay_subbufs_consumed(rbuf->chan, rbuf->cpu, 1);
-		rbuf->bytes_consumed = 0;
-	}
+	relay_consume_bytes(rbuf, buf->private);
 }
 
 static struct pipe_buf_operations relay_pipe_buf_ops = {
@@ -1060,118 +1064,79 @@ static int subbuf_splice_actor(struct file *in,
 			       unsigned int flags,
 			       int *nonpad_ret)
 {
-	unsigned int pidx, poff;
-	unsigned int subbuf_pages;
-	int ret = 0;
-	int do_wakeup = 0;
+	unsigned int pidx, poff, total_len, subbuf_pages, ret;
 	struct rchan_buf *rbuf = in->private_data;
 	unsigned int subbuf_size = rbuf->chan->subbuf_size;
 	size_t read_start = ((size_t)*ppos) % rbuf->chan->alloc_size;
-	size_t avail = subbuf_size - read_start % subbuf_size;
 	size_t read_subbuf = read_start / subbuf_size;
 	size_t padding = rbuf->padding[read_subbuf];
 	size_t nonpad_end = read_subbuf * subbuf_size + subbuf_size - padding;
+	struct page *pages[PIPE_BUFFERS];
+	struct partial_page partial[PIPE_BUFFERS];
+	struct splice_pipe_desc spd = {
+		.pages = pages,
+		.nr_pages = 0,
+		.partial = partial,
+		.flags = flags,
+		.ops = &relay_pipe_buf_ops,
+	};
 
 	if (rbuf->subbufs_produced == rbuf->subbufs_consumed)
 		return 0;
 
-	if (len > avail)
-		len = avail;
-
-	if (pipe->inode)
-		mutex_lock(&pipe->inode->i_mutex);
+	/*
+	 * Adjust read len, if longer than what is available
+	 */
+	if (len > (subbuf_size - read_start % subbuf_size))
+		len = subbuf_size - read_start % subbuf_size;
 
 	subbuf_pages = rbuf->chan->alloc_size >> PAGE_SHIFT;
 	pidx = (read_start / PAGE_SIZE) % subbuf_pages;
 	poff = read_start & ~PAGE_MASK;
 
-	for (;;) {
-		unsigned int this_len;
-		unsigned int this_end;
-		int newbuf = (pipe->curbuf + pipe->nrbufs) & (PIPE_BUFFERS - 1);
-		struct pipe_buffer *buf = pipe->bufs + newbuf;
+	for (total_len = 0; spd.nr_pages < subbuf_pages; spd.nr_pages++) {
+		unsigned int this_len, this_end, private;
+		unsigned int cur_pos = read_start + total_len;
 
-		if (!pipe->readers) {
-			send_sig(SIGPIPE, current, 0);
-			if (!ret)
-				ret = -EPIPE;
+		if (!len)
 			break;
-		}
-
-		if (pipe->nrbufs < PIPE_BUFFERS) {
-			this_len = PAGE_SIZE - poff;
-			if (this_len > avail)
-				this_len = avail;
-
-			buf->page = rbuf->page_array[pidx];
-			buf->offset = poff;
-			this_end = read_start + ret + this_len;
-			if (this_end > nonpad_end) {
-				if (read_start + ret >= nonpad_end)
-					buf->len = 0;
-				else
-					buf->len = nonpad_end - (read_start + ret);
-			} else
-				buf->len = this_len;
-
-			*nonpad_ret += buf->len;
-
-			buf->ops = &relay_pipe_buf_ops;
-			pipe->nrbufs++;
 
-			avail -= this_len;
-			ret += this_len;
-			poff = 0;
-			pidx = (pidx + 1) % subbuf_pages;
+		this_len = min_t(unsigned long, len, PAGE_SIZE - poff);
+		private = this_len;
 
-			if (pipe->inode)
-				do_wakeup = 1;
+		spd.pages[spd.nr_pages] = rbuf->page_array[pidx];
+		spd.partial[spd.nr_pages].offset = poff;
 
-			if (!avail)
-				break;
-
-			if (pipe->nrbufs < PIPE_BUFFERS)
-				continue;
-
-			break;
+		this_end = cur_pos + this_len;
+		if (this_end >= nonpad_end) {
+			this_len = nonpad_end - cur_pos;
+			private = this_len + padding;
 		}
+		spd.partial[spd.nr_pages].len = this_len;
+		spd.partial[spd.nr_pages].private = private;
 
-		if (flags & SPLICE_F_NONBLOCK) {
-			if (!ret)
-				ret = -EAGAIN;
-			break;
-		}
+		len -= this_len;
+		total_len += this_len;
+		poff = 0;
+		pidx = (pidx + 1) % subbuf_pages;
 
-		if (signal_pending(current)) {
-			if (!ret)
-				ret = -ERESTARTSYS;
+		if (this_end >= nonpad_end) {
+			spd.nr_pages++;
 			break;
 		}
-
-		if (do_wakeup) {
-			smp_mb();
-			if (waitqueue_active(&pipe->wait))
-				wake_up_interruptible_sync(&pipe->wait);
-			kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
-			do_wakeup = 0;
-		}
-
-		pipe->waiting_writers++;
-		pipe_wait(pipe);
-		pipe->waiting_writers--;
 	}
 
-	if (pipe->inode)
-		mutex_unlock(&pipe->inode->i_mutex);
+	if (!spd.nr_pages)
+		return 0;
 
-	if (do_wakeup) {
-		smp_mb();
-		if (waitqueue_active(&pipe->wait))
-			wake_up_interruptible(&pipe->wait);
-		kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
-	}
+	ret = *nonpad_ret = splice_to_pipe(pipe, &spd);
+	if (ret < 0 || ret < total_len)
+		return ret;
 
-	return ret;
+        if (read_start + ret == nonpad_end)
+                ret += padding;
+
+        return ret;
 }
 
 static ssize_t relay_file_splice_read(struct file *in,
@@ -1192,7 +1157,6 @@ static ssize_t relay_file_splice_read(struct file *in,
 		if (ret < 0)
 			break;
 		else if (!ret) {
-			break;
 			if (spliced)
 				break;
 			if (flags & SPLICE_F_NONBLOCK) {
-- 
1.5.2.1.174.gcd03


  parent reply	other threads:[~2007-06-12  7:04 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-06-12  6:57 [PATCH 0/18] Convert sendfile to splice Jens Axboe
2007-06-12  6:57 ` [PATCH 1/18] splice: abstract out actor data Jens Axboe
2007-06-12 15:31   ` Eric Dumazet
2007-06-12 16:22     ` Jens Axboe
2007-06-13  8:48       ` Peter Zijlstra
2007-06-13  8:48         ` Jens Axboe
2007-06-12  6:57 ` [PATCH 2/18] vmsplice: add vmsplice-to-user support Jens Axboe
2007-06-12  6:57 ` [PATCH 3/18] sys_sendfile: switch to using ->splice_read, if available Jens Axboe
2007-06-12  6:58 ` [PATCH 4/18] sendfile: remove .sendfile from filesystems that use generic_file_sendfile() Jens Axboe
2007-06-12  6:58 ` [PATCH 5/18] sendfile: kill generic_file_sendfile() Jens Axboe
2007-06-12  6:58 ` [PATCH 6/18] splice: add void cookie to the actor data Jens Axboe
2007-06-12  6:58 ` [PATCH 7/18] loop: convert to using splice_direct_to_actor() instead of sendfile() Jens Axboe
2007-06-12  6:58 ` [PATCH 8/18] sendfile: convert nfs to using splice_read() Jens Axboe
2007-06-12  6:58 ` [PATCH 9/18] sendfile: convert nfsd to splice_direct_to_actor() Jens Axboe
2007-06-12  6:58 ` [PATCH 10/18] splice: relay support Jens Axboe
2007-06-12  6:58 ` [PATCH 11/18] splice: divorce the splice structure/function definitions from the pipe header Jens Axboe
2007-06-12  6:58 ` [PATCH 12/18] pipe: allow passing around of ops private pointer Jens Axboe
2007-06-12  6:58 ` Jens Axboe [this message]
2007-06-12  6:58 ` [PATCH 14/18] shmem: convert to using splice instead of sendfile() Jens Axboe
2007-06-12  6:58 ` [PATCH 15/18] sendfile: remove bad_sendfile() from bad_file_ops Jens Axboe
2007-06-12  6:58 ` [PATCH 16/18] splice: completely document external interface with kerneldoc Jens Axboe
2007-06-12  6:58 ` [PATCH 17/18] ext2 xip: replace sendfile with splice Jens Axboe
2007-06-12  6:58 ` [PATCH 18/18] Remove remnants of sendfile() Jens Axboe

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1181631495919-git-send-email-jens.axboe@oracle.com \
    --to=jens.axboe@oracle.com \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®