diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-07-31 17:03:05 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-07-31 17:03:05 -0400 |
commit | 2e7ca2064cbb070834233ea540ac9c2ff0d09894 (patch) | |
tree | 7ab24df1442f70644b268af279121980f4c03c75 /kernel | |
parent | ff2620f778b1942eea40bd43773094dbc0e76c7e (diff) | |
parent | 3c74541777302eec43a0d1327c4d58b8659a776b (diff) |
Merge branch 'for-4.13-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup
Pull cgroup fixes from Tejun Heo:
"Several cgroup bug fixes.
- cgroup core was calling a migration callback on empty migrations,
which could make cpuset crash.
- There was a very subtle bug where the controller interface files
aren't created directly when cgroup2 is mounted. Because later
operations create them, this bug didn't get noticed earlier.
- Failed writes to cgroup.subtree_control were incorrectly returning
zero"
* 'for-4.13-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup:
cgroup: fix error return value from cgroup_subtree_control()
cgroup: create dfl_root files on subsys registration
cgroup: don't call migration methods if there are no tasks to migrate
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/cgroup/cgroup-internal.h | 3 | ||||
-rw-r--r-- | kernel/cgroup/cgroup.c | 66 |
2 files changed, 40 insertions, 29 deletions
diff --git a/kernel/cgroup/cgroup-internal.h b/kernel/cgroup/cgroup-internal.h index 793565c05742..8b4c3c2f2509 100644 --- a/kernel/cgroup/cgroup-internal.h +++ b/kernel/cgroup/cgroup-internal.h | |||
@@ -33,6 +33,9 @@ struct cgroup_taskset { | |||
33 | struct list_head src_csets; | 33 | struct list_head src_csets; |
34 | struct list_head dst_csets; | 34 | struct list_head dst_csets; |
35 | 35 | ||
36 | /* the number of tasks in the set */ | ||
37 | int nr_tasks; | ||
38 | |||
36 | /* the subsys currently being processed */ | 39 | /* the subsys currently being processed */ |
37 | int ssid; | 40 | int ssid; |
38 | 41 | ||
diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c index 620794a20a33..df2e0f14a95d 100644 --- a/kernel/cgroup/cgroup.c +++ b/kernel/cgroup/cgroup.c | |||
@@ -2006,6 +2006,8 @@ static void cgroup_migrate_add_task(struct task_struct *task, | |||
2006 | if (!cset->mg_src_cgrp) | 2006 | if (!cset->mg_src_cgrp) |
2007 | return; | 2007 | return; |
2008 | 2008 | ||
2009 | mgctx->tset.nr_tasks++; | ||
2010 | |||
2009 | list_move_tail(&task->cg_list, &cset->mg_tasks); | 2011 | list_move_tail(&task->cg_list, &cset->mg_tasks); |
2010 | if (list_empty(&cset->mg_node)) | 2012 | if (list_empty(&cset->mg_node)) |
2011 | list_add_tail(&cset->mg_node, | 2013 | list_add_tail(&cset->mg_node, |
@@ -2094,21 +2096,19 @@ static int cgroup_migrate_execute(struct cgroup_mgctx *mgctx) | |||
2094 | struct css_set *cset, *tmp_cset; | 2096 | struct css_set *cset, *tmp_cset; |
2095 | int ssid, failed_ssid, ret; | 2097 | int ssid, failed_ssid, ret; |
2096 | 2098 | ||
2097 | /* methods shouldn't be called if no task is actually migrating */ | ||
2098 | if (list_empty(&tset->src_csets)) | ||
2099 | return 0; | ||
2100 | |||
2101 | /* check that we can legitimately attach to the cgroup */ | 2099 | /* check that we can legitimately attach to the cgroup */ |
2102 | do_each_subsys_mask(ss, ssid, mgctx->ss_mask) { | 2100 | if (tset->nr_tasks) { |
2103 | if (ss->can_attach) { | 2101 | do_each_subsys_mask(ss, ssid, mgctx->ss_mask) { |
2104 | tset->ssid = ssid; | 2102 | if (ss->can_attach) { |
2105 | ret = ss->can_attach(tset); | 2103 | tset->ssid = ssid; |
2106 | if (ret) { | 2104 | ret = ss->can_attach(tset); |
2107 | failed_ssid = ssid; | 2105 | if (ret) { |
2108 | goto out_cancel_attach; | 2106 | failed_ssid = ssid; |
2107 | goto out_cancel_attach; | ||
2108 | } | ||
2109 | } | 2109 | } |
2110 | } | 2110 | } while_each_subsys_mask(); |
2111 | } while_each_subsys_mask(); | 2111 | } |
2112 | 2112 | ||
2113 | /* | 2113 | /* |
2114 | * Now that we're guaranteed success, proceed to move all tasks to | 2114 | * Now that we're guaranteed success, proceed to move all tasks to |
@@ -2137,25 +2137,29 @@ static int cgroup_migrate_execute(struct cgroup_mgctx *mgctx) | |||
2137 | */ | 2137 | */ |
2138 | tset->csets = &tset->dst_csets; | 2138 | tset->csets = &tset->dst_csets; |
2139 | 2139 | ||
2140 | do_each_subsys_mask(ss, ssid, mgctx->ss_mask) { | 2140 | if (tset->nr_tasks) { |
2141 | if (ss->attach) { | 2141 | do_each_subsys_mask(ss, ssid, mgctx->ss_mask) { |
2142 | tset->ssid = ssid; | 2142 | if (ss->attach) { |
2143 | ss->attach(tset); | 2143 | tset->ssid = ssid; |
2144 | } | 2144 | ss->attach(tset); |
2145 | } while_each_subsys_mask(); | 2145 | } |
2146 | } while_each_subsys_mask(); | ||
2147 | } | ||
2146 | 2148 | ||
2147 | ret = 0; | 2149 | ret = 0; |
2148 | goto out_release_tset; | 2150 | goto out_release_tset; |
2149 | 2151 | ||
2150 | out_cancel_attach: | 2152 | out_cancel_attach: |
2151 | do_each_subsys_mask(ss, ssid, mgctx->ss_mask) { | 2153 | if (tset->nr_tasks) { |
2152 | if (ssid == failed_ssid) | 2154 | do_each_subsys_mask(ss, ssid, mgctx->ss_mask) { |
2153 | break; | 2155 | if (ssid == failed_ssid) |
2154 | if (ss->cancel_attach) { | 2156 | break; |
2155 | tset->ssid = ssid; | 2157 | if (ss->cancel_attach) { |
2156 | ss->cancel_attach(tset); | 2158 | tset->ssid = ssid; |
2157 | } | 2159 | ss->cancel_attach(tset); |
2158 | } while_each_subsys_mask(); | 2160 | } |
2161 | } while_each_subsys_mask(); | ||
2162 | } | ||
2159 | out_release_tset: | 2163 | out_release_tset: |
2160 | spin_lock_irq(&css_set_lock); | 2164 | spin_lock_irq(&css_set_lock); |
2161 | list_splice_init(&tset->dst_csets, &tset->src_csets); | 2165 | list_splice_init(&tset->dst_csets, &tset->src_csets); |
@@ -2997,11 +3001,11 @@ static ssize_t cgroup_subtree_control_write(struct kernfs_open_file *of, | |||
2997 | cgrp->subtree_control &= ~disable; | 3001 | cgrp->subtree_control &= ~disable; |
2998 | 3002 | ||
2999 | ret = cgroup_apply_control(cgrp); | 3003 | ret = cgroup_apply_control(cgrp); |
3000 | |||
3001 | cgroup_finalize_control(cgrp, ret); | 3004 | cgroup_finalize_control(cgrp, ret); |
3005 | if (ret) | ||
3006 | goto out_unlock; | ||
3002 | 3007 | ||
3003 | kernfs_activate(cgrp->kn); | 3008 | kernfs_activate(cgrp->kn); |
3004 | ret = 0; | ||
3005 | out_unlock: | 3009 | out_unlock: |
3006 | cgroup_kn_unlock(of->kn); | 3010 | cgroup_kn_unlock(of->kn); |
3007 | return ret ?: nbytes; | 3011 | return ret ?: nbytes; |
@@ -4669,6 +4673,10 @@ int __init cgroup_init(void) | |||
4669 | 4673 | ||
4670 | if (ss->bind) | 4674 | if (ss->bind) |
4671 | ss->bind(init_css_set.subsys[ssid]); | 4675 | ss->bind(init_css_set.subsys[ssid]); |
4676 | |||
4677 | mutex_lock(&cgroup_mutex); | ||
4678 | css_populate_dir(init_css_set.subsys[ssid]); | ||
4679 | mutex_unlock(&cgroup_mutex); | ||
4672 | } | 4680 | } |
4673 | 4681 | ||
4674 | /* init_css_set.subsys[] has been updated, re-hash */ | 4682 | /* init_css_set.subsys[] has been updated, re-hash */ |