aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/cgroup_freezer.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2012-10-16 18:03:14 -0400
committerTejun Heo <tj@kernel.org>2012-10-16 18:03:14 -0400
commit51f246ed95caed12898649d8170d2d352da6af76 (patch)
tree28215338713b2aa79414e00adfb096ba7163248d /kernel/cgroup_freezer.c
parentdd67d32dbc5de299d70cc9e10c6c1e29ffa56b92 (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.c43
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 */
154static 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
267static int try_to_freeze_cgroup(struct cgroup *cgroup, struct freezer *freezer) 261static 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
287static void unfreeze_cgroup(struct cgroup *cgroup, struct freezer *freezer) 272static 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
298static int freezer_change_state(struct cgroup *cgroup, 283static 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
332static int freezer_write(struct cgroup *cgroup, 312static 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
353static struct cftype files[] = { 332static struct cftype files[] = {