]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - kernel/cgroup_freezer.c
cgroup_freezer: make freezer->state mask of flags
[karo-tx-linux.git] / kernel / cgroup_freezer.c
index 2690830e742869dc2cff270283021ec074247d11..e76aa9fb3ef43cf6f0f3766eae5341b5ac0590ea 100644 (file)
 #include <linux/freezer.h>
 #include <linux/seq_file.h>
 
-enum freezer_state {
-       CGROUP_THAWED = 0,
-       CGROUP_FREEZING,
-       CGROUP_FROZEN,
+enum freezer_state_flags {
+       CGROUP_FREEZING         = (1 << 1), /* this freezer is freezing */
+       CGROUP_FROZEN           = (1 << 3), /* this and its descendants frozen */
 };
 
 struct freezer {
        struct cgroup_subsys_state      css;
-       enum freezer_state              state;
+       unsigned int                    state;
        spinlock_t                      lock;
 };
 
@@ -48,12 +47,10 @@ static inline struct freezer *task_freezer(struct task_struct *task)
 
 bool cgroup_freezing(struct task_struct *task)
 {
-       enum freezer_state state;
        bool ret;
 
        rcu_read_lock();
-       state = task_freezer(task)->state;
-       ret = state == CGROUP_FREEZING || state == CGROUP_FROZEN;
+       ret = task_freezer(task)->state & CGROUP_FREEZING;
        rcu_read_unlock();
 
        return ret;
@@ -63,10 +60,13 @@ bool cgroup_freezing(struct task_struct *task)
  * cgroups_write_string() limits the size of freezer state strings to
  * CGROUP_LOCAL_BUFFER_SIZE
  */
-static const char *freezer_state_strs[] = {
-       "THAWED",
-       "FREEZING",
-       "FROZEN",
+static const char *freezer_state_strs(unsigned int state)
+{
+       if (state & CGROUP_FROZEN)
+               return "FROZEN";
+       if (state & CGROUP_FREEZING)
+               return "FREEZING";
+       return "THAWED";
 };
 
 /*
@@ -91,7 +91,6 @@ static struct cgroup_subsys_state *freezer_create(struct cgroup *cgroup)
                return ERR_PTR(-ENOMEM);
 
        spin_lock_init(&freezer->lock);
-       freezer->state = CGROUP_THAWED;
        return &freezer->css;
 }
 
@@ -99,7 +98,7 @@ static void freezer_destroy(struct cgroup *cgroup)
 {
        struct freezer *freezer = cgroup_freezer(cgroup);
 
-       if (freezer->state != CGROUP_THAWED)
+       if (freezer->state & CGROUP_FREEZING)
                atomic_dec(&system_freezing_cnt);
        kfree(freezer);
 }
@@ -129,15 +128,13 @@ static void freezer_attach(struct cgroup *new_cgrp, struct cgroup_taskset *tset)
         * Tasks in @tset are on @new_cgrp but may not conform to its
         * current state before executing the following - !frozen tasks may
         * be visible in a FROZEN cgroup and frozen tasks in a THAWED one.
-        * This means that, to determine whether to freeze, one should test
-        * whether the state equals THAWED.
         */
        cgroup_taskset_for_each(task, new_cgrp, tset) {
-               if (freezer->state == CGROUP_THAWED) {
+               if (!(freezer->state & CGROUP_FREEZING)) {
                        __thaw_task(task);
                } else {
                        freeze_task(task);
-                       freezer->state = CGROUP_FREEZING;
+                       freezer->state &= ~CGROUP_FROZEN;
                }
        }
 
@@ -159,11 +156,7 @@ static void freezer_fork(struct task_struct *task)
                goto out;
 
        spin_lock_irq(&freezer->lock);
-       /*
-        * @task might have been just migrated into a FROZEN cgroup.  Test
-        * equality with THAWED.  Read the comment in freezer_attach().
-        */
-       if (freezer->state != CGROUP_THAWED)
+       if (freezer->state & CGROUP_FREEZING)
                freeze_task(task);
        spin_unlock_irq(&freezer->lock);
 out:
@@ -184,7 +177,8 @@ static void update_if_frozen(struct freezer *freezer)
        struct cgroup_iter it;
        struct task_struct *task;
 
-       if (freezer->state != CGROUP_FREEZING)
+       if (!(freezer->state & CGROUP_FREEZING) ||
+           (freezer->state & CGROUP_FROZEN))
                return;
 
        cgroup_iter_start(cgroup, &it);
@@ -202,7 +196,7 @@ static void update_if_frozen(struct freezer *freezer)
                }
        }
 
-       freezer->state = CGROUP_FROZEN;
+       freezer->state |= CGROUP_FROZEN;
 notyet:
        cgroup_iter_end(cgroup, &it);
 }
@@ -211,14 +205,14 @@ static int freezer_read(struct cgroup *cgroup, struct cftype *cft,
                        struct seq_file *m)
 {
        struct freezer *freezer = cgroup_freezer(cgroup);
-       enum freezer_state state;
+       unsigned int state;
 
        spin_lock_irq(&freezer->lock);
        update_if_frozen(freezer);
        state = freezer->state;
        spin_unlock_irq(&freezer->lock);
 
-       seq_puts(m, freezer_state_strs[state]);
+       seq_puts(m, freezer_state_strs(state));
        seq_putc(m, '\n');
        return 0;
 }
@@ -258,14 +252,14 @@ static void freezer_apply_state(struct freezer *freezer, bool freeze)
        lockdep_assert_held(&freezer->lock);
 
        if (freeze) {
-               if (freezer->state == CGROUP_THAWED)
+               if (!(freezer->state & CGROUP_FREEZING))
                        atomic_inc(&system_freezing_cnt);
-               freezer->state = CGROUP_FREEZING;
+               freezer->state |= CGROUP_FREEZING;
                freeze_cgroup(freezer);
        } else {
-               if (freezer->state != CGROUP_THAWED)
+               if (freezer->state & CGROUP_FREEZING)
                        atomic_dec(&system_freezing_cnt);
-               freezer->state = CGROUP_THAWED;
+               freezer->state &= ~(CGROUP_FREEZING | CGROUP_FROZEN);
                unfreeze_cgroup(freezer);
        }
 }
@@ -290,9 +284,9 @@ static int freezer_write(struct cgroup *cgroup, struct cftype *cft,
 {
        bool freeze;
 
-       if (strcmp(buffer, freezer_state_strs[CGROUP_THAWED]) == 0)
+       if (strcmp(buffer, freezer_state_strs(0)) == 0)
                freeze = false;
-       else if (strcmp(buffer, freezer_state_strs[CGROUP_FROZEN]) == 0)
+       else if (strcmp(buffer, freezer_state_strs(CGROUP_FROZEN)) == 0)
                freeze = true;
        else
                return -EINVAL;