diff options
author | Tejun Heo <tj@kernel.org> | 2012-10-16 18:03:14 -0400 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2012-10-16 18:03:14 -0400 |
commit | 51f246ed95caed12898649d8170d2d352da6af76 (patch) | |
tree | 28215338713b2aa79414e00adfb096ba7163248d /kernel/cgroup_freezer.c | |
parent | dd67d32dbc5de299d70cc9e10c6c1e29ffa56b92 (diff) |
cgroup_freezer: make it official that writes to freezer.state don't fail
try_to_freeze_cgroup() has condition checks which are intended to fail
the write operation to freezer.state if there are tasks which can't be
frozen. The condition checks have been broken for quite some time
now. freeze_task() returns %false if the target task can't be frozen,
so num_cant_freeze_now is never incremented.
In addition, strangely, cgroup freezing proceeds even after the write
is failed, which is rather broken.
This patch rips out the non-working code intended to fail the write to
freezer.state when the cgroup contains non-freezable tasks and makes
it official that writes to freezer.state succeed whether there are
non-freezable tasks in the cgroup or not.
This leaves is_task_frozen_enough() with only one user -
upste_if_frozen(). Collapse it into the caller. Note that this
removes an extra call to freezing().
This doesn't cause any userland behavior changes.
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Rafael J. Wysocki <rjw@sisk.pl>
Diffstat (limited to 'kernel/cgroup_freezer.c')
-rw-r--r-- | kernel/cgroup_freezer.c | 43 |
1 files changed, 11 insertions, 32 deletions
diff --git a/kernel/cgroup_freezer.c b/kernel/cgroup_freezer.c index 12bfedb598c2..05d52185139c 100644 --- a/kernel/cgroup_freezer.c +++ b/kernel/cgroup_freezer.c | |||
@@ -150,13 +150,6 @@ static void freezer_destroy(struct cgroup *cgroup) | |||
150 | kfree(freezer); | 150 | kfree(freezer); |
151 | } | 151 | } |
152 | 152 | ||
153 | /* task is frozen or will freeze immediately when next it gets woken */ | ||
154 | static bool is_task_frozen_enough(struct task_struct *task) | ||
155 | { | ||
156 | return frozen(task) || | ||
157 | (task_is_stopped_or_traced(task) && freezing(task)); | ||
158 | } | ||
159 | |||
160 | /* | 153 | /* |
161 | * The call to cgroup_lock() in the freezer.state write method prevents | 154 | * The call to cgroup_lock() in the freezer.state write method prevents |
162 | * a write to that file racing against an attach, and hence the | 155 | * a write to that file racing against an attach, and hence the |
@@ -222,7 +215,8 @@ static void update_if_frozen(struct cgroup *cgroup, | |||
222 | cgroup_iter_start(cgroup, &it); | 215 | cgroup_iter_start(cgroup, &it); |
223 | while ((task = cgroup_iter_next(cgroup, &it))) { | 216 | while ((task = cgroup_iter_next(cgroup, &it))) { |
224 | ntotal++; | 217 | ntotal++; |
225 | if (freezing(task) && is_task_frozen_enough(task)) | 218 | if (freezing(task) && (frozen(task) || |
219 | task_is_stopped_or_traced(task))) | ||
226 | nfrozen++; | 220 | nfrozen++; |
227 | } | 221 | } |
228 | 222 | ||
@@ -264,24 +258,15 @@ static int freezer_read(struct cgroup *cgroup, struct cftype *cft, | |||
264 | return 0; | 258 | return 0; |
265 | } | 259 | } |
266 | 260 | ||
267 | static int try_to_freeze_cgroup(struct cgroup *cgroup, struct freezer *freezer) | 261 | static void freeze_cgroup(struct cgroup *cgroup, struct freezer *freezer) |
268 | { | 262 | { |
269 | struct cgroup_iter it; | 263 | struct cgroup_iter it; |
270 | struct task_struct *task; | 264 | struct task_struct *task; |
271 | unsigned int num_cant_freeze_now = 0; | ||
272 | 265 | ||
273 | cgroup_iter_start(cgroup, &it); | 266 | cgroup_iter_start(cgroup, &it); |
274 | while ((task = cgroup_iter_next(cgroup, &it))) { | 267 | while ((task = cgroup_iter_next(cgroup, &it))) |
275 | if (!freeze_task(task)) | 268 | freeze_task(task); |
276 | continue; | ||
277 | if (is_task_frozen_enough(task)) | ||
278 | continue; | ||
279 | if (!freezing(task) && !freezer_should_skip(task)) | ||
280 | num_cant_freeze_now++; | ||
281 | } | ||
282 | cgroup_iter_end(cgroup, &it); | 269 | cgroup_iter_end(cgroup, &it); |
283 | |||
284 | return num_cant_freeze_now ? -EBUSY : 0; | ||
285 | } | 270 | } |
286 | 271 | ||
287 | static void unfreeze_cgroup(struct cgroup *cgroup, struct freezer *freezer) | 272 | static void unfreeze_cgroup(struct cgroup *cgroup, struct freezer *freezer) |
@@ -295,13 +280,10 @@ static void unfreeze_cgroup(struct cgroup *cgroup, struct freezer *freezer) | |||
295 | cgroup_iter_end(cgroup, &it); | 280 | cgroup_iter_end(cgroup, &it); |
296 | } | 281 | } |
297 | 282 | ||
298 | static int freezer_change_state(struct cgroup *cgroup, | 283 | static void freezer_change_state(struct cgroup *cgroup, |
299 | enum freezer_state goal_state) | 284 | enum freezer_state goal_state) |
300 | { | 285 | { |
301 | struct freezer *freezer; | 286 | struct freezer *freezer = cgroup_freezer(cgroup); |
302 | int retval = 0; | ||
303 | |||
304 | freezer = cgroup_freezer(cgroup); | ||
305 | 287 | ||
306 | spin_lock_irq(&freezer->lock); | 288 | spin_lock_irq(&freezer->lock); |
307 | 289 | ||
@@ -318,22 +300,19 @@ static int freezer_change_state(struct cgroup *cgroup, | |||
318 | if (freezer->state == CGROUP_THAWED) | 300 | if (freezer->state == CGROUP_THAWED) |
319 | atomic_inc(&system_freezing_cnt); | 301 | atomic_inc(&system_freezing_cnt); |
320 | freezer->state = CGROUP_FREEZING; | 302 | freezer->state = CGROUP_FREEZING; |
321 | retval = try_to_freeze_cgroup(cgroup, freezer); | 303 | freeze_cgroup(cgroup, freezer); |
322 | break; | 304 | break; |
323 | default: | 305 | default: |
324 | BUG(); | 306 | BUG(); |
325 | } | 307 | } |
326 | 308 | ||
327 | spin_unlock_irq(&freezer->lock); | 309 | spin_unlock_irq(&freezer->lock); |
328 | |||
329 | return retval; | ||
330 | } | 310 | } |
331 | 311 | ||
332 | static int freezer_write(struct cgroup *cgroup, | 312 | static int freezer_write(struct cgroup *cgroup, |
333 | struct cftype *cft, | 313 | struct cftype *cft, |
334 | const char *buffer) | 314 | const char *buffer) |
335 | { | 315 | { |
336 | int retval; | ||
337 | enum freezer_state goal_state; | 316 | enum freezer_state goal_state; |
338 | 317 | ||
339 | if (strcmp(buffer, freezer_state_strs[CGROUP_THAWED]) == 0) | 318 | if (strcmp(buffer, freezer_state_strs[CGROUP_THAWED]) == 0) |
@@ -345,9 +324,9 @@ static int freezer_write(struct cgroup *cgroup, | |||
345 | 324 | ||
346 | if (!cgroup_lock_live_group(cgroup)) | 325 | if (!cgroup_lock_live_group(cgroup)) |
347 | return -ENODEV; | 326 | return -ENODEV; |
348 | retval = freezer_change_state(cgroup, goal_state); | 327 | freezer_change_state(cgroup, goal_state); |
349 | cgroup_unlock(); | 328 | cgroup_unlock(); |
350 | return retval; | 329 | return 0; |
351 | } | 330 | } |
352 | 331 | ||
353 | static struct cftype files[] = { | 332 | static struct cftype files[] = { |