cgroup: Clean up css_set task traversal
authorMichal Koutný <mkoutny@suse.com>
Fri, 24 Jan 2020 11:40:16 +0000 (12:40 +0100)
committerTejun Heo <tj@kernel.org>
Wed, 12 Feb 2020 22:11:52 +0000 (17:11 -0500)
css_task_iter stores pointer to head of each iterable list, this dates
back to commit 0f0a2b4fa621 ("cgroup: reorganize css_task_iter") when we
did not store cur_cset. Let us utilize list heads directly in cur_cset
and streamline css_task_iter_advance_css_set a bit. This is no
intentional function change.

Signed-off-by: Michal Koutný <mkoutny@suse.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
include/linux/cgroup.h
kernel/cgroup/cgroup.c

index e75d219..f1219b9 100644 (file)
@@ -58,9 +58,6 @@ struct css_task_iter {
        struct list_head                *tcset_head;
 
        struct list_head                *task_pos;
-       struct list_head                *tasks_head;
-       struct list_head                *mg_tasks_head;
-       struct list_head                *dying_tasks_head;
 
        struct list_head                *cur_tasks_head;
        struct css_set                  *cur_cset;
index c719a41..b4c4c4f 100644 (file)
@@ -4391,29 +4391,24 @@ static void css_task_iter_advance_css_set(struct css_task_iter *it)
 
        lockdep_assert_held(&css_set_lock);
 
-       /* Advance to the next non-empty css_set */
-       do {
-               cset = css_task_iter_next_css_set(it);
-               if (!cset) {
-                       it->task_pos = NULL;
-                       return;
+       /* Advance to the next non-empty css_set and find first non-empty tasks list*/
+       while ((cset = css_task_iter_next_css_set(it))) {
+               if (!list_empty(&cset->tasks)) {
+                       it->cur_tasks_head = &cset->tasks;
+                       break;
+               } else if (!list_empty(&cset->mg_tasks)) {
+                       it->cur_tasks_head = &cset->mg_tasks;
+                       break;
+               } else if (!list_empty(&cset->dying_tasks)) {
+                       it->cur_tasks_head = &cset->dying_tasks;
+                       break;
                }
-       } while (!css_set_populated(cset) && list_empty(&cset->dying_tasks));
-
-       if (!list_empty(&cset->tasks)) {
-               it->task_pos = cset->tasks.next;
-               it->cur_tasks_head = &cset->tasks;
-       } else if (!list_empty(&cset->mg_tasks)) {
-               it->task_pos = cset->mg_tasks.next;
-               it->cur_tasks_head = &cset->mg_tasks;
-       } else {
-               it->task_pos = cset->dying_tasks.next;
-               it->cur_tasks_head = &cset->dying_tasks;
        }
-
-       it->tasks_head = &cset->tasks;
-       it->mg_tasks_head = &cset->mg_tasks;
-       it->dying_tasks_head = &cset->dying_tasks;
+       if (!cset) {
+               it->task_pos = NULL;
+               return;
+       }
+       it->task_pos = it->cur_tasks_head->next;
 
        /*
         * We don't keep css_sets locked across iteration steps and thus
@@ -4458,24 +4453,24 @@ static void css_task_iter_advance(struct css_task_iter *it)
 repeat:
        if (it->task_pos) {
                /*
-                * Advance iterator to find next entry.  cset->tasks is
-                * consumed first and then ->mg_tasks.  After ->mg_tasks,
-                * we move onto the next cset.
+                * Advance iterator to find next entry. We go through cset
+                * tasks, mg_tasks and dying_tasks, when consumed we move onto
+                * the next cset.
                 */
                if (it->flags & CSS_TASK_ITER_SKIPPED)
                        it->flags &= ~CSS_TASK_ITER_SKIPPED;
                else
                        it->task_pos = it->task_pos->next;
 
-               if (it->task_pos == it->tasks_head) {
-                       it->task_pos = it->mg_tasks_head->next;
-                       it->cur_tasks_head = it->mg_tasks_head;
+               if (it->task_pos == &it->cur_cset->tasks) {
+                       it->cur_tasks_head = &it->cur_cset->mg_tasks;
+                       it->task_pos = it->cur_tasks_head->next;
                }
-               if (it->task_pos == it->mg_tasks_head) {
-                       it->task_pos = it->dying_tasks_head->next;
-                       it->cur_tasks_head = it->dying_tasks_head;
+               if (it->task_pos == &it->cur_cset->mg_tasks) {
+                       it->cur_tasks_head = &it->cur_cset->dying_tasks;
+                       it->task_pos = it->cur_tasks_head->next;
                }
-               if (it->task_pos == it->dying_tasks_head)
+               if (it->task_pos == &it->cur_cset->dying_tasks)
                        css_task_iter_advance_css_set(it);
        } else {
                /* called from start, proceed to the first cset */
@@ -4493,12 +4488,12 @@ repeat:
                        goto repeat;
 
                /* and dying leaders w/o live member threads */
-               if (it->cur_tasks_head == it->dying_tasks_head &&
+               if (it->cur_tasks_head == &it->cur_cset->dying_tasks &&
                    !atomic_read(&task->signal->live))
                        goto repeat;
        } else {
                /* skip all dying ones */
-               if (it->cur_tasks_head == it->dying_tasks_head)
+               if (it->cur_tasks_head == &it->cur_cset->dying_tasks)
                        goto repeat;
        }
 }