aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/cgroup_freezer.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2012-11-09 12:12:30 -0500
committerTejun Heo <tj@kernel.org>2012-11-09 12:12:30 -0500
commitd6a2fe134219adf94e6bd0c8f6e2a3163ff68c41 (patch)
tree5e1a967eac89becbb0e480dc08906be20d3d3c2d /kernel/cgroup_freezer.c
parent04a4ec32571e88c614b229824afec376d24cc035 (diff)
cgroup_freezer: make freezer->state mask of flags
freezer->state was an enum value - one of THAWED, FREEZING and FROZEN. As the scheduled full hierarchy support requires more than one freezing condition, switch it to mask of flags. If FREEZING is not set, it's thawed. FREEZING is set if freezing or frozen. If frozen, both FREEZING and FROZEN are set. Now that tasks can be attached to an already frozen cgroup, this also makes freezing condition checks more natural. This patch doesn't introduce any behavior change. Signed-off-by: Tejun Heo <tj@kernel.org> Reviewed-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Reviewed-by: Michal Hocko <mhocko@suse.cz>
Diffstat (limited to 'kernel/cgroup_freezer.c')
-rw-r--r--kernel/cgroup_freezer.c60
1 files changed, 27 insertions, 33 deletions
diff --git a/kernel/cgroup_freezer.c b/kernel/cgroup_freezer.c
index 2690830e7428..e76aa9fb3ef4 100644
--- a/kernel/cgroup_freezer.c
+++ b/kernel/cgroup_freezer.c
@@ -22,15 +22,14 @@
22#include <linux/freezer.h> 22#include <linux/freezer.h>
23#include <linux/seq_file.h> 23#include <linux/seq_file.h>
24 24
25enum freezer_state { 25enum freezer_state_flags {
26 CGROUP_THAWED = 0, 26 CGROUP_FREEZING = (1 << 1), /* this freezer is freezing */
27 CGROUP_FREEZING, 27 CGROUP_FROZEN = (1 << 3), /* this and its descendants frozen */
28 CGROUP_FROZEN,
29}; 28};
30 29
31struct freezer { 30struct freezer {
32 struct cgroup_subsys_state css; 31 struct cgroup_subsys_state css;
33 enum freezer_state state; 32 unsigned int state;
34 spinlock_t lock; 33 spinlock_t lock;
35}; 34};
36 35
@@ -48,12 +47,10 @@ static inline struct freezer *task_freezer(struct task_struct *task)
48 47
49bool cgroup_freezing(struct task_struct *task) 48bool cgroup_freezing(struct task_struct *task)
50{ 49{
51 enum freezer_state state;
52 bool ret; 50 bool ret;
53 51
54 rcu_read_lock(); 52 rcu_read_lock();
55 state = task_freezer(task)->state; 53 ret = task_freezer(task)->state & CGROUP_FREEZING;
56 ret = state == CGROUP_FREEZING || state == CGROUP_FROZEN;
57 rcu_read_unlock(); 54 rcu_read_unlock();
58 55
59 return ret; 56 return ret;
@@ -63,10 +60,13 @@ bool cgroup_freezing(struct task_struct *task)
63 * cgroups_write_string() limits the size of freezer state strings to 60 * cgroups_write_string() limits the size of freezer state strings to
64 * CGROUP_LOCAL_BUFFER_SIZE 61 * CGROUP_LOCAL_BUFFER_SIZE
65 */ 62 */
66static const char *freezer_state_strs[] = { 63static const char *freezer_state_strs(unsigned int state)
67 "THAWED", 64{
68 "FREEZING", 65 if (state & CGROUP_FROZEN)
69 "FROZEN", 66 return "FROZEN";
67 if (state & CGROUP_FREEZING)
68 return "FREEZING";
69 return "THAWED";
70}; 70};
71 71
72/* 72/*
@@ -91,7 +91,6 @@ static struct cgroup_subsys_state *freezer_create(struct cgroup *cgroup)
91 return ERR_PTR(-ENOMEM); 91 return ERR_PTR(-ENOMEM);
92 92
93 spin_lock_init(&freezer->lock); 93 spin_lock_init(&freezer->lock);
94 freezer->state = CGROUP_THAWED;
95 return &freezer->css; 94 return &freezer->css;
96} 95}
97 96
@@ -99,7 +98,7 @@ static void freezer_destroy(struct cgroup *cgroup)
99{ 98{
100 struct freezer *freezer = cgroup_freezer(cgroup); 99 struct freezer *freezer = cgroup_freezer(cgroup);
101 100
102 if (freezer->state != CGROUP_THAWED) 101 if (freezer->state & CGROUP_FREEZING)
103 atomic_dec(&system_freezing_cnt); 102 atomic_dec(&system_freezing_cnt);
104 kfree(freezer); 103 kfree(freezer);
105} 104}
@@ -129,15 +128,13 @@ static void freezer_attach(struct cgroup *new_cgrp, struct cgroup_taskset *tset)
129 * Tasks in @tset are on @new_cgrp but may not conform to its 128 * Tasks in @tset are on @new_cgrp but may not conform to its
130 * current state before executing the following - !frozen tasks may 129 * current state before executing the following - !frozen tasks may
131 * be visible in a FROZEN cgroup and frozen tasks in a THAWED one. 130 * be visible in a FROZEN cgroup and frozen tasks in a THAWED one.
132 * This means that, to determine whether to freeze, one should test
133 * whether the state equals THAWED.
134 */ 131 */
135 cgroup_taskset_for_each(task, new_cgrp, tset) { 132 cgroup_taskset_for_each(task, new_cgrp, tset) {
136 if (freezer->state == CGROUP_THAWED) { 133 if (!(freezer->state & CGROUP_FREEZING)) {
137 __thaw_task(task); 134 __thaw_task(task);
138 } else { 135 } else {
139 freeze_task(task); 136 freeze_task(task);
140 freezer->state = CGROUP_FREEZING; 137 freezer->state &= ~CGROUP_FROZEN;
141 } 138 }
142 } 139 }
143 140
@@ -159,11 +156,7 @@ static void freezer_fork(struct task_struct *task)
159 goto out; 156 goto out;
160 157
161 spin_lock_irq(&freezer->lock); 158 spin_lock_irq(&freezer->lock);
162 /* 159 if (freezer->state & CGROUP_FREEZING)
163 * @task might have been just migrated into a FROZEN cgroup. Test
164 * equality with THAWED. Read the comment in freezer_attach().
165 */
166 if (freezer->state != CGROUP_THAWED)
167 freeze_task(task); 160 freeze_task(task);
168 spin_unlock_irq(&freezer->lock); 161 spin_unlock_irq(&freezer->lock);
169out: 162out:
@@ -184,7 +177,8 @@ static void update_if_frozen(struct freezer *freezer)
184 struct cgroup_iter it; 177 struct cgroup_iter it;
185 struct task_struct *task; 178 struct task_struct *task;
186 179
187 if (freezer->state != CGROUP_FREEZING) 180 if (!(freezer->state & CGROUP_FREEZING) ||
181 (freezer->state & CGROUP_FROZEN))
188 return; 182 return;
189 183
190 cgroup_iter_start(cgroup, &it); 184 cgroup_iter_start(cgroup, &it);
@@ -202,7 +196,7 @@ static void update_if_frozen(struct freezer *freezer)
202 } 196 }
203 } 197 }
204 198
205 freezer->state = CGROUP_FROZEN; 199 freezer->state |= CGROUP_FROZEN;
206notyet: 200notyet:
207 cgroup_iter_end(cgroup, &it); 201 cgroup_iter_end(cgroup, &it);
208} 202}
@@ -211,14 +205,14 @@ static int freezer_read(struct cgroup *cgroup, struct cftype *cft,
211 struct seq_file *m) 205 struct seq_file *m)
212{ 206{
213 struct freezer *freezer = cgroup_freezer(cgroup); 207 struct freezer *freezer = cgroup_freezer(cgroup);
214 enum freezer_state state; 208 unsigned int state;
215 209
216 spin_lock_irq(&freezer->lock); 210 spin_lock_irq(&freezer->lock);
217 update_if_frozen(freezer); 211 update_if_frozen(freezer);
218 state = freezer->state; 212 state = freezer->state;
219 spin_unlock_irq(&freezer->lock); 213 spin_unlock_irq(&freezer->lock);
220 214
221 seq_puts(m, freezer_state_strs[state]); 215 seq_puts(m, freezer_state_strs(state));
222 seq_putc(m, '\n'); 216 seq_putc(m, '\n');
223 return 0; 217 return 0;
224} 218}
@@ -258,14 +252,14 @@ static void freezer_apply_state(struct freezer *freezer, bool freeze)
258 lockdep_assert_held(&freezer->lock); 252 lockdep_assert_held(&freezer->lock);
259 253
260 if (freeze) { 254 if (freeze) {
261 if (freezer->state == CGROUP_THAWED) 255 if (!(freezer->state & CGROUP_FREEZING))
262 atomic_inc(&system_freezing_cnt); 256 atomic_inc(&system_freezing_cnt);
263 freezer->state = CGROUP_FREEZING; 257 freezer->state |= CGROUP_FREEZING;
264 freeze_cgroup(freezer); 258 freeze_cgroup(freezer);
265 } else { 259 } else {
266 if (freezer->state != CGROUP_THAWED) 260 if (freezer->state & CGROUP_FREEZING)
267 atomic_dec(&system_freezing_cnt); 261 atomic_dec(&system_freezing_cnt);
268 freezer->state = CGROUP_THAWED; 262 freezer->state &= ~(CGROUP_FREEZING | CGROUP_FROZEN);
269 unfreeze_cgroup(freezer); 263 unfreeze_cgroup(freezer);
270 } 264 }
271} 265}
@@ -290,9 +284,9 @@ static int freezer_write(struct cgroup *cgroup, struct cftype *cft,
290{ 284{
291 bool freeze; 285 bool freeze;
292 286
293 if (strcmp(buffer, freezer_state_strs[CGROUP_THAWED]) == 0) 287 if (strcmp(buffer, freezer_state_strs(0)) == 0)
294 freeze = false; 288 freeze = false;
295 else if (strcmp(buffer, freezer_state_strs[CGROUP_FROZEN]) == 0) 289 else if (strcmp(buffer, freezer_state_strs(CGROUP_FROZEN)) == 0)
296 freeze = true; 290 freeze = true;
297 else 291 else
298 return -EINVAL; 292 return -EINVAL;