diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2018-10-11 13:24:01 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2018-10-11 13:24:01 -0400 |
commit | 0778a9f2dd924c3af41971ba40eec44793aea531 (patch) | |
tree | 0df1b3fcfd364447046c88efec32668b20857078 | |
parent | e5337178f7023bd06a39c06e1fab88817559c0f3 (diff) | |
parent | 479adb89a97b0a33e5a9d702119872cc82ca21aa (diff) |
Merge branch 'for-4.19-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup
Tejun writes:
"cgroup fixes for v4.19-rc7
One cgroup2 threaded mode fix for v4.19-rc7. While threaded mode
isn't used widely (yet) and the bug requires somewhat convoluted
sequence of operations, it causes a userland visible malfunction -
EINVAL on a valid attempt to enable threaded mode. This pull request
contains the fix"
* 'for-4.19-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup:
cgroup: Fix dom_cgrp propagation when enabling threaded mode
-rw-r--r-- | include/linux/cgroup-defs.h | 1 | ||||
-rw-r--r-- | kernel/cgroup/cgroup.c | 25 |
2 files changed, 17 insertions, 9 deletions
diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h index ff20b677fb9f..22254c1fe1c5 100644 --- a/include/linux/cgroup-defs.h +++ b/include/linux/cgroup-defs.h | |||
@@ -412,6 +412,7 @@ struct cgroup { | |||
412 | * specific task are charged to the dom_cgrp. | 412 | * specific task are charged to the dom_cgrp. |
413 | */ | 413 | */ |
414 | struct cgroup *dom_cgrp; | 414 | struct cgroup *dom_cgrp; |
415 | struct cgroup *old_dom_cgrp; /* used while enabling threaded */ | ||
415 | 416 | ||
416 | /* per-cpu recursive resource statistics */ | 417 | /* per-cpu recursive resource statistics */ |
417 | struct cgroup_rstat_cpu __percpu *rstat_cpu; | 418 | struct cgroup_rstat_cpu __percpu *rstat_cpu; |
diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c index aae10baf1902..4a3dae2a8283 100644 --- a/kernel/cgroup/cgroup.c +++ b/kernel/cgroup/cgroup.c | |||
@@ -2836,11 +2836,12 @@ restart: | |||
2836 | } | 2836 | } |
2837 | 2837 | ||
2838 | /** | 2838 | /** |
2839 | * cgroup_save_control - save control masks of a subtree | 2839 | * cgroup_save_control - save control masks and dom_cgrp of a subtree |
2840 | * @cgrp: root of the target subtree | 2840 | * @cgrp: root of the target subtree |
2841 | * | 2841 | * |
2842 | * Save ->subtree_control and ->subtree_ss_mask to the respective old_ | 2842 | * Save ->subtree_control, ->subtree_ss_mask and ->dom_cgrp to the |
2843 | * prefixed fields for @cgrp's subtree including @cgrp itself. | 2843 | * respective old_ prefixed fields for @cgrp's subtree including @cgrp |
2844 | * itself. | ||
2844 | */ | 2845 | */ |
2845 | static void cgroup_save_control(struct cgroup *cgrp) | 2846 | static void cgroup_save_control(struct cgroup *cgrp) |
2846 | { | 2847 | { |
@@ -2850,6 +2851,7 @@ static void cgroup_save_control(struct cgroup *cgrp) | |||
2850 | cgroup_for_each_live_descendant_pre(dsct, d_css, cgrp) { | 2851 | cgroup_for_each_live_descendant_pre(dsct, d_css, cgrp) { |
2851 | dsct->old_subtree_control = dsct->subtree_control; | 2852 | dsct->old_subtree_control = dsct->subtree_control; |
2852 | dsct->old_subtree_ss_mask = dsct->subtree_ss_mask; | 2853 | dsct->old_subtree_ss_mask = dsct->subtree_ss_mask; |
2854 | dsct->old_dom_cgrp = dsct->dom_cgrp; | ||
2853 | } | 2855 | } |
2854 | } | 2856 | } |
2855 | 2857 | ||
@@ -2875,11 +2877,12 @@ static void cgroup_propagate_control(struct cgroup *cgrp) | |||
2875 | } | 2877 | } |
2876 | 2878 | ||
2877 | /** | 2879 | /** |
2878 | * cgroup_restore_control - restore control masks of a subtree | 2880 | * cgroup_restore_control - restore control masks and dom_cgrp of a subtree |
2879 | * @cgrp: root of the target subtree | 2881 | * @cgrp: root of the target subtree |
2880 | * | 2882 | * |
2881 | * Restore ->subtree_control and ->subtree_ss_mask from the respective old_ | 2883 | * Restore ->subtree_control, ->subtree_ss_mask and ->dom_cgrp from the |
2882 | * prefixed fields for @cgrp's subtree including @cgrp itself. | 2884 | * respective old_ prefixed fields for @cgrp's subtree including @cgrp |
2885 | * itself. | ||
2883 | */ | 2886 | */ |
2884 | static void cgroup_restore_control(struct cgroup *cgrp) | 2887 | static void cgroup_restore_control(struct cgroup *cgrp) |
2885 | { | 2888 | { |
@@ -2889,6 +2892,7 @@ static void cgroup_restore_control(struct cgroup *cgrp) | |||
2889 | cgroup_for_each_live_descendant_post(dsct, d_css, cgrp) { | 2892 | cgroup_for_each_live_descendant_post(dsct, d_css, cgrp) { |
2890 | dsct->subtree_control = dsct->old_subtree_control; | 2893 | dsct->subtree_control = dsct->old_subtree_control; |
2891 | dsct->subtree_ss_mask = dsct->old_subtree_ss_mask; | 2894 | dsct->subtree_ss_mask = dsct->old_subtree_ss_mask; |
2895 | dsct->dom_cgrp = dsct->old_dom_cgrp; | ||
2892 | } | 2896 | } |
2893 | } | 2897 | } |
2894 | 2898 | ||
@@ -3196,6 +3200,8 @@ static int cgroup_enable_threaded(struct cgroup *cgrp) | |||
3196 | { | 3200 | { |
3197 | struct cgroup *parent = cgroup_parent(cgrp); | 3201 | struct cgroup *parent = cgroup_parent(cgrp); |
3198 | struct cgroup *dom_cgrp = parent->dom_cgrp; | 3202 | struct cgroup *dom_cgrp = parent->dom_cgrp; |
3203 | struct cgroup *dsct; | ||
3204 | struct cgroup_subsys_state *d_css; | ||
3199 | int ret; | 3205 | int ret; |
3200 | 3206 | ||
3201 | lockdep_assert_held(&cgroup_mutex); | 3207 | lockdep_assert_held(&cgroup_mutex); |
@@ -3225,12 +3231,13 @@ static int cgroup_enable_threaded(struct cgroup *cgrp) | |||
3225 | */ | 3231 | */ |
3226 | cgroup_save_control(cgrp); | 3232 | cgroup_save_control(cgrp); |
3227 | 3233 | ||
3228 | cgrp->dom_cgrp = dom_cgrp; | 3234 | cgroup_for_each_live_descendant_pre(dsct, d_css, cgrp) |
3235 | if (dsct == cgrp || cgroup_is_threaded(dsct)) | ||
3236 | dsct->dom_cgrp = dom_cgrp; | ||
3237 | |||
3229 | ret = cgroup_apply_control(cgrp); | 3238 | ret = cgroup_apply_control(cgrp); |
3230 | if (!ret) | 3239 | if (!ret) |
3231 | parent->nr_threaded_children++; | 3240 | parent->nr_threaded_children++; |
3232 | else | ||
3233 | cgrp->dom_cgrp = cgrp; | ||
3234 | 3241 | ||
3235 | cgroup_finalize_control(cgrp, ret); | 3242 | cgroup_finalize_control(cgrp, ret); |
3236 | return ret; | 3243 | return ret; |