aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--fs/pipe.c54
-rw-r--r--include/linux/pipe_fs_i.h4
-rw-r--r--kernel/sysctl.c8
3 files changed, 49 insertions, 17 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:
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h
index 16de3933c45e..445796945ac9 100644
--- a/include/linux/pipe_fs_i.h
+++ b/include/linux/pipe_fs_i.h
@@ -139,7 +139,9 @@ void pipe_lock(struct pipe_inode_info *);
139void pipe_unlock(struct pipe_inode_info *); 139void pipe_unlock(struct pipe_inode_info *);
140void pipe_double_lock(struct pipe_inode_info *, struct pipe_inode_info *); 140void pipe_double_lock(struct pipe_inode_info *, struct pipe_inode_info *);
141 141
142extern unsigned int pipe_max_pages; 142extern unsigned int pipe_max_size, pipe_min_size;
143int pipe_proc_fn(struct ctl_table *, int, void __user *, size_t *, loff_t *);
144
143 145
144/* Drop the inode semaphore and wait for a pipe event, atomically */ 146/* Drop the inode semaphore and wait for a pipe event, atomically */
145void pipe_wait(struct pipe_inode_info *pipe); 147void pipe_wait(struct pipe_inode_info *pipe);
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 997080f00e0b..d24f761f4876 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -1471,12 +1471,12 @@ static struct ctl_table fs_table[] = {
1471 }, 1471 },
1472#endif 1472#endif
1473 { 1473 {
1474 .procname = "pipe-max-pages", 1474 .procname = "pipe-max-size",
1475 .data = &pipe_max_pages, 1475 .data = &pipe_max_size,
1476 .maxlen = sizeof(int), 1476 .maxlen = sizeof(int),
1477 .mode = 0644, 1477 .mode = 0644,
1478 .proc_handler = &proc_dointvec_minmax, 1478 .proc_handler = &pipe_proc_fn,
1479 .extra1 = &two, 1479 .extra1 = &pipe_min_size,
1480 }, 1480 },
1481/* 1481/*
1482 * NOTE: do not add new entries to this table unless you have read 1482 * NOTE: do not add new entries to this table unless you have read