diff options
author | Tejun Heo <tj@kernel.org> | 2011-11-21 15:32:25 -0500 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2011-11-21 15:32:25 -0500 |
commit | 22b4e111fa01a1147aa562ceaf18a752a928ef4e (patch) | |
tree | f4b29f532678c72edf99bb8df3ba64d526bc8a3c /kernel/cgroup_freezer.c | |
parent | 03afed8bc296fa70186ba832c1126228bb992465 (diff) |
cgroup_freezer: prepare for removal of TIF_FREEZE
TIF_FREEZE will be removed soon and freezing() will directly test
whether any freezing condition is in effect. Make the following
changes in preparation.
* Rename cgroup_freezing_or_frozen() to cgroup_freezing() and make it
return bool.
* Make cgroup_freezing() access task_freezer() under rcu read lock
instead of task_lock(). This makes the state dereferencing racy
against task moving to another cgroup; however, it was already racy
without this change as ->state dereference wasn't synchronized.
This will be later dealt with using attach hooks.
* freezer->state is now set before trying to push tasks into the
target state.
-v2: Oleg pointed out that freeze_change_state() was setting
freeze->state incorrectly to CGROUP_FROZEN instead of
CGROUP_FREEZING. Fixed.
-v3: Matt pointed out that setting CGROUP_FROZEN used to always invoke
try_to_freeze_cgroup() regardless of the current state. Patch
updated such that the actual freeze/thaw operations are always
performed on invocation. This shouldn't make any difference
unless something is broken.
Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: Paul Menage <paul@paulmenage.org>
Cc: Li Zefan <lizf@cn.fujitsu.com>
Cc: Oleg Nesterov <oleg@redhat.com>
Diffstat (limited to 'kernel/cgroup_freezer.c')
-rw-r--r-- | kernel/cgroup_freezer.c | 40 |
1 files changed, 13 insertions, 27 deletions
diff --git a/kernel/cgroup_freezer.c b/kernel/cgroup_freezer.c index cd27b0825560..e6a1b8d1b8bc 100644 --- a/kernel/cgroup_freezer.c +++ b/kernel/cgroup_freezer.c | |||
@@ -48,19 +48,17 @@ static inline struct freezer *task_freezer(struct task_struct *task) | |||
48 | struct freezer, css); | 48 | struct freezer, css); |
49 | } | 49 | } |
50 | 50 | ||
51 | static inline int __cgroup_freezing_or_frozen(struct task_struct *task) | 51 | bool cgroup_freezing(struct task_struct *task) |
52 | { | 52 | { |
53 | enum freezer_state state = task_freezer(task)->state; | 53 | enum freezer_state state; |
54 | return (state == CGROUP_FREEZING) || (state == CGROUP_FROZEN); | 54 | bool ret; |
55 | } | ||
56 | 55 | ||
57 | int cgroup_freezing_or_frozen(struct task_struct *task) | 56 | rcu_read_lock(); |
58 | { | 57 | state = task_freezer(task)->state; |
59 | int result; | 58 | ret = state == CGROUP_FREEZING || state == CGROUP_FROZEN; |
60 | task_lock(task); | 59 | rcu_read_unlock(); |
61 | result = __cgroup_freezing_or_frozen(task); | 60 | |
62 | task_unlock(task); | 61 | return ret; |
63 | return result; | ||
64 | } | 62 | } |
65 | 63 | ||
66 | /* | 64 | /* |
@@ -102,9 +100,6 @@ struct cgroup_subsys freezer_subsys; | |||
102 | * freezer_can_attach(): | 100 | * freezer_can_attach(): |
103 | * cgroup_mutex (held by caller of can_attach) | 101 | * cgroup_mutex (held by caller of can_attach) |
104 | * | 102 | * |
105 | * cgroup_freezing_or_frozen(): | ||
106 | * task->alloc_lock (to get task's cgroup) | ||
107 | * | ||
108 | * freezer_fork() (preserving fork() performance means can't take cgroup_mutex): | 103 | * freezer_fork() (preserving fork() performance means can't take cgroup_mutex): |
109 | * freezer->lock | 104 | * freezer->lock |
110 | * sighand->siglock (if the cgroup is freezing) | 105 | * sighand->siglock (if the cgroup is freezing) |
@@ -177,13 +172,7 @@ static int freezer_can_attach(struct cgroup_subsys *ss, | |||
177 | 172 | ||
178 | static int freezer_can_attach_task(struct cgroup *cgrp, struct task_struct *tsk) | 173 | static int freezer_can_attach_task(struct cgroup *cgrp, struct task_struct *tsk) |
179 | { | 174 | { |
180 | rcu_read_lock(); | 175 | return cgroup_freezing(tsk) ? -EBUSY : 0; |
181 | if (__cgroup_freezing_or_frozen(tsk)) { | ||
182 | rcu_read_unlock(); | ||
183 | return -EBUSY; | ||
184 | } | ||
185 | rcu_read_unlock(); | ||
186 | return 0; | ||
187 | } | 176 | } |
188 | 177 | ||
189 | static void freezer_fork(struct cgroup_subsys *ss, struct task_struct *task) | 178 | static void freezer_fork(struct cgroup_subsys *ss, struct task_struct *task) |
@@ -279,7 +268,6 @@ static int try_to_freeze_cgroup(struct cgroup *cgroup, struct freezer *freezer) | |||
279 | struct task_struct *task; | 268 | struct task_struct *task; |
280 | unsigned int num_cant_freeze_now = 0; | 269 | unsigned int num_cant_freeze_now = 0; |
281 | 270 | ||
282 | freezer->state = CGROUP_FREEZING; | ||
283 | cgroup_iter_start(cgroup, &it); | 271 | cgroup_iter_start(cgroup, &it); |
284 | while ((task = cgroup_iter_next(cgroup, &it))) { | 272 | while ((task = cgroup_iter_next(cgroup, &it))) { |
285 | if (!freeze_task(task, true)) | 273 | if (!freeze_task(task, true)) |
@@ -303,8 +291,6 @@ static void unfreeze_cgroup(struct cgroup *cgroup, struct freezer *freezer) | |||
303 | while ((task = cgroup_iter_next(cgroup, &it))) | 291 | while ((task = cgroup_iter_next(cgroup, &it))) |
304 | __thaw_task(task); | 292 | __thaw_task(task); |
305 | cgroup_iter_end(cgroup, &it); | 293 | cgroup_iter_end(cgroup, &it); |
306 | |||
307 | freezer->state = CGROUP_THAWED; | ||
308 | } | 294 | } |
309 | 295 | ||
310 | static int freezer_change_state(struct cgroup *cgroup, | 296 | static int freezer_change_state(struct cgroup *cgroup, |
@@ -318,20 +304,20 @@ static int freezer_change_state(struct cgroup *cgroup, | |||
318 | spin_lock_irq(&freezer->lock); | 304 | spin_lock_irq(&freezer->lock); |
319 | 305 | ||
320 | update_if_frozen(cgroup, freezer); | 306 | update_if_frozen(cgroup, freezer); |
321 | if (goal_state == freezer->state) | ||
322 | goto out; | ||
323 | 307 | ||
324 | switch (goal_state) { | 308 | switch (goal_state) { |
325 | case CGROUP_THAWED: | 309 | case CGROUP_THAWED: |
310 | freezer->state = CGROUP_THAWED; | ||
326 | unfreeze_cgroup(cgroup, freezer); | 311 | unfreeze_cgroup(cgroup, freezer); |
327 | break; | 312 | break; |
328 | case CGROUP_FROZEN: | 313 | case CGROUP_FROZEN: |
314 | freezer->state = CGROUP_FREEZING; | ||
329 | retval = try_to_freeze_cgroup(cgroup, freezer); | 315 | retval = try_to_freeze_cgroup(cgroup, freezer); |
330 | break; | 316 | break; |
331 | default: | 317 | default: |
332 | BUG(); | 318 | BUG(); |
333 | } | 319 | } |
334 | out: | 320 | |
335 | spin_unlock_irq(&freezer->lock); | 321 | spin_unlock_irq(&freezer->lock); |
336 | 322 | ||
337 | return retval; | 323 | return retval; |