diff options
-rw-r--r-- | include/linux/cgroup.h | 4 | ||||
-rw-r--r-- | kernel/cgroup.c | 59 |
2 files changed, 32 insertions, 31 deletions
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index 0b91436c68ef..5f9ba5881717 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h | |||
@@ -779,7 +779,7 @@ static inline struct cgroup *cgroup_from_id(struct cgroup_subsys *ss, int id) | |||
779 | return idr_find(&ss->root->cgroup_idr, id); | 779 | return idr_find(&ss->root->cgroup_idr, id); |
780 | } | 780 | } |
781 | 781 | ||
782 | struct cgroup *cgroup_next_sibling(struct cgroup *pos); | 782 | struct cgroup *cgroup_next_child(struct cgroup *pos, struct cgroup *cgrp); |
783 | 783 | ||
784 | /** | 784 | /** |
785 | * cgroup_for_each_child - iterate through children of a cgroup | 785 | * cgroup_for_each_child - iterate through children of a cgroup |
@@ -802,7 +802,7 @@ struct cgroup *cgroup_next_sibling(struct cgroup *pos); | |||
802 | #define cgroup_for_each_child(pos, cgrp) \ | 802 | #define cgroup_for_each_child(pos, cgrp) \ |
803 | for ((pos) = list_first_or_null_rcu(&(cgrp)->children, \ | 803 | for ((pos) = list_first_or_null_rcu(&(cgrp)->children, \ |
804 | struct cgroup, sibling); \ | 804 | struct cgroup, sibling); \ |
805 | (pos); (pos) = cgroup_next_sibling((pos))) | 805 | (pos); (pos) = cgroup_next_child((pos), (cgrp))) |
806 | 806 | ||
807 | struct cgroup *cgroup_next_descendant_pre(struct cgroup *pos, | 807 | struct cgroup *cgroup_next_descendant_pre(struct cgroup *pos, |
808 | struct cgroup *cgroup); | 808 | struct cgroup *cgroup); |
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 6ee469837fda..dd55244952bd 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -3037,15 +3037,16 @@ static void cgroup_enable_task_cg_lists(void) | |||
3037 | } | 3037 | } |
3038 | 3038 | ||
3039 | /** | 3039 | /** |
3040 | * cgroup_next_sibling - find the next sibling of a given cgroup | 3040 | * cgroup_next_child - find the next child of a given cgroup |
3041 | * @pos: the current cgroup | 3041 | * @pos: the current position (%NULL to initiate traversal) |
3042 | * @cgrp: cgroup whose descendants to walk | ||
3042 | * | 3043 | * |
3043 | * This function returns the next sibling of @pos and should be called | 3044 | * This function returns the next child of @cgrp and should be called under |
3044 | * under RCU read lock. The only requirement is that @pos is accessible. | 3045 | * RCU read lock. The only requirement is that @cgrp and @pos are |
3045 | * The next sibling is guaranteed to be returned regardless of @pos's | 3046 | * accessible. The next sibling is guaranteed to be returned regardless of |
3046 | * state. | 3047 | * their states. |
3047 | */ | 3048 | */ |
3048 | struct cgroup *cgroup_next_sibling(struct cgroup *pos) | 3049 | struct cgroup *cgroup_next_child(struct cgroup *pos, struct cgroup *cgrp) |
3049 | { | 3050 | { |
3050 | struct cgroup *next; | 3051 | struct cgroup *next; |
3051 | 3052 | ||
@@ -3061,30 +3062,30 @@ struct cgroup *cgroup_next_sibling(struct cgroup *pos) | |||
3061 | * safe to dereference from this RCU critical section. If | 3062 | * safe to dereference from this RCU critical section. If |
3062 | * ->sibling.next is inaccessible, cgroup_is_dead() is guaranteed | 3063 | * ->sibling.next is inaccessible, cgroup_is_dead() is guaranteed |
3063 | * to be visible as %true here. | 3064 | * to be visible as %true here. |
3065 | * | ||
3066 | * If @pos is dead, its next pointer can't be dereferenced; | ||
3067 | * however, as each cgroup is given a monotonically increasing | ||
3068 | * unique serial number and always appended to the sibling list, | ||
3069 | * the next one can be found by walking the parent's children until | ||
3070 | * we see a cgroup with higher serial number than @pos's. While | ||
3071 | * this path can be slower, it's taken only when either the current | ||
3072 | * cgroup is removed or iteration and removal race. | ||
3064 | */ | 3073 | */ |
3065 | if (likely(!cgroup_is_dead(pos))) { | 3074 | if (!pos) { |
3075 | next = list_entry_rcu(cgrp->children.next, struct cgroup, sibling); | ||
3076 | } else if (likely(!cgroup_is_dead(pos))) { | ||
3066 | next = list_entry_rcu(pos->sibling.next, struct cgroup, sibling); | 3077 | next = list_entry_rcu(pos->sibling.next, struct cgroup, sibling); |
3067 | if (&next->sibling != &pos->parent->children) | 3078 | } else { |
3068 | return next; | 3079 | list_for_each_entry_rcu(next, &cgrp->children, sibling) |
3069 | return NULL; | 3080 | if (next->serial_nr > pos->serial_nr) |
3081 | break; | ||
3070 | } | 3082 | } |
3071 | 3083 | ||
3072 | /* | 3084 | if (&next->sibling != &cgrp->children) |
3073 | * Can't dereference the next pointer. Each cgroup is given a | 3085 | return next; |
3074 | * monotonically increasing unique serial number and always | ||
3075 | * appended to the sibling list, so the next one can be found by | ||
3076 | * walking the parent's children until we see a cgroup with higher | ||
3077 | * serial number than @pos's. | ||
3078 | * | ||
3079 | * While this path can be slow, it's taken only when either the | ||
3080 | * current cgroup is removed or iteration and removal race. | ||
3081 | */ | ||
3082 | list_for_each_entry_rcu(next, &pos->parent->children, sibling) | ||
3083 | if (next->serial_nr > pos->serial_nr) | ||
3084 | return next; | ||
3085 | return NULL; | 3086 | return NULL; |
3086 | } | 3087 | } |
3087 | EXPORT_SYMBOL_GPL(cgroup_next_sibling); | 3088 | EXPORT_SYMBOL_GPL(cgroup_next_child); |
3088 | 3089 | ||
3089 | /** | 3090 | /** |
3090 | * cgroup_next_descendant_pre - find the next descendant for pre-order walk | 3091 | * cgroup_next_descendant_pre - find the next descendant for pre-order walk |
@@ -3117,7 +3118,7 @@ struct cgroup *cgroup_next_descendant_pre(struct cgroup *pos, | |||
3117 | 3118 | ||
3118 | /* no child, visit my or the closest ancestor's next sibling */ | 3119 | /* no child, visit my or the closest ancestor's next sibling */ |
3119 | while (pos != cgroup) { | 3120 | while (pos != cgroup) { |
3120 | next = cgroup_next_sibling(pos); | 3121 | next = cgroup_next_child(pos, pos->parent); |
3121 | if (next) | 3122 | if (next) |
3122 | return next; | 3123 | return next; |
3123 | pos = pos->parent; | 3124 | pos = pos->parent; |
@@ -3198,7 +3199,7 @@ struct cgroup *cgroup_next_descendant_post(struct cgroup *pos, | |||
3198 | } | 3199 | } |
3199 | 3200 | ||
3200 | /* if there's an unvisited sibling, visit its leftmost descendant */ | 3201 | /* if there's an unvisited sibling, visit its leftmost descendant */ |
3201 | next = cgroup_next_sibling(pos); | 3202 | next = cgroup_next_child(pos, pos->parent); |
3202 | if (next) | 3203 | if (next) |
3203 | return cgroup_leftmost_descendant(next); | 3204 | return cgroup_leftmost_descendant(next); |
3204 | 3205 | ||
@@ -4549,9 +4550,9 @@ static int cgroup_destroy_locked(struct cgroup *cgrp) | |||
4549 | /* | 4550 | /* |
4550 | * Mark @cgrp dead. This prevents further task migration and child | 4551 | * Mark @cgrp dead. This prevents further task migration and child |
4551 | * creation by disabling cgroup_lock_live_group(). Note that | 4552 | * creation by disabling cgroup_lock_live_group(). Note that |
4552 | * CGRP_DEAD assertion is depended upon by cgroup_next_sibling() to | 4553 | * CGRP_DEAD assertion is depended upon by cgroup_next_child() to |
4553 | * resume iteration after dropping RCU read lock. See | 4554 | * resume iteration after dropping RCU read lock. See |
4554 | * cgroup_next_sibling() for details. | 4555 | * cgroup_next_child() for details. |
4555 | */ | 4556 | */ |
4556 | set_bit(CGRP_DEAD, &cgrp->flags); | 4557 | set_bit(CGRP_DEAD, &cgrp->flags); |
4557 | 4558 | ||