Patch "thermal: cpu_cooling: don't call kcalloc() under rcu_read_lock" has been added to the 4.2-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
thermal: cpu_cooling: don't call kcalloc() under rcu_read_lock
to the 4.2-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
thermal-cpu_cooling-don-t-call-kcalloc-under-rcu_read_lock.patch
and it can be found in the queue-4.2 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
459ac37506d195713b5e82271a2ac44a777e47dfMon Sep 17 00:00:00 2001
From: Javi Merino <[email protected]>
Date: Mon, 17 Aug 2015 19:21:42 +0100
Subject: thermal: cpu_cooling: don't call kcalloc() under rcu_read_lock
From: Javi Merino <[email protected]>
commit 459ac37506d195713b5e82271a2ac44a777e47df upstream.
build_dyn_power_table() allocates the power table while holding rcu_read_lock. kcalloc using GFP_KERNEL may sleep, so it can't be called in an RCU read-side path.
Move the rcu protection to the part of the function that really needs
it: the part that handles the dev_pm_opp pointer received from dev_pm_opp_find_freq_ceil(). In the unlikely case that there is an OPP added to the cpu while this function is running, return -EAGAIN.
--- drivers/thermal/cpu_cooling.c | 47 ++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 24 deletions(-)
drivers/thermal/cpu_cooling.c +23 -24
@@ -262,7 +262,9 @@ static int cpufreq_thermal_notifier(stru* efficiently. Power is stored in mW, frequency in KHz. The * resulting table is in ascending order. * -* Return: 0 on success, -E* on error. +* Return: 0 on success, -EINVAL if there are no OPPs for any CPUs, +* -ENOMEM if we run out of memory or -EAGAIN if an OPP was +* added/enabled while the function was executing. */ static int build_dyn_power_table (struct cpufreq_cooling_device *cpufreq_device,u32 capacitance)
@@ -270,11 +272,9 @@ static int build_dyn_power_table(structstruct power_table *power_table;struct dev_pm_opp *opp;struct device *dev =NULL ; -int num_opps =0 , cpu, i, ret =0 ; +int num_opps =0 , cpu, i;unsigned long freq; -rcu_read_lock (); -for_each_cpu (cpu, &cpufreq_device->allowed_cpus) { dev =get_cpu_device (cpu);if (!dev) {
@@ -284,24 +284,20 @@ static int build_dyn_power_table(struct } num_opps =dev_pm_opp_get_opp_count (dev); -if (num_opps >0 ) { +if (num_opps >0 )break ; - }else if (num_opps <0 ) { - ret = num_opps; - goto unlock; - } +else if (num_opps <0 ) +return num_opps; } -if (num_opps ==0 ) { - ret = -EINVAL ; - goto unlock; - } +if (num_opps ==0 ) +return -EINVAL ; power_table =kcalloc (num_opps,sizeof (*power_table),GFP_KERNEL ); -if (!power_table) { - ret = -ENOMEM ; - goto unlock; - } +if (!power_table) +return -ENOMEM ; + +rcu_read_lock (); for (freq = 0, i = 0; opp = dev_pm_opp_find_freq_ceil(dev, &freq), !IS_ERR(opp);
@@ -309,6 +305,11 @@ static int build_dyn_power_table(structu32 freq_mhz, voltage_mv;u64 power; +if (i >= num_opps) { +rcu_read_unlock (); +return -EAGAIN ; + } + freq_mhz = freq /1000000 ; voltage_mv =dev_pm_opp_get_voltage (opp) /1000 ;
@@ -326,18 +327,16 @@ static int build_dyn_power_table(struct power_table[i].power = power; } -if (i ==0 ) { - ret =PTR_ERR (opp); - goto unlock; - } +rcu_read_unlock (); + +if (i != num_opps) +return PTR_ERR (opp); cpufreq_device->cpu_dev = dev; cpufreq_device->dyn_power_table = power_table; cpufreq_device->dyn_power_table_entries = i; -unlock: -rcu_read_unlock (); -return ret; +return 0 ; } static u32 cpu_freq_to_power(struct cpufreq_cooling_device *cpufreq_device,
Patches currently in stable-queue which might be from [email protected] are
queue-4.2/thermal-cpu_cooling-don-t-call-kcalloc-under-rcu_read_lock.patch queue-4.2/thermal-cpu_cooling-free-power-table-on-error-or-when-unregistering.patch