From b9b63b0c622a0a1fb4ad6475908910a45b6520b2 Mon Sep 17 00:00:00 2001 From: Syed Rameez Mustafa Date: Thu, 3 Nov 2016 18:13:08 -0700 Subject: [PATCH] sched/hmp: Fix memory leak when task fork fails The scheduler allocates memory for the task load structures during fork. It then relies to sched_exit() to be called to free that memory. However, if the fork itself fails at any point after the allocation, the memory is left unclaimed forever. Fix this memory leak by freeing the allocated memory under error conditions. Change-Id: I14a8290c9fcc4174ec80560e9f9d7bcdb119761f Signed-off-by: Syed Rameez Mustafa --- include/linux/sched.h | 3 +++ kernel/fork.c | 1 + kernel/sched/sched.h | 3 --- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index b1351226b102..f8aa9992a694 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -2393,6 +2393,7 @@ struct cpu_cycle_counter_cb { }; #ifdef CONFIG_SCHED_HMP +extern void free_task_load_ptrs(struct task_struct *p); extern int sched_set_window(u64 window_start, unsigned int window_size); extern unsigned long sched_get_busy(int cpu); extern void sched_get_cpus_busy(struct sched_load *busy, @@ -2418,6 +2419,8 @@ extern int sched_set_group_id(struct task_struct *p, unsigned int group_id); extern unsigned int sched_get_group_id(struct task_struct *p); #else /* CONFIG_SCHED_HMP */ +static inline void free_task_load_ptrs(struct task_struct *p) { } + static inline u64 sched_ktime_clock(void) { return 0; diff --git a/kernel/fork.c b/kernel/fork.c index 8a5962276788..a46ce4505066 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1654,6 +1654,7 @@ bad_fork_cleanup_audit: bad_fork_cleanup_perf: perf_event_free_task(p); bad_fork_cleanup_policy: + free_task_load_ptrs(p); #ifdef CONFIG_NUMA mpol_put(p->mempolicy); bad_fork_cleanup_threadgroup_lock: diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index de29c926379b..4289bf6cd642 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -1079,7 +1079,6 @@ extern unsigned int __read_mostly sched_downmigrate; extern unsigned int __read_mostly sysctl_sched_spill_nr_run; extern unsigned int __read_mostly sched_load_granule; -extern void free_task_load_ptrs(struct task_struct *p); extern void init_new_task_load(struct task_struct *p, bool idle_task); extern u64 sched_ktime_clock(void); extern int got_boost_kick(void); @@ -1528,8 +1527,6 @@ static inline struct sched_cluster *rq_cluster(struct rq *rq) return NULL; } -static inline void free_task_load_ptrs(struct task_struct *p) { } - static inline void init_new_task_load(struct task_struct *p, bool idle_task) { }