aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-04-29 16:12:42 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-05-07 11:56:36 -0400
commitbeed6c2e00e0dde6722b590e6a02c20248224c68 (patch)
treeee6dbd600c8a30e70197a0b94682c81ca7fec6ce
parent1cb1976ecd018b02825e5a0fba06ffe95bdaedc6 (diff)
pipes: add a "packetized pipe" mode for writing
commit 9883035ae7edef3ec62ad215611cb8e17d6a1a5d upstream. The actual internal pipe implementation is already really about individual packets (called "pipe buffers"), and this simply exposes that as a special packetized mode. When we are in the packetized mode (marked by O_DIRECT as suggested by Alan Cox), a write() on a pipe will not merge the new data with previous writes, so each write will get a pipe buffer of its own. The pipe buffer is then marked with the PIPE_BUF_FLAG_PACKET flag, which in turn will tell the reader side to break the read at that boundary (and throw away any partial packet contents that do not fit in the read buffer). End result: as long as you do writes less than PIPE_BUF in size (so that the pipe doesn't have to split them up), you can now treat the pipe as a packet interface, where each read() system call will read one packet at a time. You can just use a sufficiently big read buffer (PIPE_BUF is sufficient, since bigger than that doesn't guarantee atomicity anyway), and the return value of the read() will naturally give you the size of the packet. NOTE! We do not support zero-sized packets, and zero-sized reads and writes to a pipe continue to be no-ops. Also note that big packets will currently be split at write time, but that the size at which that happens is not really specified (except that it's bigger than PIPE_BUF). Currently that limit is the system page size, but we might want to explicitly support bigger packets some day. The main user for this is going to be the autofs packet interface, allowing us to stop having to care so deeply about exact packet sizes (which have had bugs with 32/64-bit compatibility modes). But user space can create packetized pipes with "pipe2(fd, O_DIRECT)", which will fail with an EINVAL on kernels that do not support this interface. Tested-by: Michael Tokarev <mjt@tls.msk.ru> Cc: Alan Cox <alan@lxorguk.ukuu.org.uk> Cc: David Miller <davem@davemloft.net> Cc: Ian Kent <raven@themaw.net> Cc: Thomas Meyer <thomas@m3y3r.de> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--fs/pipe.c31
-rw-r--r--include/linux/pipe_fs_i.h1
2 files changed, 30 insertions, 2 deletions
diff --git a/fs/pipe.c b/fs/pipe.c
index da42f7db50d..0499a96287a 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -345,6 +345,16 @@ static const struct pipe_buf_operations anon_pipe_buf_ops = {
345 .get = generic_pipe_buf_get, 345 .get = generic_pipe_buf_get,
346}; 346};
347 347
348static const struct pipe_buf_operations packet_pipe_buf_ops = {
349 .can_merge = 0,
350 .map = generic_pipe_buf_map,
351 .unmap = generic_pipe_buf_unmap,
352 .confirm = generic_pipe_buf_confirm,
353 .release = anon_pipe_buf_release,
354 .steal = generic_pipe_buf_steal,
355 .get = generic_pipe_buf_get,
356};
357
348static ssize_t 358static ssize_t
349pipe_read(struct kiocb *iocb, const struct iovec *_iov, 359pipe_read(struct kiocb *iocb, const struct iovec *_iov,
350 unsigned long nr_segs, loff_t pos) 360 unsigned long nr_segs, loff_t pos)
@@ -406,6 +416,13 @@ redo:
406 ret += chars; 416 ret += chars;
407 buf->offset += chars; 417 buf->offset += chars;
408 buf->len -= chars; 418 buf->len -= chars;
419
420 /* Was it a packet buffer? Clean up and exit */
421 if (buf->flags & PIPE_BUF_FLAG_PACKET) {
422 total_len = chars;
423 buf->len = 0;
424 }
425
409 if (!buf->len) { 426 if (!buf->len) {
410 buf->ops = NULL; 427 buf->ops = NULL;
411 ops->release(pipe, buf); 428 ops->release(pipe, buf);
@@ -458,6 +475,11 @@ redo:
458 return ret; 475 return ret;
459} 476}
460 477
478static inline int is_packetized(struct file *file)
479{
480 return (file->f_flags & O_DIRECT) != 0;
481}
482
461static ssize_t 483static ssize_t
462pipe_write(struct kiocb *iocb, const struct iovec *_iov, 484pipe_write(struct kiocb *iocb, const struct iovec *_iov,
463 unsigned long nr_segs, loff_t ppos) 485 unsigned long nr_segs, loff_t ppos)
@@ -592,6 +614,11 @@ redo2:
592 buf->ops = &anon_pipe_buf_ops; 614 buf->ops = &anon_pipe_buf_ops;
593 buf->offset = 0; 615 buf->offset = 0;
594 buf->len = chars; 616 buf->len = chars;
617 buf->flags = 0;
618 if (is_packetized(filp)) {
619 buf->ops = &packet_pipe_buf_ops;
620 buf->flags = PIPE_BUF_FLAG_PACKET;
621 }
595 pipe->nrbufs = ++bufs; 622 pipe->nrbufs = ++bufs;
596 pipe->tmp_page = NULL; 623 pipe->tmp_page = NULL;
597 624
@@ -1012,7 +1039,7 @@ struct file *create_write_pipe(int flags)
1012 goto err_dentry; 1039 goto err_dentry;
1013 f->f_mapping = inode->i_mapping; 1040 f->f_mapping = inode->i_mapping;
1014 1041
1015 f->f_flags = O_WRONLY | (flags & O_NONBLOCK); 1042 f->f_flags = O_WRONLY | (flags & (O_NONBLOCK | O_DIRECT));
1016 f->f_version = 0; 1043 f->f_version = 0;
1017 1044
1018 return f; 1045 return f;
@@ -1056,7 +1083,7 @@ int do_pipe_flags(int *fd, int flags)
1056 int error; 1083 int error;
1057 int fdw, fdr; 1084 int fdw, fdr;
1058 1085
1059 if (flags & ~(O_CLOEXEC | O_NONBLOCK)) 1086 if (flags & ~(O_CLOEXEC | O_NONBLOCK | O_DIRECT))
1060 return -EINVAL; 1087 return -EINVAL;
1061 1088
1062 fw = create_write_pipe(flags); 1089 fw = create_write_pipe(flags);
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h
index 77257c92155..0072a5366e9 100644
--- a/include/linux/pipe_fs_i.h
+++ b/include/linux/pipe_fs_i.h
@@ -8,6 +8,7 @@
8#define PIPE_BUF_FLAG_LRU 0x01 /* page is on the LRU */ 8#define PIPE_BUF_FLAG_LRU 0x01 /* page is on the LRU */
9#define PIPE_BUF_FLAG_ATOMIC 0x02 /* was atomically mapped */ 9#define PIPE_BUF_FLAG_ATOMIC 0x02 /* was atomically mapped */
10#define PIPE_BUF_FLAG_GIFT 0x04 /* page is a gift */ 10#define PIPE_BUF_FLAG_GIFT 0x04 /* page is a gift */
11#define PIPE_BUF_FLAG_PACKET 0x08 /* read() as a packet */
11 12
12/** 13/**
13 * struct pipe_buffer - a linux kernel pipe buffer 14 * struct pipe_buffer - a linux kernel pipe buffer