diff options
author | Oleg Nesterov <oleg@redhat.com> | 2017-01-30 18:06:11 +0300 |
---|---|---|
committer | Eric W. Biederman <ebiederm@xmission.com> | 2017-02-03 16:34:41 +1300 |
commit | 0f1b92cbdd0309afae0af1963e8cccddb3d2eaff (patch) | |
tree | f30ecfd58043e4a2b32de2b053efac37a4f03b21 /kernel/fork.c | |
parent | 015bb305b8ebe8d601a238ab70ebdc394c7a19ba (diff) |
introduce the walk_process_tree() helper
Add the new helper to walk the process tree, the next patch adds a user.
Note that it visits the group leaders only, proc_visitor can do
for_each_thread itself or we can trivially extend walk_process_tree() to
do this.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Diffstat (limited to 'kernel/fork.c')
-rw-r--r-- | kernel/fork.c | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index 11c5c8ab827c..135b7a49ad59 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -2053,6 +2053,38 @@ SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp, } #endif +void walk_process_tree(struct task_struct *top, proc_visitor visitor, void *data) +{ + struct task_struct *leader, *parent, *child; + int res; + + read_lock(&tasklist_lock); + leader = top = top->group_leader; +down: + for_each_thread(leader, parent) { + list_for_each_entry(child, &parent->children, sibling) { + res = visitor(child, data); + if (res) { + if (res < 0) + goto out; + leader = child; + goto down; + } +up: + ; + } + } + + if (leader != top) { + child = leader; + parent = child->real_parent; + leader = parent->group_leader; + goto up; + } +out: + read_unlock(&tasklist_lock); +} + #ifndef ARCH_MIN_MMSTRUCT_ALIGN #define ARCH_MIN_MMSTRUCT_ALIGN 0 #endif |