]> git.karo-electronics.de Git - karo-tx-linux.git/blob - kernel/cgroup_freezer.c
video: mxsfb: fix typo: 'FAILING' instead of 'FALLING'
[karo-tx-linux.git] / kernel / cgroup_freezer.c
1 /*
2  * cgroup_freezer.c -  control group freezer subsystem
3  *
4  * Copyright IBM Corporation, 2007
5  *
6  * Author : Cedric Le Goater <clg@fr.ibm.com>
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of version 2.1 of the GNU Lesser General Public License
10  * as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it would be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15  */
16
17 #include <linux/export.h>
18 #include <linux/slab.h>
19 #include <linux/cgroup.h>
20 #include <linux/fs.h>
21 #include <linux/uaccess.h>
22 #include <linux/freezer.h>
23 #include <linux/seq_file.h>
24
25 /*
26  * A cgroup is freezing if any FREEZING flags are set.  FREEZING_SELF is
27  * set if "FROZEN" is written to freezer.state cgroupfs file, and cleared
28  * for "THAWED".  FREEZING_PARENT is set if the parent freezer is FREEZING
29  * for whatever reason.  IOW, a cgroup has FREEZING_PARENT set if one of
30  * its ancestors has FREEZING_SELF set.
31  */
32 enum freezer_state_flags {
33         CGROUP_FREEZER_ONLINE   = (1 << 0), /* freezer is fully online */
34         CGROUP_FREEZING_SELF    = (1 << 1), /* this freezer is freezing */
35         CGROUP_FREEZING_PARENT  = (1 << 2), /* the parent freezer is freezing */
36         CGROUP_FROZEN           = (1 << 3), /* this and its descendants frozen */
37
38         /* mask for all FREEZING flags */
39         CGROUP_FREEZING         = CGROUP_FREEZING_SELF | CGROUP_FREEZING_PARENT,
40 };
41
42 struct freezer {
43         struct cgroup_subsys_state      css;
44         unsigned int                    state;
45         spinlock_t                      lock;
46 };
47
48 static inline struct freezer *cgroup_freezer(struct cgroup *cgroup)
49 {
50         return container_of(cgroup_subsys_state(cgroup, freezer_subsys_id),
51                             struct freezer, css);
52 }
53
54 static inline struct freezer *task_freezer(struct task_struct *task)
55 {
56         return container_of(task_subsys_state(task, freezer_subsys_id),
57                             struct freezer, css);
58 }
59
60 static struct freezer *parent_freezer(struct freezer *freezer)
61 {
62         struct cgroup *pcg = freezer->css.cgroup->parent;
63
64         if (pcg)
65                 return cgroup_freezer(pcg);
66         return NULL;
67 }
68
69 bool cgroup_freezing(struct task_struct *task)
70 {
71         bool ret;
72
73         rcu_read_lock();
74         ret = task_freezer(task)->state & CGROUP_FREEZING;
75         rcu_read_unlock();
76
77         return ret;
78 }
79
80 /*
81  * cgroups_write_string() limits the size of freezer state strings to
82  * CGROUP_LOCAL_BUFFER_SIZE
83  */
84 static const char *freezer_state_strs(unsigned int state)
85 {
86         if (state & CGROUP_FROZEN)
87                 return "FROZEN";
88         if (state & CGROUP_FREEZING)
89                 return "FREEZING";
90         return "THAWED";
91 };
92
93 struct cgroup_subsys freezer_subsys;
94
95 static struct cgroup_subsys_state *freezer_create(struct cgroup *cgroup)
96 {
97         struct freezer *freezer;
98
99         freezer = kzalloc(sizeof(struct freezer), GFP_KERNEL);
100         if (!freezer)
101                 return ERR_PTR(-ENOMEM);
102
103         spin_lock_init(&freezer->lock);
104         return &freezer->css;
105 }
106
107 /**
108  * freezer_post_create - commit creation of a freezer cgroup
109  * @cgroup: cgroup being created
110  *
111  * We're committing to creation of @cgroup.  Mark it online and inherit
112  * parent's freezing state while holding both parent's and our
113  * freezer->lock.
114  */
115 static void freezer_post_create(struct cgroup *cgroup)
116 {
117         struct freezer *freezer = cgroup_freezer(cgroup);
118         struct freezer *parent = parent_freezer(freezer);
119
120         /*
121          * The following double locking and freezing state inheritance
122          * guarantee that @cgroup can never escape ancestors' freezing
123          * states.  See cgroup_for_each_descendant_pre() for details.
124          */
125         if (parent)
126                 spin_lock_irq(&parent->lock);
127         spin_lock_nested(&freezer->lock, SINGLE_DEPTH_NESTING);
128
129         freezer->state |= CGROUP_FREEZER_ONLINE;
130
131         if (parent && (parent->state & CGROUP_FREEZING)) {
132                 freezer->state |= CGROUP_FREEZING_PARENT | CGROUP_FROZEN;
133                 atomic_inc(&system_freezing_cnt);
134         }
135
136         spin_unlock(&freezer->lock);
137         if (parent)
138                 spin_unlock_irq(&parent->lock);
139 }
140
141 /**
142  * freezer_pre_destroy - initiate destruction of @cgroup
143  * @cgroup: cgroup being destroyed
144  *
145  * @cgroup is going away.  Mark it dead and decrement system_freezing_count
146  * if it was holding one.
147  */
148 static void freezer_pre_destroy(struct cgroup *cgroup)
149 {
150         struct freezer *freezer = cgroup_freezer(cgroup);
151
152         spin_lock_irq(&freezer->lock);
153
154         if (freezer->state & CGROUP_FREEZING)
155                 atomic_dec(&system_freezing_cnt);
156
157         freezer->state = 0;
158
159         spin_unlock_irq(&freezer->lock);
160 }
161
162 static void freezer_destroy(struct cgroup *cgroup)
163 {
164         kfree(cgroup_freezer(cgroup));
165 }
166
167 /*
168  * Tasks can be migrated into a different freezer anytime regardless of its
169  * current state.  freezer_attach() is responsible for making new tasks
170  * conform to the current state.
171  *
172  * Freezer state changes and task migration are synchronized via
173  * @freezer->lock.  freezer_attach() makes the new tasks conform to the
174  * current state and all following state changes can see the new tasks.
175  */
176 static void freezer_attach(struct cgroup *new_cgrp, struct cgroup_taskset *tset)
177 {
178         struct freezer *freezer = cgroup_freezer(new_cgrp);
179         struct task_struct *task;
180         bool clear_frozen = false;
181
182         spin_lock_irq(&freezer->lock);
183
184         /*
185          * Make the new tasks conform to the current state of @new_cgrp.
186          * For simplicity, when migrating any task to a FROZEN cgroup, we
187          * revert it to FREEZING and let update_if_frozen() determine the
188          * correct state later.
189          *
190          * Tasks in @tset are on @new_cgrp but may not conform to its
191          * current state before executing the following - !frozen tasks may
192          * be visible in a FROZEN cgroup and frozen tasks in a THAWED one.
193          */
194         cgroup_taskset_for_each(task, new_cgrp, tset) {
195                 if (!(freezer->state & CGROUP_FREEZING)) {
196                         __thaw_task(task);
197                 } else {
198                         freeze_task(task);
199                         freezer->state &= ~CGROUP_FROZEN;
200                         clear_frozen = true;
201                 }
202         }
203
204         spin_unlock_irq(&freezer->lock);
205
206         /*
207          * Propagate FROZEN clearing upwards.  We may race with
208          * update_if_frozen(), but as long as both work bottom-up, either
209          * update_if_frozen() sees child's FROZEN cleared or we clear the
210          * parent's FROZEN later.  No parent w/ !FROZEN children can be
211          * left FROZEN.
212          */
213         while (clear_frozen && (freezer = parent_freezer(freezer))) {
214                 spin_lock_irq(&freezer->lock);
215                 freezer->state &= ~CGROUP_FROZEN;
216                 clear_frozen = freezer->state & CGROUP_FREEZING;
217                 spin_unlock_irq(&freezer->lock);
218         }
219 }
220
221 static void freezer_fork(struct task_struct *task)
222 {
223         struct freezer *freezer;
224
225         rcu_read_lock();
226         freezer = task_freezer(task);
227
228         /*
229          * The root cgroup is non-freezable, so we can skip the
230          * following check.
231          */
232         if (!freezer->css.cgroup->parent)
233                 goto out;
234
235         spin_lock_irq(&freezer->lock);
236         if (freezer->state & CGROUP_FREEZING)
237                 freeze_task(task);
238         spin_unlock_irq(&freezer->lock);
239 out:
240         rcu_read_unlock();
241 }
242
243 /**
244  * update_if_frozen - update whether a cgroup finished freezing
245  * @cgroup: cgroup of interest
246  *
247  * Once FREEZING is initiated, transition to FROZEN is lazily updated by
248  * calling this function.  If the current state is FREEZING but not FROZEN,
249  * this function checks whether all tasks of this cgroup and the descendant
250  * cgroups finished freezing and, if so, sets FROZEN.
251  *
252  * The caller is responsible for grabbing RCU read lock and calling
253  * update_if_frozen() on all descendants prior to invoking this function.
254  *
255  * Task states and freezer state might disagree while tasks are being
256  * migrated into or out of @cgroup, so we can't verify task states against
257  * @freezer state here.  See freezer_attach() for details.
258  */
259 static void update_if_frozen(struct cgroup *cgroup)
260 {
261         struct freezer *freezer = cgroup_freezer(cgroup);
262         struct cgroup *pos;
263         struct cgroup_iter it;
264         struct task_struct *task;
265
266         WARN_ON_ONCE(!rcu_read_lock_held());
267
268         spin_lock_irq(&freezer->lock);
269
270         if (!(freezer->state & CGROUP_FREEZING) ||
271             (freezer->state & CGROUP_FROZEN))
272                 goto out_unlock;
273
274         /* are all (live) children frozen? */
275         cgroup_for_each_child(pos, cgroup) {
276                 struct freezer *child = cgroup_freezer(pos);
277
278                 if ((child->state & CGROUP_FREEZER_ONLINE) &&
279                     !(child->state & CGROUP_FROZEN))
280                         goto out_unlock;
281         }
282
283         /* are all tasks frozen? */
284         cgroup_iter_start(cgroup, &it);
285
286         while ((task = cgroup_iter_next(cgroup, &it))) {
287                 if (freezing(task)) {
288                         /*
289                          * freezer_should_skip() indicates that the task
290                          * should be skipped when determining freezing
291                          * completion.  Consider it frozen in addition to
292                          * the usual frozen condition.
293                          */
294                         if (!frozen(task) && !freezer_should_skip(task))
295                                 goto out_iter_end;
296                 }
297         }
298
299         freezer->state |= CGROUP_FROZEN;
300 out_iter_end:
301         cgroup_iter_end(cgroup, &it);
302 out_unlock:
303         spin_unlock_irq(&freezer->lock);
304 }
305
306 static int freezer_read(struct cgroup *cgroup, struct cftype *cft,
307                         struct seq_file *m)
308 {
309         struct cgroup *pos;
310
311         rcu_read_lock();
312
313         /* update states bottom-up */
314         cgroup_for_each_descendant_post(pos, cgroup)
315                 update_if_frozen(pos);
316         update_if_frozen(cgroup);
317
318         rcu_read_unlock();
319
320         seq_puts(m, freezer_state_strs(cgroup_freezer(cgroup)->state));
321         seq_putc(m, '\n');
322         return 0;
323 }
324
325 static void freeze_cgroup(struct freezer *freezer)
326 {
327         struct cgroup *cgroup = freezer->css.cgroup;
328         struct cgroup_iter it;
329         struct task_struct *task;
330
331         cgroup_iter_start(cgroup, &it);
332         while ((task = cgroup_iter_next(cgroup, &it)))
333                 freeze_task(task);
334         cgroup_iter_end(cgroup, &it);
335 }
336
337 static void unfreeze_cgroup(struct freezer *freezer)
338 {
339         struct cgroup *cgroup = freezer->css.cgroup;
340         struct cgroup_iter it;
341         struct task_struct *task;
342
343         cgroup_iter_start(cgroup, &it);
344         while ((task = cgroup_iter_next(cgroup, &it)))
345                 __thaw_task(task);
346         cgroup_iter_end(cgroup, &it);
347 }
348
349 /**
350  * freezer_apply_state - apply state change to a single cgroup_freezer
351  * @freezer: freezer to apply state change to
352  * @freeze: whether to freeze or unfreeze
353  * @state: CGROUP_FREEZING_* flag to set or clear
354  *
355  * Set or clear @state on @cgroup according to @freeze, and perform
356  * freezing or thawing as necessary.
357  */
358 static void freezer_apply_state(struct freezer *freezer, bool freeze,
359                                 unsigned int state)
360 {
361         /* also synchronizes against task migration, see freezer_attach() */
362         lockdep_assert_held(&freezer->lock);
363
364         if (!(freezer->state & CGROUP_FREEZER_ONLINE))
365                 return;
366
367         if (freeze) {
368                 if (!(freezer->state & CGROUP_FREEZING))
369                         atomic_inc(&system_freezing_cnt);
370                 freezer->state |= state;
371                 freeze_cgroup(freezer);
372         } else {
373                 bool was_freezing = freezer->state & CGROUP_FREEZING;
374
375                 freezer->state &= ~state;
376
377                 if (!(freezer->state & CGROUP_FREEZING)) {
378                         if (was_freezing)
379                                 atomic_dec(&system_freezing_cnt);
380                         freezer->state &= ~CGROUP_FROZEN;
381                         unfreeze_cgroup(freezer);
382                 }
383         }
384 }
385
386 /**
387  * freezer_change_state - change the freezing state of a cgroup_freezer
388  * @freezer: freezer of interest
389  * @freeze: whether to freeze or thaw
390  *
391  * Freeze or thaw @freezer according to @freeze.  The operations are
392  * recursive - all descendants of @freezer will be affected.
393  */
394 static void freezer_change_state(struct freezer *freezer, bool freeze)
395 {
396         struct cgroup *pos;
397
398         /* update @freezer */
399         spin_lock_irq(&freezer->lock);
400         freezer_apply_state(freezer, freeze, CGROUP_FREEZING_SELF);
401         spin_unlock_irq(&freezer->lock);
402
403         /*
404          * Update all its descendants in pre-order traversal.  Each
405          * descendant will try to inherit its parent's FREEZING state as
406          * CGROUP_FREEZING_PARENT.
407          */
408         rcu_read_lock();
409         cgroup_for_each_descendant_pre(pos, freezer->css.cgroup) {
410                 struct freezer *pos_f = cgroup_freezer(pos);
411                 struct freezer *parent = parent_freezer(pos_f);
412
413                 /*
414                  * Our update to @parent->state is already visible which is
415                  * all we need.  No need to lock @parent.  For more info on
416                  * synchronization, see freezer_post_create().
417                  */
418                 spin_lock_irq(&pos_f->lock);
419                 freezer_apply_state(pos_f, parent->state & CGROUP_FREEZING,
420                                     CGROUP_FREEZING_PARENT);
421                 spin_unlock_irq(&pos_f->lock);
422         }
423         rcu_read_unlock();
424 }
425
426 static int freezer_write(struct cgroup *cgroup, struct cftype *cft,
427                          const char *buffer)
428 {
429         bool freeze;
430
431         if (strcmp(buffer, freezer_state_strs(0)) == 0)
432                 freeze = false;
433         else if (strcmp(buffer, freezer_state_strs(CGROUP_FROZEN)) == 0)
434                 freeze = true;
435         else
436                 return -EINVAL;
437
438         freezer_change_state(cgroup_freezer(cgroup), freeze);
439         return 0;
440 }
441
442 static u64 freezer_self_freezing_read(struct cgroup *cgroup, struct cftype *cft)
443 {
444         struct freezer *freezer = cgroup_freezer(cgroup);
445
446         return (bool)(freezer->state & CGROUP_FREEZING_SELF);
447 }
448
449 static u64 freezer_parent_freezing_read(struct cgroup *cgroup, struct cftype *cft)
450 {
451         struct freezer *freezer = cgroup_freezer(cgroup);
452
453         return (bool)(freezer->state & CGROUP_FREEZING_PARENT);
454 }
455
456 static struct cftype files[] = {
457         {
458                 .name = "state",
459                 .flags = CFTYPE_NOT_ON_ROOT,
460                 .read_seq_string = freezer_read,
461                 .write_string = freezer_write,
462         },
463         {
464                 .name = "self_freezing",
465                 .flags = CFTYPE_NOT_ON_ROOT,
466                 .read_u64 = freezer_self_freezing_read,
467         },
468         {
469                 .name = "parent_freezing",
470                 .flags = CFTYPE_NOT_ON_ROOT,
471                 .read_u64 = freezer_parent_freezing_read,
472         },
473         { }     /* terminate */
474 };
475
476 struct cgroup_subsys freezer_subsys = {
477         .name           = "freezer",
478         .create         = freezer_create,
479         .post_create    = freezer_post_create,
480         .pre_destroy    = freezer_pre_destroy,
481         .destroy        = freezer_destroy,
482         .subsys_id      = freezer_subsys_id,
483         .attach         = freezer_attach,
484         .fork           = freezer_fork,
485         .base_cftypes   = files,
486 };