|
@@ -2613,6 +2613,14 @@ static ssize_t cgroup_subtree_control_write(struct kernfs_open_file *of,
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
+ /* unavailable or not enabled on the parent? */
|
|
|
+ if (!(cgrp_dfl_root.subsys_mask & (1 << ssid)) ||
|
|
|
+ (cgroup_parent(cgrp) &&
|
|
|
+ !(cgroup_parent(cgrp)->child_subsys_mask & (1 << ssid)))) {
|
|
|
+ ret = -ENOENT;
|
|
|
+ goto out_unlock;
|
|
|
+ }
|
|
|
+
|
|
|
/*
|
|
|
* Because css offlining is asynchronous, userland
|
|
|
* might try to re-enable the same controller while
|
|
@@ -2635,14 +2643,6 @@ static ssize_t cgroup_subtree_control_write(struct kernfs_open_file *of,
|
|
|
|
|
|
return restart_syscall();
|
|
|
}
|
|
|
-
|
|
|
- /* unavailable or not enabled on the parent? */
|
|
|
- if (!(cgrp_dfl_root.subsys_mask & (1 << ssid)) ||
|
|
|
- (cgroup_parent(cgrp) &&
|
|
|
- !(cgroup_parent(cgrp)->child_subsys_mask & (1 << ssid)))) {
|
|
|
- ret = -ENOENT;
|
|
|
- goto out_unlock;
|
|
|
- }
|
|
|
} else if (disable & (1 << ssid)) {
|
|
|
if (!(cgrp->child_subsys_mask & (1 << ssid))) {
|
|
|
disable &= ~(1 << ssid);
|
|
@@ -2673,12 +2673,10 @@ static ssize_t cgroup_subtree_control_write(struct kernfs_open_file *of,
|
|
|
goto out_unlock;
|
|
|
}
|
|
|
|
|
|
- /*
|
|
|
- * Create csses for enables and update child_subsys_mask. This
|
|
|
- * changes cgroup_e_css() results which in turn makes the
|
|
|
- * subsequent cgroup_update_dfl_csses() associate all tasks in the
|
|
|
- * subtree to the updated csses.
|
|
|
- */
|
|
|
+ cgrp->child_subsys_mask |= enable;
|
|
|
+ cgrp->child_subsys_mask &= ~disable;
|
|
|
+
|
|
|
+ /* create new csses */
|
|
|
for_each_subsys(ss, ssid) {
|
|
|
if (!(enable & (1 << ssid)))
|
|
|
continue;
|
|
@@ -2690,9 +2688,11 @@ static ssize_t cgroup_subtree_control_write(struct kernfs_open_file *of,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- cgrp->child_subsys_mask |= enable;
|
|
|
- cgrp->child_subsys_mask &= ~disable;
|
|
|
-
|
|
|
+ /*
|
|
|
+ * At this point, cgroup_e_css() results reflect the new csses
|
|
|
+ * making the following cgroup_update_dfl_csses() properly update
|
|
|
+ * css associations of all tasks in the subtree.
|
|
|
+ */
|
|
|
ret = cgroup_update_dfl_csses(cgrp);
|
|
|
if (ret)
|
|
|
goto err_undo_css;
|