diff options
-rw-r--r-- | include/linux/cgroup-defs.h | 1 | ||||
-rw-r--r-- | include/linux/cgroup.h | 20 | ||||
-rw-r--r-- | kernel/cgroup/cgroup.c | 5 | ||||
-rw-r--r-- | kernel/cgroup/cpuset.c | 4 |
4 files changed, 28 insertions, 2 deletions
diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h index 21745946cae1..ec47101cb1bf 100644 --- a/include/linux/cgroup-defs.h +++ b/include/linux/cgroup-defs.h | |||
@@ -48,6 +48,7 @@ enum { | |||
48 | CSS_ONLINE = (1 << 1), /* between ->css_online() and ->css_offline() */ | 48 | CSS_ONLINE = (1 << 1), /* between ->css_online() and ->css_offline() */ |
49 | CSS_RELEASED = (1 << 2), /* refcnt reached zero, released */ | 49 | CSS_RELEASED = (1 << 2), /* refcnt reached zero, released */ |
50 | CSS_VISIBLE = (1 << 3), /* css is visible to userland */ | 50 | CSS_VISIBLE = (1 << 3), /* css is visible to userland */ |
51 | CSS_DYING = (1 << 4), /* css is dying */ | ||
51 | }; | 52 | }; |
52 | 53 | ||
53 | /* bits in struct cgroup flags field */ | 54 | /* bits in struct cgroup flags field */ |
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index ed2573e149fa..710a005c6b7a 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h | |||
@@ -344,6 +344,26 @@ static inline bool css_tryget_online(struct cgroup_subsys_state *css) | |||
344 | } | 344 | } |
345 | 345 | ||
346 | /** | 346 | /** |
347 | * css_is_dying - test whether the specified css is dying | ||
348 | * @css: target css | ||
349 | * | ||
350 | * Test whether @css is in the process of offlining or already offline. In | ||
351 | * most cases, ->css_online() and ->css_offline() callbacks should be | ||
352 | * enough; however, the actual offline operations are RCU delayed and this | ||
353 | * test returns %true also when @css is scheduled to be offlined. | ||
354 | * | ||
355 | * This is useful, for example, when the use case requires synchronous | ||
356 | * behavior with respect to cgroup removal. cgroup removal schedules css | ||
357 | * offlining but the css can seem alive while the operation is being | ||
358 | * delayed. If the delay affects user visible semantics, this test can be | ||
359 | * used to resolve the situation. | ||
360 | */ | ||
361 | static inline bool css_is_dying(struct cgroup_subsys_state *css) | ||
362 | { | ||
363 | return !(css->flags & CSS_NO_REF) && percpu_ref_is_dying(&css->refcnt); | ||
364 | } | ||
365 | |||
366 | /** | ||
347 | * css_put - put a css reference | 367 | * css_put - put a css reference |
348 | * @css: target css | 368 | * @css: target css |
349 | * | 369 | * |
diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c index c3c9a0e1b3c9..8d4e85eae42c 100644 --- a/kernel/cgroup/cgroup.c +++ b/kernel/cgroup/cgroup.c | |||
@@ -4265,6 +4265,11 @@ static void kill_css(struct cgroup_subsys_state *css) | |||
4265 | { | 4265 | { |
4266 | lockdep_assert_held(&cgroup_mutex); | 4266 | lockdep_assert_held(&cgroup_mutex); |
4267 | 4267 | ||
4268 | if (css->flags & CSS_DYING) | ||
4269 | return; | ||
4270 | |||
4271 | css->flags |= CSS_DYING; | ||
4272 | |||
4268 | /* | 4273 | /* |
4269 | * This must happen before css is disassociated with its cgroup. | 4274 | * This must happen before css is disassociated with its cgroup. |
4270 | * See seq_css() for details. | 4275 | * See seq_css() for details. |
diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c index f6501f4f6040..ae643412948a 100644 --- a/kernel/cgroup/cpuset.c +++ b/kernel/cgroup/cpuset.c | |||
@@ -176,9 +176,9 @@ typedef enum { | |||
176 | } cpuset_flagbits_t; | 176 | } cpuset_flagbits_t; |
177 | 177 | ||
178 | /* convenient tests for these bits */ | 178 | /* convenient tests for these bits */ |
179 | static inline bool is_cpuset_online(const struct cpuset *cs) | 179 | static inline bool is_cpuset_online(struct cpuset *cs) |
180 | { | 180 | { |
181 | return test_bit(CS_ONLINE, &cs->flags); | 181 | return test_bit(CS_ONLINE, &cs->flags) && !css_is_dying(&cs->css); |
182 | } | 182 | } |
183 | 183 | ||
184 | static inline int is_cpu_exclusive(const struct cpuset *cs) | 184 | static inline int is_cpu_exclusive(const struct cpuset *cs) |