From: Matt Helsley Adapts delayacct to use Task Watchers. Does not adapt taskstats to use Task Watchers. Signed-off-by: Matt Helsley Cc: Shailabh Nagar Cc: Balbir Singh Cc: Chandra S. Seetharaman Signed-off-by: Andrew Morton --- include/linux/delayacct.h | 2 +- kernel/delayacct.c | 23 +++++++++++++++++++++++ kernel/exit.c | 2 -- kernel/fork.c | 2 -- 4 files changed, 24 insertions(+), 5 deletions(-) diff -puN include/linux/delayacct.h~task-watchers-register-per-task-delay-accounting include/linux/delayacct.h --- a/include/linux/delayacct.h~task-watchers-register-per-task-delay-accounting +++ a/include/linux/delayacct.h @@ -61,7 +61,7 @@ static inline void delayacct_tsk_init(st static inline void delayacct_tsk_exit(struct task_struct *tsk) { - if (tsk->delays) + if (unlikely(tsk->delays)) __delayacct_tsk_exit(tsk); } diff -puN kernel/delayacct.c~task-watchers-register-per-task-delay-accounting kernel/delayacct.c --- a/kernel/delayacct.c~task-watchers-register-per-task-delay-accounting +++ a/kernel/delayacct.c @@ -18,6 +18,7 @@ #include #include #include +#include int delayacct_on __read_mostly; /* Delay accounting turned on/off */ kmem_cache_t *delayacct_cache; @@ -29,6 +30,27 @@ static int __init delayacct_setup_enable } __setup("delayacct", delayacct_setup_enable); +static int delayacct_watch_task(struct notifier_block *nb, unsigned long val, + void *t) +{ + struct task_struct *tsk = t; + switch(get_watch_event(val)) { + case WATCH_TASK_CLONE: + delayacct_tsk_init(tsk); + break; + case WATCH_TASK_FREE: + delayacct_tsk_exit(tsk); + break; + default: + return NOTIFY_DONE; + } + return NOTIFY_OK; +} + +static struct notifier_block __read_mostly delayacct_nb = { + .notifier_call = delayacct_watch_task, +}; + void delayacct_init(void) { delayacct_cache = kmem_cache_create("delayacct_cache", @@ -36,6 +58,7 @@ void delayacct_init(void) 0, SLAB_PANIC, NULL, NULL); + register_task_watcher(&delayacct_nb); delayacct_tsk_init(&init_task); } diff -puN kernel/exit.c~task-watchers-register-per-task-delay-accounting kernel/exit.c --- a/kernel/exit.c~task-watchers-register-per-task-delay-accounting +++ a/kernel/exit.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -910,7 +909,6 @@ fastcall NORET_TYPE void do_exit(long co tsk->exit_code = code; taskstats_exit_send(tsk, tidstats, group_dead); taskstats_exit_free(tidstats); - delayacct_tsk_exit(tsk); notify_result = notify_watchers(WATCH_TASK_FREE, tsk); WARN_ON(notify_result & NOTIFY_STOP_MASK); diff -puN kernel/fork.c~task-watchers-register-per-task-delay-accounting kernel/fork.c --- a/kernel/fork.c~task-watchers-register-per-task-delay-accounting +++ a/kernel/fork.c @@ -44,7 +44,6 @@ #include #include #include -#include #include #include @@ -1006,7 +1005,6 @@ static task_t *copy_process(unsigned lon goto bad_fork_cleanup_put_domain; p->did_exec = 0; - delayacct_tsk_init(p); /* Must remain after dup_task_struct() */ copy_flags(clone_flags, p); p->pid = pid; retval = -EFAULT; _