aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/cgroup.c58
1 files changed, 28 insertions, 30 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index cbbb46f783de..dffa54041d4a 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -2705,36 +2705,6 @@ static ssize_t cgroup_subtree_control_write(struct kernfs_open_file *of,
2705 ret = -ENOENT; 2705 ret = -ENOENT;
2706 goto out_unlock; 2706 goto out_unlock;
2707 } 2707 }
2708
2709 /*
2710 * @ss is already enabled through dependency and
2711 * we'll just make it visible. Skip draining.
2712 */
2713 if (cgrp->child_subsys_mask & (1 << ssid))
2714 continue;
2715
2716 /*
2717 * Because css offlining is asynchronous, userland
2718 * might try to re-enable the same controller while
2719 * the previous instance is still around. In such
2720 * cases, wait till it's gone using offline_waitq.
2721 */
2722 cgroup_for_each_live_child(child, cgrp) {
2723 DEFINE_WAIT(wait);
2724
2725 if (!cgroup_css(child, ss))
2726 continue;
2727
2728 cgroup_get(child);
2729 prepare_to_wait(&child->offline_waitq, &wait,
2730 TASK_UNINTERRUPTIBLE);
2731 cgroup_kn_unlock(of->kn);
2732 schedule();
2733 finish_wait(&child->offline_waitq, &wait);
2734 cgroup_put(child);
2735
2736 return restart_syscall();
2737 }
2738 } else if (disable & (1 << ssid)) { 2708 } else if (disable & (1 << ssid)) {
2739 if (!(cgrp->subtree_control & (1 << ssid))) { 2709 if (!(cgrp->subtree_control & (1 << ssid))) {
2740 disable &= ~(1 << ssid); 2710 disable &= ~(1 << ssid);
@@ -2780,6 +2750,34 @@ static ssize_t cgroup_subtree_control_write(struct kernfs_open_file *of,
2780 enable |= css_enable; 2750 enable |= css_enable;
2781 disable |= css_disable; 2751 disable |= css_disable;
2782 2752
2753 /*
2754 * Because css offlining is asynchronous, userland might try to
2755 * re-enable the same controller while the previous instance is
2756 * still around. In such cases, wait till it's gone using
2757 * offline_waitq.
2758 */
2759 for_each_subsys(ss, ssid) {
2760 if (!(css_enable & (1 << ssid)))
2761 continue;
2762
2763 cgroup_for_each_live_child(child, cgrp) {
2764 DEFINE_WAIT(wait);
2765
2766 if (!cgroup_css(child, ss))
2767 continue;
2768
2769 cgroup_get(child);
2770 prepare_to_wait(&child->offline_waitq, &wait,
2771 TASK_UNINTERRUPTIBLE);
2772 cgroup_kn_unlock(of->kn);
2773 schedule();
2774 finish_wait(&child->offline_waitq, &wait);
2775 cgroup_put(child);
2776
2777 return restart_syscall();
2778 }
2779 }
2780
2783 cgrp->subtree_control = new_sc; 2781 cgrp->subtree_control = new_sc;
2784 cgrp->child_subsys_mask = new_ss; 2782 cgrp->child_subsys_mask = new_ss;
2785 2783