[PATCH] task: Make task list manipulations RCU safe
authorEric W. Biederman <ebiederm@xmission.com>
Wed, 19 Apr 2006 05:20:16 +0000 (22:20 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Wed, 19 Apr 2006 16:13:49 +0000 (09:13 -0700)
While we can currently walk through thread groups, process groups, and
sessions with just the rcu_read_lock, this opens the door to walking the
entire task list.

We already have all of the other RCU guarantees so there is no cost in
doing this, this should be enough so that proc can stop taking the
tasklist lock during readdir.

prev_task was killed because it has no users, and using it will miss new
tasks when doing an rcu traversal.

Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
fs/exec.c
include/linux/sched.h
kernel/exit.c
kernel/fork.c

index 4121bb55973933b8a407c6969edba4094dad8022..3a79d97ac234422c353ad6c37ab973d3363471bd 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -712,7 +712,7 @@ static int de_thread(struct task_struct *tsk)
                attach_pid(current, PIDTYPE_PID,  current->pid);
                attach_pid(current, PIDTYPE_PGID, current->signal->pgrp);
                attach_pid(current, PIDTYPE_SID,  current->signal->session);
-               list_add_tail(&current->tasks, &init_task.tasks);
+               list_add_tail_rcu(&current->tasks, &init_task.tasks);
 
                current->group_leader = current;
                leader->group_leader = current;
index b7d31e2e1729027ada80a4759eb2eb7618d482ae..29b7d4f87d207a69a1b8a2c0167416f1332f030d 100644 (file)
@@ -1192,8 +1192,7 @@ extern void wait_task_inactive(task_t * p);
 #define remove_parent(p)       list_del_init(&(p)->sibling)
 #define add_parent(p)          list_add_tail(&(p)->sibling,&(p)->parent->children)
 
-#define next_task(p)   list_entry((p)->tasks.next, struct task_struct, tasks)
-#define prev_task(p)   list_entry((p)->tasks.prev, struct task_struct, tasks)
+#define next_task(p)   list_entry(rcu_dereference((p)->tasks.next), struct task_struct, tasks)
 
 #define for_each_process(p) \
        for (p = &init_task ; (p = next_task(p)) != &init_task ; )
index 1a9787ac61733abbc793c10c515347904a678bff..f86434d7b3d1811b689bfedcfc1bc40079950a34 100644 (file)
@@ -56,7 +56,7 @@ static void __unhash_process(struct task_struct *p)
                detach_pid(p, PIDTYPE_PGID);
                detach_pid(p, PIDTYPE_SID);
 
-               list_del_init(&p->tasks);
+               list_del_rcu(&p->tasks);
                __get_cpu_var(process_counts)--;
        }
        list_del_rcu(&p->thread_group);
index 54b15f8cda538b3a721c03704c04390a369ae65c..34515772611ee93cfba6bcb4104f5fba350cd2c1 100644 (file)
@@ -1204,7 +1204,7 @@ static task_t *copy_process(unsigned long clone_flags,
                        attach_pid(p, PIDTYPE_PGID, process_group(p));
                        attach_pid(p, PIDTYPE_SID, p->signal->session);
 
-                       list_add_tail(&p->tasks, &init_task.tasks);
+                       list_add_tail_rcu(&p->tasks, &init_task.tasks);
                        __get_cpu_var(process_counts)++;
                }
                attach_pid(p, PIDTYPE_PID, p->pid);