History

cgroup: Prevent double killing of css when enabling threaded cgroup

The test_cgcore_no_internal_process_constraint_on_threads selftest when running with subsystem controlling noise triggers two warnings: > [ 597.443115] WARNING: CPU: 1 PID: 28167 at kernel/cgroup/cgroup.c:3131 cgroup_apply_control_enable+0xe0/0x3f0 > [ 597.443413] WARNING: CPU: 1 PID: 28167 at kernel/cgroup/cgroup.c:3177 cgroup_apply_control_disable+0xa6/0x160 Both stem from a call to cgroup_type_write. The first warning was also triggered by syzkaller. When we're switching cgroup to threaded mode shortly after a subsystem was disabled on it, we can see the respective subsystem css dying there. The warning in cgroup_apply_control_enable is harmless in this case since we're not adding new subsys anyway. The warning in cgroup_apply_control_disable indicates an attempt to kill css of recently disabled subsystem repeatedly. The commit prevents these situations by making cgroup_type_write wait for all dying csses to go away before re-applying subtree controls. When at it, the locations of WARN_ON_ONCE calls are moved so that warning is triggered only when we are about to misuse the dying css.

Michal Koutný committed 6 years ago

Commit 3bc0bb31 parent 75ea91c1 file · +6 −5Browse files

Unified · Split

kernel/cgroup/cgroup.c+6−5
@@ -3055,8 +3055,6 @@ static int cgroup_apply_control_enable(struct cgroup *cgrp) · 3054 unmodified lines
30553055 for_each_subsys(ss, ssid) {
30563056 struct cgroup_subsys_state *css = cgroup_css(dsct, ss);
30573057
3058− WARN_ON_ONCE(css && percpu_ref_is_dying(&css->refcnt));
3059−
30603058 if (!(cgroup_ss_mask(dsct) & (1 << ss->id)))
30613059 continue;
30623060
@@ -3066,6 +3064,8 @@ static int cgroup_apply_control_enable(struct cgroup *cgrp) · 3 unmodified lines
30663064 return PTR_ERR(css);
30673065 }
30683066
3067+ WARN_ON_ONCE(percpu_ref_is_dying(&css->refcnt));
3068+
30693069 if (css_visible(css)) {
30703070 ret = css_populate_dir(css);
30713071 if (ret)
@@ -3101,11 +3101,11 @@ static void cgroup_apply_control_disable(struct cgroup *cgrp) · 29 unmodified lines
31013101 for_each_subsys(ss, ssid) {
31023102 struct cgroup_subsys_state *css = cgroup_css(dsct, ss);
31033103
3104− WARN_ON_ONCE(css && percpu_ref_is_dying(&css->refcnt));
3105−
31063104 if (!css)
31073105 continue;
31083106
3107+ WARN_ON_ONCE(percpu_ref_is_dying(&css->refcnt));
3108+
31093109 if (css->parent &&
31103110 !(cgroup_ss_mask(dsct) & (1 << ss->id))) {
31113111 kill_css(css);
@@ -3392,7 +3392,8 @@ static ssize_t cgroup_type_write(struct kernfs_open_file *of, char *buf, · 280 unmodified lines
33923392 if (strcmp(strstrip(buf), "threaded"))
33933393 return -EINVAL;
33943394
3395− cgrp = cgroup_kn_lock_live(of->kn, false);
3395+ /* drain dying csses before we re-apply (threaded) subtree control */
3396+ cgrp = cgroup_kn_lock_live(of->kn, true);
33963397 if (!cgrp)
33973398 return -ENOENT;
33983399

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t