Skip to content

Commit

Permalink
pipe: change /proc/sys/fs/pipe-max-pages to byte sized interface
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Jens Axboe committed Jun 3, 2010
1 parent 419f836 commit ff9da69
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 17 deletions.
54 changes: 42 additions & 12 deletions fs/pipe.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,14 @@

/*
* The max size that a non-root user is allowed to grow the pipe. Can
* be set by root in /proc/sys/fs/pipe-max-pages
* be set by root in /proc/sys/fs/pipe-max-size
*/
unsigned int pipe_max_pages = PIPE_DEF_BUFFERS * 16;
unsigned int pipe_max_size = 1048576;

/*
* Minimum pipe size, as required by POSIX
*/
unsigned int pipe_min_size = PAGE_SIZE;

/*
* We use a start+len construction, which provides full use of the
Expand Down Expand Up @@ -1156,6 +1161,35 @@ static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long nr_pages)
return nr_pages * PAGE_SIZE;
}

/*
* Currently we rely on the pipe array holding a power-of-2 number
* of pages.
*/
static inline unsigned int round_pipe_size(unsigned int size)
{
unsigned long nr_pages;

nr_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
return roundup_pow_of_two(nr_pages) << PAGE_SHIFT;
}

/*
* This should work even if CONFIG_PROC_FS isn't set, as proc_dointvec_minmax
* will return an error.
*/
int pipe_proc_fn(struct ctl_table *table, int write, void __user *buf,
size_t *lenp, loff_t *ppos)
{
int ret;

ret = proc_dointvec_minmax(table, write, buf, lenp, ppos);
if (ret < 0 || !write)
return ret;

pipe_max_size = round_pipe_size(pipe_max_size);
return ret;
}

long pipe_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct pipe_inode_info *pipe;
Expand All @@ -1169,23 +1203,19 @@ long pipe_fcntl(struct file *file, unsigned int cmd, unsigned long arg)

switch (cmd) {
case F_SETPIPE_SZ: {
unsigned long nr_pages;
unsigned int size, nr_pages;

/*
* Currently the array must be a power-of-2 size, so adjust
* upwards if needed.
*/
nr_pages = (arg + PAGE_SIZE - 1) >> PAGE_SHIFT;
nr_pages = roundup_pow_of_two(nr_pages);
size = round_pipe_size(arg);
nr_pages = size >> PAGE_SHIFT;

if (!capable(CAP_SYS_RESOURCE) && nr_pages > pipe_max_pages) {
if (!capable(CAP_SYS_RESOURCE) && size > pipe_max_size) {
ret = -EPERM;
goto out;
} else if (nr_pages < 1) {
} else if (nr_pages < PAGE_SIZE) {
ret = -EINVAL;
goto out;
}
ret = pipe_set_size(pipe, arg);
ret = pipe_set_size(pipe, nr_pages);
break;
}
case F_GETPIPE_SZ:
Expand Down
4 changes: 3 additions & 1 deletion include/linux/pipe_fs_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,9 @@ void pipe_lock(struct pipe_inode_info *);
void pipe_unlock(struct pipe_inode_info *);
void pipe_double_lock(struct pipe_inode_info *, struct pipe_inode_info *);

extern unsigned int pipe_max_pages;
extern unsigned int pipe_max_size, pipe_min_size;
int pipe_proc_fn(struct ctl_table *, int, void __user *, size_t *, loff_t *);


/* Drop the inode semaphore and wait for a pipe event, atomically */
void pipe_wait(struct pipe_inode_info *pipe);
Expand Down
8 changes: 4 additions & 4 deletions kernel/sysctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1471,12 +1471,12 @@ static struct ctl_table fs_table[] = {
},
#endif
{
.procname = "pipe-max-pages",
.data = &pipe_max_pages,
.procname = "pipe-max-size",
.data = &pipe_max_size,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_minmax,
.extra1 = &two,
.proc_handler = &pipe_proc_fn,
.extra1 = &pipe_min_size,
},
/*
* NOTE: do not add new entries to this table unless you have read
Expand Down

0 comments on commit ff9da69

Please sign in to comment.