aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2017-07-16 21:43:33 -0400
committerTejun Heo <tj@kernel.org>2017-07-16 21:44:42 -0400
commit788b950c62e06b02278a0fd380e1a0667996ce3c (patch)
treeca94c0d11e8d7f0b736d27036dd611f6ea2e75a7
parent88e033e326307831922e34e7de0d694274dcc1c7 (diff)
cgroup: distinguish local and children populated states
cgrp->populated_cnt counts both local (the cgroup's populated css_sets) and subtree proper (populated children) so that it's only zero when the whole subtree, including self, is empty. This patch splits the counter into two so that local and children populated states are tracked separately. It allows finer-grained tests on the state of the hierarchy which will be used to replace css_set walking local populated test. Signed-off-by: Tejun Heo <tj@kernel.org>
-rw-r--r--include/linux/cgroup-defs.h13
-rw-r--r--include/linux/cgroup.h2
-rw-r--r--kernel/cgroup/cgroup.c37
3 files changed, 31 insertions, 21 deletions
diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h
index 09f4c7df1478..ae7bc1e70085 100644
--- a/include/linux/cgroup-defs.h
+++ b/include/linux/cgroup-defs.h
@@ -263,11 +263,16 @@ struct cgroup {
263 263
264 /* 264 /*
265 * Each non-empty css_set associated with this cgroup contributes 265 * Each non-empty css_set associated with this cgroup contributes
266 * one to populated_cnt. All children with non-zero popuplated_cnt 266 * one to nr_populated_csets. The counter is zero iff this cgroup
267 * of their own contribute one. The count is zero iff there's no 267 * doesn't have any tasks.
268 * task in this cgroup or its subtree. 268 *
269 * All children which have non-zero nr_populated_csets and/or
270 * nr_populated_children of their own contribute one to
271 * nr_populated_children. The counter is zero iff this cgroup's
272 * subtree proper doesn't have any tasks.
269 */ 273 */
270 int populated_cnt; 274 int nr_populated_csets;
275 int nr_populated_children;
271 276
272 struct kernfs_node *kn; /* cgroup kernfs entry */ 277 struct kernfs_node *kn; /* cgroup kernfs entry */
273 struct cgroup_file procs_file; /* handle for "cgroup.procs" */ 278 struct cgroup_file procs_file; /* handle for "cgroup.procs" */
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index 710a005c6b7a..308b10797a54 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -537,7 +537,7 @@ static inline bool task_under_cgroup_hierarchy(struct task_struct *task,
537/* no synchronization, the result can only be used as a hint */ 537/* no synchronization, the result can only be used as a hint */
538static inline bool cgroup_is_populated(struct cgroup *cgrp) 538static inline bool cgroup_is_populated(struct cgroup *cgrp)
539{ 539{
540 return cgrp->populated_cnt; 540 return cgrp->nr_populated_csets + cgrp->nr_populated_children;
541} 541}
542 542
543/* returns ino associated with a cgroup */ 543/* returns ino associated with a cgroup */
diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
index 4f02b5edd82c..5fe2644cd0f3 100644
--- a/kernel/cgroup/cgroup.c
+++ b/kernel/cgroup/cgroup.c
@@ -587,39 +587,44 @@ static bool css_set_populated(struct css_set *cset)
587} 587}
588 588
589/** 589/**
590 * cgroup_update_populated - updated populated count of a cgroup 590 * cgroup_update_populated - update the populated count of a cgroup
591 * @cgrp: the target cgroup 591 * @cgrp: the target cgroup
592 * @populated: inc or dec populated count 592 * @populated: inc or dec populated count
593 * 593 *
594 * One of the css_sets associated with @cgrp is either getting its first 594 * One of the css_sets associated with @cgrp is either getting its first
595 * task or losing the last. Update @cgrp->populated_cnt accordingly. The 595 * task or losing the last. Update @cgrp->nr_populated_* accordingly. The
596 * count is propagated towards root so that a given cgroup's populated_cnt 596 * count is propagated towards root so that a given cgroup's
597 * is zero iff the cgroup and all its descendants don't contain any tasks. 597 * nr_populated_children is zero iff none of its descendants contain any
598 * tasks.
598 * 599 *
599 * @cgrp's interface file "cgroup.populated" is zero if 600 * @cgrp's interface file "cgroup.populated" is zero if both
600 * @cgrp->populated_cnt is zero and 1 otherwise. When @cgrp->populated_cnt 601 * @cgrp->nr_populated_csets and @cgrp->nr_populated_children are zero and
601 * changes from or to zero, userland is notified that the content of the 602 * 1 otherwise. When the sum changes from or to zero, userland is notified
602 * interface file has changed. This can be used to detect when @cgrp and 603 * that the content of the interface file has changed. This can be used to
603 * its descendants become populated or empty. 604 * detect when @cgrp and its descendants become populated or empty.
604 */ 605 */
605static void cgroup_update_populated(struct cgroup *cgrp, bool populated) 606static void cgroup_update_populated(struct cgroup *cgrp, bool populated)
606{ 607{
608 struct cgroup *child = NULL;
609 int adj = populated ? 1 : -1;
610
607 lockdep_assert_held(&css_set_lock); 611 lockdep_assert_held(&css_set_lock);
608 612
609 do { 613 do {
610 bool trigger; 614 bool was_populated = cgroup_is_populated(cgrp);
611 615
612 if (populated) 616 if (!child)
613 trigger = !cgrp->populated_cnt++; 617 cgrp->nr_populated_csets += adj;
614 else 618 else
615 trigger = !--cgrp->populated_cnt; 619 cgrp->nr_populated_children += adj;
616 620
617 if (!trigger) 621 if (was_populated == cgroup_is_populated(cgrp))
618 break; 622 break;
619 623
620 cgroup1_check_for_release(cgrp); 624 cgroup1_check_for_release(cgrp);
621 cgroup_file_notify(&cgrp->events_file); 625 cgroup_file_notify(&cgrp->events_file);
622 626
627 child = cgrp;
623 cgrp = cgroup_parent(cgrp); 628 cgrp = cgroup_parent(cgrp);
624 } while (cgrp); 629 } while (cgrp);
625} 630}
@@ -630,7 +635,7 @@ static void cgroup_update_populated(struct cgroup *cgrp, bool populated)
630 * @populated: whether @cset is populated or depopulated 635 * @populated: whether @cset is populated or depopulated
631 * 636 *
632 * @cset is either getting the first task or losing the last. Update the 637 * @cset is either getting the first task or losing the last. Update the
633 * ->populated_cnt of all associated cgroups accordingly. 638 * populated counters of all associated cgroups accordingly.
634 */ 639 */
635static void css_set_update_populated(struct css_set *cset, bool populated) 640static void css_set_update_populated(struct css_set *cset, bool populated)
636{ 641{
@@ -653,7 +658,7 @@ static void css_set_update_populated(struct css_set *cset, bool populated)
653 * css_set, @from_cset can be NULL. If @task is being disassociated 658 * css_set, @from_cset can be NULL. If @task is being disassociated
654 * instead of moved, @to_cset can be NULL. 659 * instead of moved, @to_cset can be NULL.
655 * 660 *
656 * This function automatically handles populated_cnt updates and 661 * This function automatically handles populated counter updates and
657 * css_task_iter adjustments but the caller is responsible for managing 662 * css_task_iter adjustments but the caller is responsible for managing
658 * @from_cset and @to_cset's reference counts. 663 * @from_cset and @to_cset's reference counts.
659 */ 664 */