summaryrefslogtreecommitdiffstats
path: root/kernel/exit.c
diff options
context:
space:
mode:
authorWu Fengguang <fengguang.wu@intel.com>2011-04-05 13:21:19 -0600
committerWu Fengguang <fengguang.wu@intel.com>2011-12-18 14:20:20 +0800
commit54848d73f9f254631303d6eab9b976855988b266 (patch)
tree9fb4b7e564f2c0df88d0bde2f482b9b7efc847fa /kernel/exit.c
parent1bc36b6426ae49139e9f56491db76b95921454d7 (diff)
downloadlinux-54848d73f9f254631303d6eab9b976855988b266.tar.gz
linux-54848d73f9f254631303d6eab9b976855988b266.tar.bz2
linux-54848d73f9f254631303d6eab9b976855988b266.zip
writeback: charge leaked page dirties to active tasks
It's a years long problem that a large number of short-lived dirtiers (eg. gcc instances in a fast kernel build) may starve long-run dirtiers (eg. dd) as well as pushing the dirty pages to the global hard limit. The solution is to charge the pages dirtied by the exited gcc to the other random dirtying tasks. It sounds not perfect, however should behave good enough in practice, seeing as that throttled tasks aren't actually running so those that are running are more likely to pick it up and get throttled, therefore promoting an equal spread. Randy: fix compile error: 'dirty_throttle_leaks' undeclared in exit.c Acked-by: Jan Kara <jack@suse.cz> Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Signed-off-by: Randy Dunlap <rdunlap@xenotime.net> Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
Diffstat (limited to 'kernel/exit.c')
-rw-r--r--kernel/exit.c3
1 files changed, 3 insertions, 0 deletions
diff --git a/kernel/exit.c b/kernel/exit.c
index d0b7d988f873..d4aac24cc469 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -51,6 +51,7 @@
#include <trace/events/sched.h>
#include <linux/hw_breakpoint.h>
#include <linux/oom.h>
+#include <linux/writeback.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
@@ -1037,6 +1038,8 @@ NORET_TYPE void do_exit(long code)
validate_creds_for_do_exit(tsk);
preempt_disable();
+ if (tsk->nr_dirtied)
+ __this_cpu_add(dirty_throttle_leaks, tsk->nr_dirtied);
exit_rcu();
/* causes final put_task_struct in finish_task_switch(). */
tsk->state = TASK_DEAD;