diff options
-rw-r--r-- | include/linux/cgroup-defs.h | 13 | ||||
-rw-r--r-- | include/linux/cgroup.h | 2 | ||||
-rw-r--r-- | kernel/cgroup/cgroup.c | 37 |
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 */ |
538 | static inline bool cgroup_is_populated(struct cgroup *cgrp) | 538 | static 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 | */ |
605 | static void cgroup_update_populated(struct cgroup *cgrp, bool populated) | 606 | static 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 | */ |
635 | static void css_set_update_populated(struct css_set *cset, bool populated) | 640 | static 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 | */ |