2015-12-15 17:29:08

by Stanislav Kinsburskiy

[permalink] [raw]
Subject: [PATCH RFC 0/3] Fix splice for packetized pipes

With introduction of packetized pipes, splice wasn't updated to respect this
new behaviour.
In terms of splice it means, that it never set PIPE_BUF_FLAG_PACKET on
created pipe buffer regarless pipe operating mode, thus breaking the whole
logic.
To fix this, new SPLICE_F_PACKET flag was introduced. It's supposed to be used
only in kernel and set, when write pipe is in packetized mode. In
splice_to_pipe() it's converted into created pipe buffer PIPE_BUF_FLAG_PACKET
flag.

The following series implements...

---

Stanislav Kinsburskiy (3):
pipe: make is_packetized() non-static and declare in pipe_fs_i.h
splice: new SPLICE_F_PACKET flag introduced
splice: add support of splicing to packetized pipe


fs/pipe.c | 2 +-
fs/splice.c | 8 ++++++++
include/linux/pipe_fs_i.h | 2 ++
include/linux/splice.h | 5 +++++
4 files changed, 16 insertions(+), 1 deletion(-)


2015-12-15 17:29:07

by Stanislav Kinsburskiy

[permalink] [raw]
Subject: [PATCH RFC 1/3] pipe: make is_packetized() non-static and declare in pipe_fs_i.h

With introduction of packetized pipe mode, represented by O_DIRECT flag,
splice stopped working correctly with a pipe in this mode.
To be able to fix them, this helper have to exposed.

Signed-off-by: Stanislav Kinsburskiy <[email protected]>
---
fs/pipe.c | 2 +-
include/linux/pipe_fs_i.h | 2 ++
2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/fs/pipe.c b/fs/pipe.c
index 42cf8dd..645d142 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -329,7 +329,7 @@ pipe_read(struct kiocb *iocb, struct iov_iter *to)
return ret;
}

-static inline int is_packetized(struct file *file)
+int is_packetized(struct file *file)
{
return (file->f_flags & O_DIRECT) != 0;
}
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h
index eb8b8ac..9fdaf8f 100644
--- a/include/linux/pipe_fs_i.h
+++ b/include/linux/pipe_fs_i.h
@@ -146,4 +146,6 @@ struct pipe_inode_info *get_pipe_info(struct file *file);

int create_pipe_files(struct file **, int);

+int is_packetized(struct file *file);
+
#endif

2015-12-15 17:29:16

by Stanislav Kinsburskiy

[permalink] [raw]
Subject: [PATCH RFC 2/3] splice: new SPLICE_F_PACKET flag introduced

This flag is used by kernel only to represent pipe packetized mode for splice
engine.

Signed-off-by: Stanislav Kinsburskiy <[email protected]>
---
include/linux/splice.h | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/include/linux/splice.h b/include/linux/splice.h
index da2751d..13ca14d 100644
--- a/include/linux/splice.h
+++ b/include/linux/splice.h
@@ -20,6 +20,11 @@
#define SPLICE_F_MORE (0x04) /* expect more data */
#define SPLICE_F_GIFT (0x08) /* pages passed in are a gift */

+#ifdef __KERNEL__
+
+#define SPLICE_F_PACKET (0x1000) /* pipe buffers have to be packetized */
+
+#endif
/*
* Passed to the actors
*/

2015-12-15 17:29:22

by Stanislav Kinsburskiy

[permalink] [raw]
Subject: [PATCH RFC 3/3] splice: add support of splicing to packetized pipe

This patch uses SPLICE_F_PACKET as a flag, representing packetized pipe.
In splice_to_pipe() this flag is converted into PIPE_BUF_FLAG_PACKET on pipe
buffer.

Signed-off-by: Stanislav Kinsburskiy <[email protected]>
---
fs/splice.c | 8 ++++++++
1 file changed, 8 insertions(+)

diff --git a/fs/splice.c b/fs/splice.c
index 4cf700d..d698fb2 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -210,6 +210,8 @@ ssize_t splice_to_pipe(struct pipe_inode_info *pipe,
buf->ops = spd->ops;
if (spd->flags & SPLICE_F_GIFT)
buf->flags |= PIPE_BUF_FLAG_GIFT;
+ if (spd->flags & SPLICE_F_PACKET)
+ buf->flags |= PIPE_BUF_FLAG_PACKET;

pipe->nrbufs++;
page_nr++;
@@ -1420,6 +1422,9 @@ static long do_splice(struct file *in, loff_t __user *off_in,
offset = in->f_pos;
}

+ if (is_packetized(out))
+ flags |= SPLICE_F_PACKET;
+
ret = do_splice_to(in, &offset, opipe, len, flags);

if (!off_in)
@@ -1609,6 +1614,9 @@ static long vmsplice_to_pipe(struct file *file, const struct iovec __user *iov,
if (splice_grow_spd(pipe, &spd))
return -ENOMEM;

+ if (is_packetized(file))
+ spd.flags |= SPLICE_F_PACKET;
+
spd.nr_pages = get_iovec_page_array(iov, nr_segs, spd.pages,
spd.partial, false,
spd.nr_pages_max);