aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 */