cgroup: restructure child_subsys_mask handling in cgroup_subtree_control_write()
authorTejun Heo <tj@kernel.org>
Tue, 18 Nov 2014 07:49:50 +0000 (02:49 -0500)
committerTejun Heo <tj@kernel.org>
Tue, 18 Nov 2014 07:49:50 +0000 (02:49 -0500)
Make cgroup_subtree_control_write() first calculate new
subtree_control (new_sc), child_subsys_mask (new_ss) and
css_enable/disable masks before applying them to the cgroup.  Also,
store the original subtree_control (old_sc) and child_subsys_mask
(old_ss) and use them to restore the orignal state after failure.

This patch shouldn't cause any behavior changes.  This prepares for a
fix for a bug in the async css offline wait logic.

Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: Zefan Li <lizefan@huawei.com>
kernel/cgroup.c

index 1dda601..cbbb46f 100644 (file)
@@ -2653,7 +2653,7 @@ static ssize_t cgroup_subtree_control_write(struct kernfs_open_file *of,
                                            loff_t off)
 {
        unsigned int enable = 0, disable = 0;
-       unsigned int css_enable, css_disable, old_ctrl, new_ctrl;
+       unsigned int css_enable, css_disable, old_sc, new_sc, old_ss, new_ss;
        struct cgroup *cgrp, *child;
        struct cgroup_subsys *ss;
        char *tok;
@@ -2770,18 +2770,19 @@ static ssize_t cgroup_subtree_control_write(struct kernfs_open_file *of,
         * subsystems than specified may need to be enabled or disabled
         * depending on subsystem dependencies.
         */
-       cgrp->subtree_control |= enable;
-       cgrp->subtree_control &= ~disable;
+       old_sc = cgrp->subtree_control;
+       old_ss = cgrp->child_subsys_mask;
+       new_sc = (old_sc | enable) & ~disable;
+       new_ss = cgroup_calc_child_subsys_mask(cgrp, new_sc);
 
-       old_ctrl = cgrp->child_subsys_mask;
-       cgroup_refresh_child_subsys_mask(cgrp);
-       new_ctrl = cgrp->child_subsys_mask;
-
-       css_enable = ~old_ctrl & new_ctrl;
-       css_disable = old_ctrl & ~new_ctrl;
+       css_enable = ~old_ss & new_ss;
+       css_disable = old_ss & ~new_ss;
        enable |= css_enable;
        disable |= css_disable;
 
+       cgrp->subtree_control = new_sc;
+       cgrp->child_subsys_mask = new_ss;
+
        /*
         * Create new csses or make the existing ones visible.  A css is
         * created invisible if it's being implicitly enabled through
@@ -2844,9 +2845,8 @@ out_unlock:
        return ret ?: nbytes;
 
 err_undo_css:
-       cgrp->subtree_control &= ~enable;
-       cgrp->subtree_control |= disable;
-       cgroup_refresh_child_subsys_mask(cgrp);
+       cgrp->subtree_control = old_sc;
+       cgrp->child_subsys_mask = old_ss;
 
        for_each_subsys(ss, ssid) {
                if (!(enable & (1 << ssid)))