aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2006-06-26 03:25:55 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-06-26 12:58:25 -0400
commit99f895518368252ba862cc15ce4eb98ebbe1bec6 (patch)
treea9dcc01963221d1fd6a7e357b95d361ebfe91c6d /kernel
parent8578cea7509cbdec25b31d08b48a92fcc3b1a9e3 (diff)
[PATCH] proc: don't lock task_structs indefinitely
Every inode in /proc holds a reference to a struct task_struct. If a directory or file is opened and remains open after the the task exits this pinning continues. With 8K stacks on a 32bit machine the amount pinned per file descriptor is about 10K. Normally I would figure a reasonable per user process limit is about 100 processes. With 80 processes, with a 1000 file descriptors each I can trigger the 00M killer on a 32bit kernel, because I have pinned about 800MB of useless data. This patch replaces the struct task_struct pointer with a pointer to a struct task_ref which has a struct task_struct pointer. The so the pinning of dead tasks does not happen. The code now has to contend with the fact that the task may now exit at any time. Which is a little but not muh more complicated. With this change it takes about 1000 processes each opening up 1000 file descriptors before I can trigger the OOM killer. Much better. [mlp@google.com: task_mmu small fixes] Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Cc: Trond Myklebust <trond.myklebust@fys.uio.no> Cc: Paul Jackson <pj@sgi.com> Cc: Oleg Nesterov <oleg@tv-sign.ru> Cc: Albert Cahalan <acahalan@gmail.com> Signed-off-by: Prasanna Meda <mlp@google.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/cpuset.c27
1 files changed, 20 insertions, 7 deletions
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index b602f73fb38d..3e991c0c02e2 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -50,6 +50,7 @@
50#include <linux/time.h> 50#include <linux/time.h>
51#include <linux/backing-dev.h> 51#include <linux/backing-dev.h>
52#include <linux/sort.h> 52#include <linux/sort.h>
53#include <linux/task_ref.h>
53 54
54#include <asm/uaccess.h> 55#include <asm/uaccess.h>
55#include <asm/atomic.h> 56#include <asm/atomic.h>
@@ -2442,31 +2443,43 @@ void __cpuset_memory_pressure_bump(void)
2442 */ 2443 */
2443static int proc_cpuset_show(struct seq_file *m, void *v) 2444static int proc_cpuset_show(struct seq_file *m, void *v)
2444{ 2445{
2446 struct task_ref *tref;
2445 struct task_struct *tsk; 2447 struct task_struct *tsk;
2446 char *buf; 2448 char *buf;
2447 int retval = 0; 2449 int retval;
2448 2450
2451 retval = -ENOMEM;
2449 buf = kmalloc(PAGE_SIZE, GFP_KERNEL); 2452 buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
2450 if (!buf) 2453 if (!buf)
2451 return -ENOMEM; 2454 goto out;
2455
2456 retval = -ESRCH;
2457 tref = m->private;
2458 tsk = get_tref_task(tref);
2459 if (!tsk)
2460 goto out_free;
2452 2461
2453 tsk = m->private; 2462 retval = -EINVAL;
2454 mutex_lock(&manage_mutex); 2463 mutex_lock(&manage_mutex);
2464
2455 retval = cpuset_path(tsk->cpuset, buf, PAGE_SIZE); 2465 retval = cpuset_path(tsk->cpuset, buf, PAGE_SIZE);
2456 if (retval < 0) 2466 if (retval < 0)
2457 goto out; 2467 goto out_unlock;
2458 seq_puts(m, buf); 2468 seq_puts(m, buf);
2459 seq_putc(m, '\n'); 2469 seq_putc(m, '\n');
2460out: 2470out_unlock:
2461 mutex_unlock(&manage_mutex); 2471 mutex_unlock(&manage_mutex);
2472 put_task_struct(tsk);
2473out_free:
2462 kfree(buf); 2474 kfree(buf);
2475out:
2463 return retval; 2476 return retval;
2464} 2477}
2465 2478
2466static int cpuset_open(struct inode *inode, struct file *file) 2479static int cpuset_open(struct inode *inode, struct file *file)
2467{ 2480{
2468 struct task_struct *tsk = PROC_I(inode)->task; 2481 struct task_ref *tref = PROC_I(inode)->tref;
2469 return single_open(file, proc_cpuset_show, tsk); 2482 return single_open(file, proc_cpuset_show, tref);
2470} 2483}
2471 2484
2472struct file_operations proc_cpuset_operations = { 2485struct file_operations proc_cpuset_operations = {