aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/cgroup_freezer.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2011-11-21 15:32:25 -0500
committerTejun Heo <tj@kernel.org>2011-11-21 15:32:25 -0500
commit22b4e111fa01a1147aa562ceaf18a752a928ef4e (patch)
treef4b29f532678c72edf99bb8df3ba64d526bc8a3c /kernel/cgroup_freezer.c
parent03afed8bc296fa70186ba832c1126228bb992465 (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.c40
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
51static inline int __cgroup_freezing_or_frozen(struct task_struct *task) 51bool 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
57int 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
178static int freezer_can_attach_task(struct cgroup *cgrp, struct task_struct *tsk) 173static 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
189static void freezer_fork(struct cgroup_subsys *ss, struct task_struct *task) 178static 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
310static int freezer_change_state(struct cgroup *cgroup, 296static 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 }
334out: 320
335 spin_unlock_irq(&freezer->lock); 321 spin_unlock_irq(&freezer->lock);
336 322
337 return retval; 323 return retval;