aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/cgroup-defs.h1
-rw-r--r--include/linux/cgroup.h20
-rw-r--r--kernel/cgroup/cgroup.c5
-rw-r--r--kernel/cgroup/cpuset.c4
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 */
361static 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 */
179static inline bool is_cpuset_online(const struct cpuset *cs) 179static 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
184static inline int is_cpu_exclusive(const struct cpuset *cs) 184static inline int is_cpu_exclusive(const struct cpuset *cs)