All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Fix restoring pipes with full buffers
@ 2011-01-28 18:45 Dan Smith
       [not found] ` <1296240311-5050-1-git-send-email-danms-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
  0 siblings, 1 reply; 8+ messages in thread
From: Dan Smith @ 2011-01-28 18:45 UTC (permalink / raw)
  To: containers-qjLDD68F18O7TbgM5vRIOg

While this fixes restoring pipes that were completely full, it actually
corrects a potential issue with restoring any pipe buffers.  By using
splice() to do this work when we are reading the image from another pipe,
we depend on userspace setting up the buffers in the pipe perfectly
such that the data to be restored is oriented in the pipe in the same
way as it is expected (or required) to be in the restored pipe.  The
"full" case is the hardest to get right, but userspace could break things
if it loaded up the inbound pipe with lots of small buffers which would
cause splice() to hit the PIPE_BUFFERS limit before having read the
requested amount of data.

Instead, drop the optimization and just read() and write() data into
the pipe.

Signed-off-by: Dan Smith <danms-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
---
 fs/pipe.c |   49 ++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 46 insertions(+), 3 deletions(-)

diff --git a/fs/pipe.c b/fs/pipe.c
index 9664e4f..0da1e3a 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -926,17 +926,60 @@ static int pipe_file_checkpoint(struct ckpt_ctx *ctx, struct file *file)
 	return ret;
 }
 
+static int restore_pipe_buffer(struct ckpt_ctx *ctx,
+			       struct file *dest,
+			       int len)
+{
+	char *buf;
+	int ret;
+	int nread;
+	int nwrote;
+	int nleft = len;
+
+	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	for (nleft = len; nleft > 0; nleft -= nread) {
+		int size = nleft < PAGE_SIZE ? nleft : PAGE_SIZE;
+		loff_t pos;
+
+		pos = file_pos_read(ctx->file);
+		nread = kernel_read(ctx->file, pos, buf, size);
+		if (nread < 0) {
+			ret = nread;
+			goto out;
+		}
+		file_pos_write(ctx->file, pos + nread);
+
+		pos = file_pos_read(dest);
+		nwrote = kernel_write(dest, pos, buf, nread);
+		if (nwrote < 0) {
+			ret = nwrote;
+			goto out;
+		}
+		file_pos_write(dest, pos + nwrote);
+
+		if (nwrote != nread) {
+			ret = -EPIPE;
+			goto out;
+		}
+	}
+	ret = len;
+ out:
+	kfree(buf);
+	return ret;
+}
+
 static int restore_pipe(struct ckpt_ctx *ctx, struct file *file)
 {
-	struct pipe_inode_info *pipe;
 	int len, ret;
 
 	len = _ckpt_read_obj_type(ctx, NULL, 0, CKPT_HDR_PIPE_BUF);
 	if (len <= 0)
 		return len;
 
-	pipe = file->f_dentry->d_inode->i_pipe;
-	ret = do_splice_to(ctx->file, &ctx->file->f_pos, pipe, len, 0);
+	ret = restore_pipe_buffer(ctx, file, len);
 
 	if (ret >= 0 && ret != len)
 		ret = -EPIPE;  /* can occur due to an error in source file */
-- 
1.7.2.2

^ permalink raw reply related	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2011-01-31 17:09 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-01-28 18:45 [PATCH] Fix restoring pipes with full buffers Dan Smith
     [not found] ` <1296240311-5050-1-git-send-email-danms-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2011-01-28 23:05   ` Oren Laadan
     [not found]     ` <4D434BD0.5070809-eQaUEPhvms7ENvBUuze7eA@public.gmane.org>
2011-01-29  0:47       ` Dan Smith
2011-01-28 23:08   ` Matt Helsley
     [not found]     ` <20110128230822.GE16432-52DBMbEzqgQ/wnmkkaCWp/UQ3DHhIser@public.gmane.org>
2011-01-29  5:38       ` Oren Laadan
2011-01-29  5:45   ` Oren Laadan
     [not found]     ` <4D43A996.3020202-eQaUEPhvms7ENvBUuze7eA@public.gmane.org>
2011-01-31 16:44       ` Dan Smith
     [not found]         ` <87mxmh6n13.fsf-FLMGYpZoEPULwtHQx/6qkW3U47Q5hpJU@public.gmane.org>
2011-01-31 17:09           ` Oren Laadan

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.