diff options
| -rw-r--r-- | kernel/cgroup.c | 58 |
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 | ||
