diff options
Diffstat (limited to 'recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.17/0117-pipes-add-a-packetized-pipe-mode-for-writing.patch')
-rw-r--r-- | recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.17/0117-pipes-add-a-packetized-pipe-mode-for-writing.patch | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.17/0117-pipes-add-a-packetized-pipe-mode-for-writing.patch b/recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.17/0117-pipes-add-a-packetized-pipe-mode-for-writing.patch new file mode 100644 index 00000000..e25c9d0e --- /dev/null +++ b/recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.17/0117-pipes-add-a-packetized-pipe-mode-for-writing.patch | |||
@@ -0,0 +1,143 @@ | |||
1 | From 458c33bdfc9d408f94038a4db0544ab348d0d96d Mon Sep 17 00:00:00 2001 | ||
2 | From: Linus Torvalds <torvalds@linux-foundation.org> | ||
3 | Date: Sun, 29 Apr 2012 13:12:42 -0700 | ||
4 | Subject: [PATCH 117/165] pipes: add a "packetized pipe" mode for writing | ||
5 | |||
6 | commit 9883035ae7edef3ec62ad215611cb8e17d6a1a5d upstream. | ||
7 | |||
8 | The actual internal pipe implementation is already really about | ||
9 | individual packets (called "pipe buffers"), and this simply exposes that | ||
10 | as a special packetized mode. | ||
11 | |||
12 | When we are in the packetized mode (marked by O_DIRECT as suggested by | ||
13 | Alan Cox), a write() on a pipe will not merge the new data with previous | ||
14 | writes, so each write will get a pipe buffer of its own. The pipe | ||
15 | buffer is then marked with the PIPE_BUF_FLAG_PACKET flag, which in turn | ||
16 | will tell the reader side to break the read at that boundary (and throw | ||
17 | away any partial packet contents that do not fit in the read buffer). | ||
18 | |||
19 | End result: as long as you do writes less than PIPE_BUF in size (so that | ||
20 | the pipe doesn't have to split them up), you can now treat the pipe as a | ||
21 | packet interface, where each read() system call will read one packet at | ||
22 | a time. You can just use a sufficiently big read buffer (PIPE_BUF is | ||
23 | sufficient, since bigger than that doesn't guarantee atomicity anyway), | ||
24 | and the return value of the read() will naturally give you the size of | ||
25 | the packet. | ||
26 | |||
27 | NOTE! We do not support zero-sized packets, and zero-sized reads and | ||
28 | writes to a pipe continue to be no-ops. Also note that big packets will | ||
29 | currently be split at write time, but that the size at which that | ||
30 | happens is not really specified (except that it's bigger than PIPE_BUF). | ||
31 | Currently that limit is the system page size, but we might want to | ||
32 | explicitly support bigger packets some day. | ||
33 | |||
34 | The main user for this is going to be the autofs packet interface, | ||
35 | allowing us to stop having to care so deeply about exact packet sizes | ||
36 | (which have had bugs with 32/64-bit compatibility modes). But user | ||
37 | space can create packetized pipes with "pipe2(fd, O_DIRECT)", which will | ||
38 | fail with an EINVAL on kernels that do not support this interface. | ||
39 | |||
40 | Tested-by: Michael Tokarev <mjt@tls.msk.ru> | ||
41 | Cc: Alan Cox <alan@lxorguk.ukuu.org.uk> | ||
42 | Cc: David Miller <davem@davemloft.net> | ||
43 | Cc: Ian Kent <raven@themaw.net> | ||
44 | Cc: Thomas Meyer <thomas@m3y3r.de> | ||
45 | Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> | ||
46 | Signed-off-by: Ben Hutchings <ben@decadent.org.uk> | ||
47 | --- | ||
48 | fs/pipe.c | 31 +++++++++++++++++++++++++++++-- | ||
49 | include/linux/pipe_fs_i.h | 1 + | ||
50 | 2 files changed, 30 insertions(+), 2 deletions(-) | ||
51 | |||
52 | diff --git a/fs/pipe.c b/fs/pipe.c | ||
53 | index 4065f07..05ed5ca 100644 | ||
54 | --- a/fs/pipe.c | ||
55 | +++ b/fs/pipe.c | ||
56 | @@ -345,6 +345,16 @@ static const struct pipe_buf_operations anon_pipe_buf_ops = { | ||
57 | .get = generic_pipe_buf_get, | ||
58 | }; | ||
59 | |||
60 | +static const struct pipe_buf_operations packet_pipe_buf_ops = { | ||
61 | + .can_merge = 0, | ||
62 | + .map = generic_pipe_buf_map, | ||
63 | + .unmap = generic_pipe_buf_unmap, | ||
64 | + .confirm = generic_pipe_buf_confirm, | ||
65 | + .release = anon_pipe_buf_release, | ||
66 | + .steal = generic_pipe_buf_steal, | ||
67 | + .get = generic_pipe_buf_get, | ||
68 | +}; | ||
69 | + | ||
70 | static ssize_t | ||
71 | pipe_read(struct kiocb *iocb, const struct iovec *_iov, | ||
72 | unsigned long nr_segs, loff_t pos) | ||
73 | @@ -406,6 +416,13 @@ redo: | ||
74 | ret += chars; | ||
75 | buf->offset += chars; | ||
76 | buf->len -= chars; | ||
77 | + | ||
78 | + /* Was it a packet buffer? Clean up and exit */ | ||
79 | + if (buf->flags & PIPE_BUF_FLAG_PACKET) { | ||
80 | + total_len = chars; | ||
81 | + buf->len = 0; | ||
82 | + } | ||
83 | + | ||
84 | if (!buf->len) { | ||
85 | buf->ops = NULL; | ||
86 | ops->release(pipe, buf); | ||
87 | @@ -458,6 +475,11 @@ redo: | ||
88 | return ret; | ||
89 | } | ||
90 | |||
91 | +static inline int is_packetized(struct file *file) | ||
92 | +{ | ||
93 | + return (file->f_flags & O_DIRECT) != 0; | ||
94 | +} | ||
95 | + | ||
96 | static ssize_t | ||
97 | pipe_write(struct kiocb *iocb, const struct iovec *_iov, | ||
98 | unsigned long nr_segs, loff_t ppos) | ||
99 | @@ -592,6 +614,11 @@ redo2: | ||
100 | buf->ops = &anon_pipe_buf_ops; | ||
101 | buf->offset = 0; | ||
102 | buf->len = chars; | ||
103 | + buf->flags = 0; | ||
104 | + if (is_packetized(filp)) { | ||
105 | + buf->ops = &packet_pipe_buf_ops; | ||
106 | + buf->flags = PIPE_BUF_FLAG_PACKET; | ||
107 | + } | ||
108 | pipe->nrbufs = ++bufs; | ||
109 | pipe->tmp_page = NULL; | ||
110 | |||
111 | @@ -1012,7 +1039,7 @@ struct file *create_write_pipe(int flags) | ||
112 | goto err_dentry; | ||
113 | f->f_mapping = inode->i_mapping; | ||
114 | |||
115 | - f->f_flags = O_WRONLY | (flags & O_NONBLOCK); | ||
116 | + f->f_flags = O_WRONLY | (flags & (O_NONBLOCK | O_DIRECT)); | ||
117 | f->f_version = 0; | ||
118 | |||
119 | return f; | ||
120 | @@ -1056,7 +1083,7 @@ int do_pipe_flags(int *fd, int flags) | ||
121 | int error; | ||
122 | int fdw, fdr; | ||
123 | |||
124 | - if (flags & ~(O_CLOEXEC | O_NONBLOCK)) | ||
125 | + if (flags & ~(O_CLOEXEC | O_NONBLOCK | O_DIRECT)) | ||
126 | return -EINVAL; | ||
127 | |||
128 | fw = create_write_pipe(flags); | ||
129 | diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h | ||
130 | index 77257c9..0072a53 100644 | ||
131 | --- a/include/linux/pipe_fs_i.h | ||
132 | +++ b/include/linux/pipe_fs_i.h | ||
133 | @@ -8,6 +8,7 @@ | ||
134 | #define PIPE_BUF_FLAG_LRU 0x01 /* page is on the LRU */ | ||
135 | #define PIPE_BUF_FLAG_ATOMIC 0x02 /* was atomically mapped */ | ||
136 | #define PIPE_BUF_FLAG_GIFT 0x04 /* page is a gift */ | ||
137 | +#define PIPE_BUF_FLAG_PACKET 0x08 /* read() as a packet */ | ||
138 | |||
139 | /** | ||
140 | * struct pipe_buffer - a linux kernel pipe buffer | ||
141 | -- | ||
142 | 1.7.7.6 | ||
143 | |||