diff options
author | Oleg Nesterov <oleg@redhat.com> | 2019-01-28 17:00:13 +0100 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2019-01-31 15:55:57 +0100 |
commit | 51bee5abeab2058ea5813c5615d6197a23dbf041 (patch) | |
tree | 5747f7ee7faf9589d1cf49ca690e598b222cef92 /block | |
parent | fs/dcache: Track & report number of negative dentries (diff) | |
download | linux-51bee5abeab2058ea5813c5615d6197a23dbf041.tar.xz linux-51bee5abeab2058ea5813c5615d6197a23dbf041.zip |
cgroup/pids: turn cgroup_subsys->free() into cgroup_subsys->release() to fix the accounting
The only user of cgroup_subsys->free() callback is pids_cgrp_subsys which
needs pids_free() to uncharge the pid.
However, ->free() is called from __put_task_struct()->cgroup_free() and this
is too late. Even the trivial program which does
for (;;) {
int pid = fork();
assert(pid >= 0);
if (pid)
wait(NULL);
else
exit(0);
}
can run out of limits because release_task()->call_rcu(delayed_put_task_struct)
implies an RCU gp after the task/pid goes away and before the final put().
Test-case:
mkdir -p /tmp/CG
mount -t cgroup2 none /tmp/CG
echo '+pids' > /tmp/CG/cgroup.subtree_control
mkdir /tmp/CG/PID
echo 2 > /tmp/CG/PID/pids.max
perl -e 'while ($p = fork) { wait; } $p // die "fork failed: $!\n"' &
echo $! > /tmp/CG/PID/cgroup.procs
Without this patch the forking process fails soon after migration.
Rename cgroup_subsys->free() to cgroup_subsys->release() and move the callsite
into the new helper, cgroup_release(), called by release_task() which actually
frees the pid(s).
Reported-by: Herton R. Krzesinski <hkrzesin@redhat.com>
Reported-by: Jan Stancek <jstancek@redhat.com>
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'block')
0 files changed, 0 insertions, 0 deletions