Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

Tejun Heo 22b4e111 03afed8b

+17 -31
+3 -3
include/linux/freezer.h
··· 63 63 extern bool freeze_task(struct task_struct *p, bool sig_only); 64 64 65 65 #ifdef CONFIG_CGROUP_FREEZER 66 - extern int cgroup_freezing_or_frozen(struct task_struct *task); 66 + extern bool cgroup_freezing(struct task_struct *task); 67 67 #else /* !CONFIG_CGROUP_FREEZER */ 68 - static inline int cgroup_freezing_or_frozen(struct task_struct *task) 68 + static inline bool cgroup_freezing(struct task_struct *task) 69 69 { 70 - return 0; 70 + return false; 71 71 } 72 72 #endif /* !CONFIG_CGROUP_FREEZER */ 73 73
+13 -27
kernel/cgroup_freezer.c
··· 48 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; 54 - return (state == CGROUP_FREEZING) || (state == CGROUP_FROZEN); 55 - } 53 + enum freezer_state state; 54 + bool ret; 56 55 57 - int cgroup_freezing_or_frozen(struct task_struct *task) 58 - { 59 - int result; 60 - task_lock(task); 61 - result = __cgroup_freezing_or_frozen(task); 62 - task_unlock(task); 63 - return result; 56 + rcu_read_lock(); 57 + state = task_freezer(task)->state; 58 + ret = state == CGROUP_FREEZING || state == CGROUP_FROZEN; 59 + rcu_read_unlock(); 60 + 61 + return ret; 64 62 } 65 63 66 64 /* ··· 99 101 * 100 102 * freezer_can_attach(): 101 103 * cgroup_mutex (held by caller of can_attach) 102 - * 103 - * cgroup_freezing_or_frozen(): 104 - * task->alloc_lock (to get task's cgroup) 105 104 * 106 105 * freezer_fork() (preserving fork() performance means can't take cgroup_mutex): 107 106 * freezer->lock ··· 172 177 173 178 static int freezer_can_attach_task(struct cgroup *cgrp, struct task_struct *tsk) 174 179 { 175 - rcu_read_lock(); 176 - if (__cgroup_freezing_or_frozen(tsk)) { 177 - rcu_read_unlock(); 178 - return -EBUSY; 179 - } 180 - rcu_read_unlock(); 181 - return 0; 180 + return cgroup_freezing(tsk) ? -EBUSY : 0; 182 181 } 183 182 184 183 static void freezer_fork(struct cgroup_subsys *ss, struct task_struct *task) ··· 268 279 struct task_struct *task; 269 280 unsigned int num_cant_freeze_now = 0; 270 281 271 - freezer->state = CGROUP_FREEZING; 272 282 cgroup_iter_start(cgroup, &it); 273 283 while ((task = cgroup_iter_next(cgroup, &it))) { 274 284 if (!freeze_task(task, true)) ··· 291 303 while ((task = cgroup_iter_next(cgroup, &it))) 292 304 __thaw_task(task); 293 305 cgroup_iter_end(cgroup, &it); 294 - 295 - freezer->state = CGROUP_THAWED; 296 306 } 297 307 298 308 static int freezer_change_state(struct cgroup *cgroup, ··· 304 318 spin_lock_irq(&freezer->lock); 305 319 306 320 update_if_frozen(cgroup, freezer); 307 - if (goal_state == freezer->state) 308 - goto out; 309 321 310 322 switch (goal_state) { 311 323 case CGROUP_THAWED: 324 + freezer->state = CGROUP_THAWED; 312 325 unfreeze_cgroup(cgroup, freezer); 313 326 break; 314 327 case CGROUP_FROZEN: 328 + freezer->state = CGROUP_FREEZING; 315 329 retval = try_to_freeze_cgroup(cgroup, freezer); 316 330 break; 317 331 default: 318 332 BUG(); 319 333 } 320 - out: 334 + 321 335 spin_unlock_irq(&freezer->lock); 322 336 323 337 return retval;
+1 -1
kernel/power/process.c
··· 170 170 171 171 read_lock(&tasklist_lock); 172 172 do_each_thread(g, p) { 173 - if (cgroup_freezing_or_frozen(p)) 173 + if (cgroup_freezing(p)) 174 174 continue; 175 175 176 176 __thaw_task(p);