aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2015-10-15 16:41:53 -0400
committerTejun Heo <tj@kernel.org>2015-10-15 16:41:53 -0400
commitafcf6c8b75444382e0f9996157207ebae34a8848 (patch)
tree6b8b8ccc4a99cfc7e156765c58ab285034980995
parent2e91fa7f6d451e3ea9fec999065d2fd199691f9d (diff)
cgroup: add cgroup_subsys->free() method and use it to fix pids controller
pids controller is completely broken in that it uncharges when a task exits allowing zombies to escape resource control. With the recent updates, cgroup core now maintains cgroup association till task free and pids controller can be fixed by uncharging on free instead of exit. This patch adds cgroup_subsys->free() method and update pids controller to use it instead of ->exit() for uncharging. Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Aleksa Sarai <cyphar@cyphar.com>
-rw-r--r--Documentation/cgroups/cgroups.txt4
-rw-r--r--include/linux/cgroup-defs.h1
-rw-r--r--kernel/cgroup.c7
-rw-r--r--kernel/cgroup_pids.c4
4 files changed, 14 insertions, 2 deletions
diff --git a/Documentation/cgroups/cgroups.txt b/Documentation/cgroups/cgroups.txt
index f935fac1e73b..c6256ae9885b 100644
--- a/Documentation/cgroups/cgroups.txt
+++ b/Documentation/cgroups/cgroups.txt
@@ -637,6 +637,10 @@ void exit(struct task_struct *task)
637 637
638Called during task exit. 638Called during task exit.
639 639
640void free(struct task_struct *task)
641
642Called when the task_struct is freed.
643
640void bind(struct cgroup *root) 644void bind(struct cgroup *root)
641(cgroup_mutex held by caller) 645(cgroup_mutex held by caller)
642 646
diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h
index 6a1ab64ee5f9..60d44b26276d 100644
--- a/include/linux/cgroup-defs.h
+++ b/include/linux/cgroup-defs.h
@@ -436,6 +436,7 @@ struct cgroup_subsys {
436 void (*cancel_fork)(struct task_struct *task, void *priv); 436 void (*cancel_fork)(struct task_struct *task, void *priv);
437 void (*fork)(struct task_struct *task, void *priv); 437 void (*fork)(struct task_struct *task, void *priv);
438 void (*exit)(struct task_struct *task); 438 void (*exit)(struct task_struct *task);
439 void (*free)(struct task_struct *task);
439 void (*bind)(struct cgroup_subsys_state *root_css); 440 void (*bind)(struct cgroup_subsys_state *root_css);
440 441
441 int early_init; 442 int early_init;
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 918658497625..867384369669 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -206,6 +206,7 @@ static u64 css_serial_nr_next = 1;
206 */ 206 */
207static unsigned long have_fork_callback __read_mostly; 207static unsigned long have_fork_callback __read_mostly;
208static unsigned long have_exit_callback __read_mostly; 208static unsigned long have_exit_callback __read_mostly;
209static unsigned long have_free_callback __read_mostly;
209 210
210/* Ditto for the can_fork callback. */ 211/* Ditto for the can_fork callback. */
211static unsigned long have_canfork_callback __read_mostly; 212static unsigned long have_canfork_callback __read_mostly;
@@ -5180,6 +5181,7 @@ static void __init cgroup_init_subsys(struct cgroup_subsys *ss, bool early)
5180 5181
5181 have_fork_callback |= (bool)ss->fork << ss->id; 5182 have_fork_callback |= (bool)ss->fork << ss->id;
5182 have_exit_callback |= (bool)ss->exit << ss->id; 5183 have_exit_callback |= (bool)ss->exit << ss->id;
5184 have_free_callback |= (bool)ss->free << ss->id;
5183 have_canfork_callback |= (bool)ss->can_fork << ss->id; 5185 have_canfork_callback |= (bool)ss->can_fork << ss->id;
5184 5186
5185 /* At system boot, before all subsystems have been 5187 /* At system boot, before all subsystems have been
@@ -5637,6 +5639,11 @@ void cgroup_exit(struct task_struct *tsk)
5637void cgroup_free(struct task_struct *task) 5639void cgroup_free(struct task_struct *task)
5638{ 5640{
5639 struct css_set *cset = task_css_set(task); 5641 struct css_set *cset = task_css_set(task);
5642 struct cgroup_subsys *ss;
5643 int ssid;
5644
5645 for_each_subsys_which(ss, ssid, &have_free_callback)
5646 ss->free(task);
5640 5647
5641 put_css_set(cset); 5648 put_css_set(cset);
5642} 5649}
diff --git a/kernel/cgroup_pids.c b/kernel/cgroup_pids.c
index 45f0856a61fe..cdd8df4e991c 100644
--- a/kernel/cgroup_pids.c
+++ b/kernel/cgroup_pids.c
@@ -266,7 +266,7 @@ static void pids_fork(struct task_struct *task, void *priv)
266 css_put(old_css); 266 css_put(old_css);
267} 267}
268 268
269static void pids_exit(struct task_struct *task) 269static void pids_free(struct task_struct *task)
270{ 270{
271 struct pids_cgroup *pids = css_pids(task_css(task, pids_cgrp_id)); 271 struct pids_cgroup *pids = css_pids(task_css(task, pids_cgrp_id));
272 272
@@ -347,7 +347,7 @@ struct cgroup_subsys pids_cgrp_subsys = {
347 .can_fork = pids_can_fork, 347 .can_fork = pids_can_fork,
348 .cancel_fork = pids_cancel_fork, 348 .cancel_fork = pids_cancel_fork,
349 .fork = pids_fork, 349 .fork = pids_fork,
350 .exit = pids_exit, 350 .free = pids_free,
351 .legacy_cftypes = pids_files, 351 .legacy_cftypes = pids_files,
352 .dfl_cftypes = pids_files, 352 .dfl_cftypes = pids_files,
353}; 353};