This patch fixes the logic of walk_task_subtree() to correctly account
for all threads (and not only threads of the tree root).

Signed-off-by: Oren Laadan <[email protected]>
Tested-by: Dan Smith <[email protected]>
---
 kernel/checkpoint/sys.c |   24 ++++++++++++++----------
 1 files changed, 14 insertions(+), 10 deletions(-)

diff --git a/kernel/checkpoint/sys.c b/kernel/checkpoint/sys.c
index 5e6994e..171c867 100644
--- a/kernel/checkpoint/sys.c
+++ b/kernel/checkpoint/sys.c
@@ -565,7 +565,10 @@ EXPORT_SYMBOL(do_ckpt_msg);
  *
  * The function will start with @root, and iterate through all the
  * descendants, including threads, in a DFS manner. Children of a task
- * are traversed before proceeding to the next thread of that task.
+ * are traversed before proceeding to the next thread of that task,
+ * and threads of a task are traversed before proceeding to the next
+ * sibling of that task. (Threads of the root task are included, but
+ * siblings of the root task are skipped).
  *
  * For each task, the callback @func will be called providing the task
  * pointer and the @data. The callback is invoked while holding the
@@ -580,10 +583,8 @@ int walk_task_subtree(struct task_struct *root,
                      int (*func)(struct task_struct *, void *),
                      void *data)
 {
-
-       struct task_struct *leader = root;
-       struct task_struct *parent = NULL;
        struct task_struct *task = root;
+       struct task_struct *parent = NULL;
        int total = 0;
        int ret;
 
@@ -604,7 +605,13 @@ int walk_task_subtree(struct task_struct *root,
                        continue;
                }
 
+               /* by definition, skip siblings of root */
                while (task != root) {
+                       /* if not last thread - proceed with thread */
+                       task = next_thread(task);
+                       if (!thread_group_leader(task))
+                               break;
+
                        /* if has sibling - proceed with sibling */
                        if (!list_is_last(&task->sibling, &parent->children)) {
                                task = list_entry(task->sibling.next,
@@ -617,12 +624,9 @@ int walk_task_subtree(struct task_struct *root,
                        parent = parent->real_parent;
                }
 
-               if (task == root) {
-                       /* in case root task is multi-threaded */
-                       root = task = next_thread(task);
-                       if (root == leader)
-                               break;
-               }
+               /* if we arrive at root again -- done */
+               if (task == root)
+                       break;
        }
        read_unlock(&tasklist_lock);
 
-- 
1.7.0.4

_______________________________________________
Containers mailing list
[email protected]
https://lists.linux-foundation.org/mailman/listinfo/containers

_______________________________________________
Devel mailing list
[email protected]
https://openvz.org/mailman/listinfo/devel

Reply via email to