diff options
Diffstat (limited to 'kernel/cgroup_freezer.c')
-rw-r--r-- | kernel/cgroup_freezer.c | 43 |
1 files changed, 26 insertions, 17 deletions
diff --git a/kernel/cgroup_freezer.c b/kernel/cgroup_freezer.c index b08722de610c..df884022fbd9 100644 --- a/kernel/cgroup_freezer.c +++ b/kernel/cgroup_freezer.c | |||
@@ -145,22 +145,40 @@ static void freezer_destroy(struct cgroup_subsys *ss, | |||
145 | kfree(cgroup_freezer(cgroup)); | 145 | kfree(cgroup_freezer(cgroup)); |
146 | } | 146 | } |
147 | 147 | ||
148 | /* Task is frozen or will freeze immediately when next it gets woken */ | ||
149 | static bool is_task_frozen_enough(struct task_struct *task) | ||
150 | { | ||
151 | return frozen(task) || | ||
152 | (task_is_stopped_or_traced(task) && freezing(task)); | ||
153 | } | ||
148 | 154 | ||
155 | /* | ||
156 | * The call to cgroup_lock() in the freezer.state write method prevents | ||
157 | * a write to that file racing against an attach, and hence the | ||
158 | * can_attach() result will remain valid until the attach completes. | ||
159 | */ | ||
149 | static int freezer_can_attach(struct cgroup_subsys *ss, | 160 | static int freezer_can_attach(struct cgroup_subsys *ss, |
150 | struct cgroup *new_cgroup, | 161 | struct cgroup *new_cgroup, |
151 | struct task_struct *task) | 162 | struct task_struct *task) |
152 | { | 163 | { |
153 | struct freezer *freezer; | 164 | struct freezer *freezer; |
154 | int retval = 0; | 165 | int retval; |
166 | |||
167 | /* Anything frozen can't move or be moved to/from */ | ||
168 | |||
169 | if (is_task_frozen_enough(task)) | ||
170 | return -EBUSY; | ||
155 | 171 | ||
156 | /* | ||
157 | * The call to cgroup_lock() in the freezer.state write method prevents | ||
158 | * a write to that file racing against an attach, and hence the | ||
159 | * can_attach() result will remain valid until the attach completes. | ||
160 | */ | ||
161 | freezer = cgroup_freezer(new_cgroup); | 172 | freezer = cgroup_freezer(new_cgroup); |
162 | if (freezer->state == STATE_FROZEN) | 173 | if (freezer->state == STATE_FROZEN) |
174 | return -EBUSY; | ||
175 | |||
176 | retval = 0; | ||
177 | task_lock(task); | ||
178 | freezer = task_freezer(task); | ||
179 | if (freezer->state == STATE_FROZEN) | ||
163 | retval = -EBUSY; | 180 | retval = -EBUSY; |
181 | task_unlock(task); | ||
164 | return retval; | 182 | return retval; |
165 | } | 183 | } |
166 | 184 | ||
@@ -193,12 +211,7 @@ static void check_if_frozen(struct cgroup *cgroup, | |||
193 | cgroup_iter_start(cgroup, &it); | 211 | cgroup_iter_start(cgroup, &it); |
194 | while ((task = cgroup_iter_next(cgroup, &it))) { | 212 | while ((task = cgroup_iter_next(cgroup, &it))) { |
195 | ntotal++; | 213 | ntotal++; |
196 | /* | 214 | if (is_task_frozen_enough(task)) |
197 | * Task is frozen or will freeze immediately when next it gets | ||
198 | * woken | ||
199 | */ | ||
200 | if (frozen(task) || | ||
201 | (task_is_stopped_or_traced(task) && freezing(task))) | ||
202 | nfrozen++; | 215 | nfrozen++; |
203 | } | 216 | } |
204 | 217 | ||
@@ -249,11 +262,7 @@ static int try_to_freeze_cgroup(struct cgroup *cgroup, struct freezer *freezer) | |||
249 | while ((task = cgroup_iter_next(cgroup, &it))) { | 262 | while ((task = cgroup_iter_next(cgroup, &it))) { |
250 | if (!freeze_task(task, true)) | 263 | if (!freeze_task(task, true)) |
251 | continue; | 264 | continue; |
252 | if (task_is_stopped_or_traced(task) && freezing(task)) | 265 | if (is_task_frozen_enough(task)) |
253 | /* | ||
254 | * The freeze flag is set so these tasks will | ||
255 | * immediately go into the fridge upon waking. | ||
256 | */ | ||
257 | continue; | 266 | continue; |
258 | if (!freezing(task) && !freezer_should_skip(task)) | 267 | if (!freezing(task) && !freezer_should_skip(task)) |
259 | num_cant_freeze_now++; | 268 | num_cant_freeze_now++; |