From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932668AbdA0KHB (ORCPT ); Fri, 27 Jan 2017 05:07:01 -0500 Received: from mailhub.sw.ru ([195.214.232.25]:13925 "EHLO relay.sw.ru" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754810AbdA0KGo (ORCPT ); Fri, 27 Jan 2017 05:06:44 -0500 From: Pavel Tikhomirov To: Ingo Molnar Cc: Peter Zijlstra , Andrew Morton , Cyrill Gorcunov , John Stultz , Thomas Gleixner , Oleg Nesterov , Nicolas Pitre , Michal Hocko , Stanislav Kinsburskiy , Mateusz Guzik , linux-kernel@vger.kernel.org, Pavel Emelyanov , Konstantin Khorenko , Pavel Tikhomirov , Lennart Poettering , "Eric W . Biederman" , Kay Sievers Subject: [PATCH 1/2] introduce the walk_process_tree() helper Date: Fri, 27 Jan 2017 13:05:42 +0300 Message-Id: <20170127100543.18390-2-ptikhomirov@virtuozzo.com> X-Mailer: git-send-email 2.9.3 In-Reply-To: <20170127100543.18390-1-ptikhomirov@virtuozzo.com> References: <20170127100543.18390-1-ptikhomirov@virtuozzo.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Oleg Nesterov 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 Reviewed-by: Pavel Tikhomirov --- include/linux/sched.h | 3 +++ kernel/fork.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/include/linux/sched.h b/include/linux/sched.h index ad3ec9e..7f8ab91 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -3067,6 +3067,9 @@ extern bool current_is_single_threaded(void); #define for_each_process_thread(p, t) \ for_each_process(p) for_each_thread(p, t) +typedef int (*proc_visitor)(struct task_struct *p, void *data); +void walk_process_tree(struct task_struct *top, proc_visitor, void *); + static inline int get_nr_threads(struct task_struct *tsk) { return tsk->signal->nr_threads; diff --git a/kernel/fork.c b/kernel/fork.c index 11c5c8a..135b7a4 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 -- 2.9.3