From: Jes S. <je...@sg...> - 2006-04-27 14:55:04
|
Hi, Attached is the patch for the simple task notifier support that has been discussed on lse-tech on multiple occasions (it superceeds pnotify/pagg/task_notify). I provides a way to hook into the fork/exit etc. places and can be used for things like task grouping and accounting, but also to clean up all the conditional callouts we have in the fork/exit paths. I will be posting one example in the next email and I will be happy to do a bunch more if we can come to agreement on this approach. I am using the raw notifier chain to give the clients the same sleep/blocking rules as the parents currently have. IMHO this makes the most sense to keep the overhead at a minimum. Comments/oppinions/flames? Cheers, Jes Simple task notifier support. This uses the raw notifier chain allowing the users the same calls to sleeping functions as are in fork() etc. Signed-off-by: Jes Sorensen <je...@sg...> ---- fs/exec.c | 3 +++ include/linux/init_task.h | 2 ++ include/linux/notifier.h | 5 +++++ include/linux/sched.h | 3 +++ kernel/exit.c | 5 +++++ kernel/fork.c | 16 ++++++++++++++++ 6 files changed, 34 insertions(+) Index: linux-2.6/fs/exec.c =================================================================== --- linux-2.6.orig/fs/exec.c +++ linux-2.6/fs/exec.c @@ -49,6 +49,7 @@ #include <linux/rmap.h> #include <linux/acct.h> #include <linux/cn_proc.h> +#include <linux/notifier.h> #include <asm/uaccess.h> #include <asm/mmu_context.h> @@ -1001,6 +1002,8 @@ suid_keys(current); exec_keys(current); + raw_notifier_call_chain(¤t->task_notifier, TN_EXEC, NULL); + task_lock(current); unsafe = unsafe_exec(current); security_bprm_apply_creds(bprm, unsafe); Index: linux-2.6/include/linux/init_task.h =================================================================== --- linux-2.6.orig/include/linux/init_task.h +++ linux-2.6/include/linux/init_task.h @@ -3,6 +3,7 @@ #include <linux/file.h> #include <linux/rcupdate.h> +#include <linux/notifier.h> #define INIT_FDTABLE \ { \ @@ -123,6 +124,7 @@ .journal_info = NULL, \ .cpu_timers = INIT_CPU_TIMERS(tsk.cpu_timers), \ .fs_excl = ATOMIC_INIT(0), \ + .task_notifier = RAW_NOTIFIER_INIT(tsk.task_notifier), \ } Index: linux-2.6/include/linux/notifier.h =================================================================== --- linux-2.6.orig/include/linux/notifier.h +++ linux-2.6/include/linux/notifier.h @@ -154,5 +154,10 @@ #define CPU_DOWN_FAILED 0x0006 /* CPU (unsigned)v NOT going down */ #define CPU_DEAD 0x0007 /* CPU (unsigned)v dead */ +#define TN_FORK 0x0001 /* Task notifier - fork */ +#define TN_EXIT 0x0002 /* Task notifier - exit */ +#define TN_FREE 0x0003 /* Task notifier - free */ +#define TN_EXEC 0x0004 /* Task notifier - exec */ + #endif /* __KERNEL__ */ #endif /* _LINUX_NOTIFIER_H */ Index: linux-2.6/include/linux/sched.h =================================================================== --- linux-2.6.orig/include/linux/sched.h +++ linux-2.6/include/linux/sched.h @@ -36,6 +36,7 @@ #include <linux/seccomp.h> #include <linux/rcupdate.h> #include <linux/futex.h> +#include <linux/notifier.h> #include <linux/auxvec.h> /* For AT_VECTOR_SIZE */ @@ -888,6 +889,8 @@ * cache last used pipe for splice */ struct pipe_inode_info *splice_pipe; + + struct raw_notifier_head task_notifier; }; static inline pid_t process_group(struct task_struct *tsk) Index: linux-2.6/kernel/exit.c =================================================================== --- linux-2.6.orig/kernel/exit.c +++ linux-2.6/kernel/exit.c @@ -34,6 +34,7 @@ #include <linux/mutex.h> #include <linux/futex.h> #include <linux/compat.h> +#include <linux/notifier.h> #include <linux/pipe_fs_i.h> #include <asm/uaccess.h> @@ -910,6 +911,10 @@ if (unlikely(tsk->compat_robust_list)) compat_exit_robust_list(tsk); #endif + /* + * Must call the exit notifier before losing the mm struct + */ + raw_notifier_call_chain(&tsk->task_notifier, TN_EXIT, tsk); exit_mm(tsk); exit_sem(tsk); Index: linux-2.6/kernel/fork.c =================================================================== --- linux-2.6.orig/kernel/fork.c +++ linux-2.6/kernel/fork.c @@ -44,6 +44,7 @@ #include <linux/rmap.h> #include <linux/acct.h> #include <linux/cn_proc.h> +#include <linux/notifier.h> #include <asm/pgtable.h> #include <asm/pgalloc.h> @@ -114,6 +115,7 @@ WARN_ON(atomic_read(&tsk->usage)); WARN_ON(tsk == current); + raw_notifier_call_chain(&tsk->task_notifier, TN_FREE, tsk); if (unlikely(tsk->audit_context)) audit_free(tsk); security_task_free(tsk); @@ -1043,6 +1045,11 @@ if (clone_flags & CLONE_THREAD) p->tgid = current->tgid; + /* + * Any of the below could be trying to use this + */ + RAW_INIT_NOTIFIER_HEAD(&p->task_notifier); + if ((retval = security_task_alloc(p))) goto bad_fork_cleanup_policy; if ((retval = audit_alloc(p))) @@ -1103,6 +1110,14 @@ p->exit_state = 0; /* + * Call the task notifiers for the current thread. It is their + * job to determine whether or not to preserve the parent's + * task_notifiers. + */ + if (raw_notifier_call_chain(¤t->task_notifier, TN_FORK, p)) + goto bad_fork_cleanup_namespace; + + /* * Ok, make it visible to the rest of the system. * We dont wake it up yet. */ @@ -1239,6 +1254,7 @@ audit_free(p); bad_fork_cleanup_security: security_task_free(p); + raw_notifier_call_chain(&p->task_notifier, TN_EXIT, p); bad_fork_cleanup_policy: #ifdef CONFIG_NUMA mpol_free(p->mempolicy); |