aboutsummaryrefslogtreecommitdiffstats
path: root/fs/pipe.c
diff options
context:
space:
mode:
authorJens Axboe <jaxboe@fusionio.com>2010-06-03 08:54:39 -0400
committerJens Axboe <jaxboe@fusionio.com>2010-06-03 08:54:39 -0400
commitff9da691c0498ff81fdd014e7a0731dab2337dac (patch)
tree429dc9ea36c9927954ed3a32f03d28730e693c8b /fs/pipe.c
parent419f8367ea37e5adc5d95479e8fd5554b92b49fe (diff)
pipe: change /proc/sys/fs/pipe-max-pages to byte sized interface
This changes the interface to be based on bytes instead. The API matches that of F_SETPIPE_SZ in that it rounds up the passed in size so that the resulting page array is a power-of-2 in size. The proc file is renamed to /proc/sys/fs/pipe-max-size to reflect this change. Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
Diffstat (limited to 'fs/pipe.c')
-rw-r--r--fs/pipe.c54
1 files changed, 42 insertions, 12 deletions
diff --git a/fs/pipe.c b/fs/pipe.c
index f98fae3e36b0..69c4c7c13ea9 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -26,9 +26,14 @@
26 26
27/* 27/*
28 * The max size that a non-root user is allowed to grow the pipe. Can 28 * The max size that a non-root user is allowed to grow the pipe. Can
29 * be set by root in /proc/sys/fs/pipe-max-pages 29 * be set by root in /proc/sys/fs/pipe-max-size
30 */ 30 */
31unsigned int pipe_max_pages = PIPE_DEF_BUFFERS * 16; 31unsigned int pipe_max_size = 1048576;
32
33/*
34 * Minimum pipe size, as required by POSIX
35 */
36unsigned int pipe_min_size = PAGE_SIZE;
32 37
33/* 38/*
34 * We use a start+len construction, which provides full use of the 39 * We use a start+len construction, which provides full use of the
@@ -1156,6 +1161,35 @@ static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long nr_pages)
1156 return nr_pages * PAGE_SIZE; 1161 return nr_pages * PAGE_SIZE;
1157} 1162}
1158 1163
1164/*
1165 * Currently we rely on the pipe array holding a power-of-2 number
1166 * of pages.
1167 */
1168static inline unsigned int round_pipe_size(unsigned int size)
1169{
1170 unsigned long nr_pages;
1171
1172 nr_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
1173 return roundup_pow_of_two(nr_pages) << PAGE_SHIFT;
1174}
1175
1176/*
1177 * This should work even if CONFIG_PROC_FS isn't set, as proc_dointvec_minmax
1178 * will return an error.
1179 */
1180int pipe_proc_fn(struct ctl_table *table, int write, void __user *buf,
1181 size_t *lenp, loff_t *ppos)
1182{
1183 int ret;
1184
1185 ret = proc_dointvec_minmax(table, write, buf, lenp, ppos);
1186 if (ret < 0 || !write)
1187 return ret;
1188
1189 pipe_max_size = round_pipe_size(pipe_max_size);
1190 return ret;
1191}
1192
1159long pipe_fcntl(struct file *file, unsigned int cmd, unsigned long arg) 1193long pipe_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
1160{ 1194{
1161 struct pipe_inode_info *pipe; 1195 struct pipe_inode_info *pipe;
@@ -1169,23 +1203,19 @@ long pipe_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
1169 1203
1170 switch (cmd) { 1204 switch (cmd) {
1171 case F_SETPIPE_SZ: { 1205 case F_SETPIPE_SZ: {
1172 unsigned long nr_pages; 1206 unsigned int size, nr_pages;
1173 1207
1174 /* 1208 size = round_pipe_size(arg);
1175 * Currently the array must be a power-of-2 size, so adjust 1209 nr_pages = size >> PAGE_SHIFT;
1176 * upwards if needed.
1177 */
1178 nr_pages = (arg + PAGE_SIZE - 1) >> PAGE_SHIFT;
1179 nr_pages = roundup_pow_of_two(nr_pages);
1180 1210
1181 if (!capable(CAP_SYS_RESOURCE) && nr_pages > pipe_max_pages) { 1211 if (!capable(CAP_SYS_RESOURCE) && size > pipe_max_size) {
1182 ret = -EPERM; 1212 ret = -EPERM;
1183 goto out; 1213 goto out;
1184 } else if (nr_pages < 1) { 1214 } else if (nr_pages < PAGE_SIZE) {
1185 ret = -EINVAL; 1215 ret = -EINVAL;
1186 goto out; 1216 goto out;
1187 } 1217 }
1188 ret = pipe_set_size(pipe, arg); 1218 ret = pipe_set_size(pipe, nr_pages);
1189 break; 1219 break;
1190 } 1220 }
1191 case F_GETPIPE_SZ: 1221 case F_GETPIPE_SZ: