From: Matt H. <mat...@us...> - 2006-06-14 00:02:19
|
This patch uses the task_watcher notifier chain to invoke exit_sem() at appropriate times. Signed-off-by: Matt Helsley <mat...@us...> Cc: Jes Sorensen <je...@sg...> -- ipc/sem.c | 23 +++++++++++++++++++++++ kernel/exit.c | 1 - kernel/fork.c | 4 +--- 3 files changed, 24 insertions(+), 4 deletions(-) Index: linux-2.6.17-rc6-mm2/ipc/sem.c =================================================================== --- linux-2.6.17-rc6-mm2.orig/ipc/sem.c +++ linux-2.6.17-rc6-mm2/ipc/sem.c @@ -82,10 +82,11 @@ #include <linux/audit.h> #include <linux/capability.h> #include <linux/seq_file.h> #include <linux/mutex.h> #include <linux/nsproxy.h> +#include <linux/notifier.h> #include <asm/uaccess.h> #include "util.h" #define sem_ids(ns) (*((ns)->ids[IPC_SEM_IDS])) @@ -121,10 +122,31 @@ static int sysvipc_sem_proc_show(struct #define sc_semmsl sem_ctls[0] #define sc_semmns sem_ctls[1] #define sc_semopm sem_ctls[2] #define sc_semmni sem_ctls[3] +static int sem_undo_task_exit(struct notifier_block *nb, unsigned long val, + void *t) +{ + switch(get_watch_event(val)) { + /* + * If it weren't for the fact that we need clone flags to call + * it we could also implement the copy_semundo portion of + * copy_process inside case WATCH_TASK_INIT + */ + case WATCH_TASK_FREE: + exit_sem(t); + return NOTIFY_OK; + default: /* Don't care */ + return NOTIFY_DONE; + } +} + +static struct notifier_block sem_watch_tasks_nb = { + .notifier_call = sem_undo_task_exit +}; + static void __ipc_init __sem_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids) { ns->ids[IPC_SEM_IDS] = ids; ns->sc_semmsl = SEMMSL; ns->sc_semmns = SEMMNS; @@ -171,10 +193,11 @@ void __init sem_init (void) { __sem_init_ns(&init_ipc_ns, &init_sem_ids); ipc_init_proc_interface("sysvipc/sem", " key semid perms nsems uid gid cuid cgid otime ctime\n", IPC_SEM_IDS, sysvipc_sem_proc_show); + register_task_watcher(&sem_watch_tasks_nb); } /* * Lockless wakeup algorithm: * Without the check/retry algorithm a lockless wakeup is possible: Index: linux-2.6.17-rc6-mm2/kernel/exit.c =================================================================== --- linux-2.6.17-rc6-mm2.orig/kernel/exit.c +++ linux-2.6.17-rc6-mm2/kernel/exit.c @@ -919,11 +919,10 @@ fastcall NORET_TYPE void do_exit(long co notify_result = notify_watchers(WATCH_TASK_FREE, tsk); WARN_ON(notify_result & NOTIFY_STOP_MASK); exit_mm(tsk); - exit_sem(tsk); __exit_files(tsk); __exit_fs(tsk); exit_task_namespaces(tsk); exit_thread(); cpuset_exit(tsk); Index: linux-2.6.17-rc6-mm2/kernel/fork.c =================================================================== --- linux-2.6.17-rc6-mm2.orig/kernel/fork.c +++ linux-2.6.17-rc6-mm2/kernel/fork.c @@ -1089,11 +1089,11 @@ static task_t *copy_process(unsigned lon goto bad_fork_cleanup_policy; /* copy all the process information */ if ((retval = copy_semundo(clone_flags, p))) goto bad_fork_cleanup_security; if ((retval = copy_files(clone_flags, p))) - goto bad_fork_cleanup_semundo; + goto bad_fork_cleanup_security; if ((retval = copy_fs(clone_flags, p))) goto bad_fork_cleanup_files; if ((retval = copy_sighand(clone_flags, p))) goto bad_fork_cleanup_fs; if ((retval = copy_signal(clone_flags, p))) @@ -1263,12 +1263,10 @@ bad_fork_cleanup_sighand: __cleanup_sighand(p->sighand); bad_fork_cleanup_fs: exit_fs(p); /* blocking */ bad_fork_cleanup_files: exit_files(p); /* blocking */ -bad_fork_cleanup_semundo: - exit_sem(p); bad_fork_cleanup_security: security_task_free(p); notify_result = notify_watchers(WATCH_TASK_FREE, p); WARN_ON(notify_result & NOTIFY_STOP_MASK); bad_fork_cleanup_policy: -- |