cgroup/rstat: check updated_next only for root
authorWei Yang <richard.weiyang@gmail.com>
Sat, 25 Dec 2021 00:09:32 +0000 (00:09 +0000)
committerTejun Heo <tj@kernel.org>
Thu, 6 Jan 2022 21:50:34 +0000 (11:50 -1000)
After commit dc26532aed0a ("cgroup: rstat: punt root-level optimization to
individual controllers"), each rstat on updated_children list has its
->updated_next not NULL.

This means we can remove the check on ->updated_next, if we make sure
the subtree from @root is on list, which could be done by checking
updated_next for root.

tj: Coding style fixes.

Signed-off-by: Wei Yang <richard.weiyang@gmail.com>
Reviewed-by: Michal Koutný <mkoutny@suse.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
kernel/cgroup/rstat.c

index bc69932..9d331ba 100644 (file)
@@ -88,6 +88,7 @@ static struct cgroup *cgroup_rstat_cpu_pop_updated(struct cgroup *pos,
                                                   struct cgroup *root, int cpu)
 {
        struct cgroup_rstat_cpu *rstatc;
+       struct cgroup *parent;
 
        if (pos == root)
                return NULL;
@@ -96,10 +97,14 @@ static struct cgroup *cgroup_rstat_cpu_pop_updated(struct cgroup *pos,
         * We're gonna walk down to the first leaf and visit/remove it.  We
         * can pick whatever unvisited node as the starting point.
         */
-       if (!pos)
+       if (!pos) {
                pos = root;
-       else
+               /* return NULL if this subtree is not on-list */
+               if (!cgroup_rstat_cpu(pos, cpu)->updated_next)
+                       return NULL;
+       } else {
                pos = cgroup_parent(pos);
+       }
 
        /* walk down to the first leaf */
        while (true) {
@@ -115,31 +120,25 @@ static struct cgroup *cgroup_rstat_cpu_pop_updated(struct cgroup *pos,
         * However, due to the way we traverse, @pos will be the first
         * child in most cases. The only exception is @root.
         */
-       if (rstatc->updated_next) {
-               struct cgroup *parent = cgroup_parent(pos);
-
-               if (parent) {
-                       struct cgroup_rstat_cpu *prstatc;
-                       struct cgroup **nextp;
-
-                       prstatc = cgroup_rstat_cpu(parent, cpu);
-                       nextp = &prstatc->updated_children;
-                       while (*nextp != pos) {
-                               struct cgroup_rstat_cpu *nrstatc;
-
-                               nrstatc = cgroup_rstat_cpu(*nextp, cpu);
-                               WARN_ON_ONCE(*nextp == parent);
-                               nextp = &nrstatc->updated_next;
-                       }
-                       *nextp = rstatc->updated_next;
-               }
+       parent = cgroup_parent(pos);
+       if (parent) {
+               struct cgroup_rstat_cpu *prstatc;
+               struct cgroup **nextp;
 
-               rstatc->updated_next = NULL;
-               return pos;
+               prstatc = cgroup_rstat_cpu(parent, cpu);
+               nextp = &prstatc->updated_children;
+               while (*nextp != pos) {
+                       struct cgroup_rstat_cpu *nrstatc;
+
+                       nrstatc = cgroup_rstat_cpu(*nextp, cpu);
+                       WARN_ON_ONCE(*nextp == parent);
+                       nextp = &nrstatc->updated_next;
+               }
+               *nextp = rstatc->updated_next;
        }
 
-       /* only happens for @root */
-       return NULL;
+       rstatc->updated_next = NULL;
+       return pos;
 }
 
 /* see cgroup_rstat_flush() */