aboutsummaryrefslogtreecommitdiffstats
path: root/fs/pipe.c
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2010-07-05 02:46:08 -0400
committerPaul Mundt <lethal@linux-sh.org>2010-07-05 02:46:08 -0400
commit285eba57db7bd7d7c3c5929fb8621fdcaaea1b00 (patch)
treea9e7f0563cef296b24c53b20dbb388ec5c210172 /fs/pipe.c
parent1c14e6cecb1811543b1016f27e5d308fbea8c08a (diff)
parent815c4163b6c8ebf8152f42b0a5fd015cfdcedc78 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Conflicts: include/linux/serial_sci.h Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'fs/pipe.c')
-rw-r--r--fs/pipe.c93
1 files changed, 65 insertions, 28 deletions
diff --git a/fs/pipe.c b/fs/pipe.c
index db6eaaba0dd8..279eef96c51c 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
@@ -1118,26 +1123,20 @@ SYSCALL_DEFINE1(pipe, int __user *, fildes)
1118 * Allocate a new array of pipe buffers and copy the info over. Returns the 1123 * Allocate a new array of pipe buffers and copy the info over. Returns the
1119 * pipe size if successful, or return -ERROR on error. 1124 * pipe size if successful, or return -ERROR on error.
1120 */ 1125 */
1121static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long arg) 1126static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long nr_pages)
1122{ 1127{
1123 struct pipe_buffer *bufs; 1128 struct pipe_buffer *bufs;
1124 1129
1125 /* 1130 /*
1126 * Must be a power-of-2 currently
1127 */
1128 if (!is_power_of_2(arg))
1129 return -EINVAL;
1130
1131 /*
1132 * We can shrink the pipe, if arg >= pipe->nrbufs. Since we don't 1131 * We can shrink the pipe, if arg >= pipe->nrbufs. Since we don't
1133 * expect a lot of shrink+grow operations, just free and allocate 1132 * expect a lot of shrink+grow operations, just free and allocate
1134 * again like we would do for growing. If the pipe currently 1133 * again like we would do for growing. If the pipe currently
1135 * contains more buffers than arg, then return busy. 1134 * contains more buffers than arg, then return busy.
1136 */ 1135 */
1137 if (arg < pipe->nrbufs) 1136 if (nr_pages < pipe->nrbufs)
1138 return -EBUSY; 1137 return -EBUSY;
1139 1138
1140 bufs = kcalloc(arg, sizeof(struct pipe_buffer), GFP_KERNEL); 1139 bufs = kcalloc(nr_pages, sizeof(struct pipe_buffer), GFP_KERNEL);
1141 if (unlikely(!bufs)) 1140 if (unlikely(!bufs))
1142 return -ENOMEM; 1141 return -ENOMEM;
1143 1142
@@ -1146,20 +1145,56 @@ static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long arg)
1146 * and adjust the indexes. 1145 * and adjust the indexes.
1147 */ 1146 */
1148 if (pipe->nrbufs) { 1147 if (pipe->nrbufs) {
1149 const unsigned int tail = pipe->nrbufs & (pipe->buffers - 1); 1148 unsigned int tail;
1150 const unsigned int head = pipe->nrbufs - tail; 1149 unsigned int head;
1150
1151 tail = pipe->curbuf + pipe->nrbufs;
1152 if (tail < pipe->buffers)
1153 tail = 0;
1154 else
1155 tail &= (pipe->buffers - 1);
1151 1156
1157 head = pipe->nrbufs - tail;
1152 if (head) 1158 if (head)
1153 memcpy(bufs, pipe->bufs + pipe->curbuf, head * sizeof(struct pipe_buffer)); 1159 memcpy(bufs, pipe->bufs + pipe->curbuf, head * sizeof(struct pipe_buffer));
1154 if (tail) 1160 if (tail)
1155 memcpy(bufs + head, pipe->bufs + pipe->curbuf, tail * sizeof(struct pipe_buffer)); 1161 memcpy(bufs + head, pipe->bufs, tail * sizeof(struct pipe_buffer));
1156 } 1162 }
1157 1163
1158 pipe->curbuf = 0; 1164 pipe->curbuf = 0;
1159 kfree(pipe->bufs); 1165 kfree(pipe->bufs);
1160 pipe->bufs = bufs; 1166 pipe->bufs = bufs;
1161 pipe->buffers = arg; 1167 pipe->buffers = nr_pages;
1162 return arg; 1168 return nr_pages * PAGE_SIZE;
1169}
1170
1171/*
1172 * Currently we rely on the pipe array holding a power-of-2 number
1173 * of pages.
1174 */
1175static inline unsigned int round_pipe_size(unsigned int size)
1176{
1177 unsigned long nr_pages;
1178
1179 nr_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
1180 return roundup_pow_of_two(nr_pages) << PAGE_SHIFT;
1181}
1182
1183/*
1184 * This should work even if CONFIG_PROC_FS isn't set, as proc_dointvec_minmax
1185 * will return an error.
1186 */
1187int pipe_proc_fn(struct ctl_table *table, int write, void __user *buf,
1188 size_t *lenp, loff_t *ppos)
1189{
1190 int ret;
1191
1192 ret = proc_dointvec_minmax(table, write, buf, lenp, ppos);
1193 if (ret < 0 || !write)
1194 return ret;
1195
1196 pipe_max_size = round_pipe_size(pipe_max_size);
1197 return ret;
1163} 1198}
1164 1199
1165long pipe_fcntl(struct file *file, unsigned int cmd, unsigned long arg) 1200long pipe_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
@@ -1174,23 +1209,25 @@ long pipe_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
1174 mutex_lock(&pipe->inode->i_mutex); 1209 mutex_lock(&pipe->inode->i_mutex);
1175 1210
1176 switch (cmd) { 1211 switch (cmd) {
1177 case F_SETPIPE_SZ: 1212 case F_SETPIPE_SZ: {
1178 if (!capable(CAP_SYS_ADMIN) && arg > pipe_max_pages) { 1213 unsigned int size, nr_pages;
1179 ret = -EINVAL; 1214
1215 size = round_pipe_size(arg);
1216 nr_pages = size >> PAGE_SHIFT;
1217
1218 ret = -EINVAL;
1219 if (!nr_pages)
1180 goto out; 1220 goto out;
1181 } 1221
1182 /* 1222 if (!capable(CAP_SYS_RESOURCE) && size > pipe_max_size) {
1183 * The pipe needs to be at least 2 pages large to 1223 ret = -EPERM;
1184 * guarantee POSIX behaviour.
1185 */
1186 if (arg < 2) {
1187 ret = -EINVAL;
1188 goto out; 1224 goto out;
1189 } 1225 }
1190 ret = pipe_set_size(pipe, arg); 1226 ret = pipe_set_size(pipe, nr_pages);
1191 break; 1227 break;
1228 }
1192 case F_GETPIPE_SZ: 1229 case F_GETPIPE_SZ:
1193 ret = pipe->buffers; 1230 ret = pipe->buffers * PAGE_SIZE;
1194 break; 1231 break;
1195 default: 1232 default:
1196 ret = -EINVAL; 1233 ret = -EINVAL;