[PATCH 8/8] cpufreq: Nest down_write/read(cpufreq_rwsem) within get_online_cpus()/put_online_cpus()

!MAILaRCHIVE_VOTE_RePLACE
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]
To: <linux-kernel@...>, Zdenek Kabelac <zdenek.kabelac@...>, Peter Zijlstra <a.p.zijlstra@...>, Oleg Nesterov <oleg@...>, Heiko Carstens <heiko.carstens@...>, Rafael J. Wysocki <rjw@...>
Cc: Andrew Morton <akpm@...>, Ingo Molnar <mingo@...>, Srivatsa Vaddagiri <vatsa@...>
Date: Tuesday, April 29, 2008 - 9:05 am

cpufreq: Nest down_write/read(cpufreq_rwsem) with get_online_cpus()

From: Gautham R Shenoy <ego@in.ibm.com>

On the CPU-Hotplug callback path, the cpufreq_rwsem has a dependency
with the cpu_hotplug lock. However on the read-path, this dependency is not
honoured resulting in a possible deadlock when one tries to change
the cpufreq governor when a CPU-Hotplug is in progress.

This patch nests the down_write/read(cpufreq_rwsem) with
get_online_cpus()/put_online_cpus() pair.

Also, it introduces a try_get_online_cpus() in the do_dbs_timer() work-item
code, since we cannot do get_online_cpus() from within work items.

Signed-off-by: Gautham R Shenoy <ego@in.ibm.com>
---

 drivers/cpufreq/cpufreq.c          |   11 +++++++++--
 drivers/cpufreq/cpufreq_ondemand.c |    9 +++++++--
 2 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 35a26a3..087f8fc 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -71,11 +71,12 @@ int lock_policy_rwsem_##mode						\
 {									\
 	int policy_cpu = per_cpu(policy_cpu, cpu);			\
 	BUG_ON(policy_cpu == -1);					\
-	down_##mode(&per_cpu(cpu_policy_rwsem, policy_cpu));		\
+	get_online_cpus();						\
 	if (unlikely(!cpu_online(cpu))) {				\
-		up_##mode(&per_cpu(cpu_policy_rwsem, policy_cpu));	\
+		put_online_cpus();					\
 		return -1;						\
 	}								\
+	down_##mode(&per_cpu(cpu_policy_rwsem, policy_cpu));		\
 									\
 	return 0;							\
 }
@@ -91,6 +92,7 @@ void unlock_policy_rwsem_read(int cpu)
 	int policy_cpu = per_cpu(policy_cpu, cpu);
 	BUG_ON(policy_cpu == -1);
 	up_read(&per_cpu(cpu_policy_rwsem, policy_cpu));
+	put_online_cpus();
 }
 EXPORT_SYMBOL_GPL(unlock_policy_rwsem_read);
 
@@ -99,6 +101,7 @@ void unlock_policy_rwsem_write(int cpu)
 	int policy_cpu = per_cpu(policy_cpu, cpu);
 	BUG_ON(policy_cpu == -1);
 	up_write(&per_cpu(cpu_policy_rwsem, policy_cpu));
+	put_online_cpus();
 }
 EXPORT_SYMBOL_GPL(unlock_policy_rwsem_write);
 
@@ -1818,7 +1821,9 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
 	cpufreq_driver = driver_data;
 	spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
 
+	get_online_cpus();
 	ret = sysdev_driver_register(&cpu_sysdev_class,&cpufreq_sysdev_driver);
+	put_online_cpus();
 
 	if ((!ret) && !(cpufreq_driver->flags & CPUFREQ_STICKY)) {
 		int i;
@@ -1833,8 +1838,10 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
 		if (ret) {
 			dprintk("no CPU initialized for driver %s\n",
 							driver_data->name);
+			get_online_cpus();
 			sysdev_driver_unregister(&cpu_sysdev_class,
 						&cpufreq_sysdev_driver);
+			put_online_cpus();
 
 			spin_lock_irqsave(&cpufreq_driver_lock, flags);
 			cpufreq_driver = NULL;
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index d2af20d..9428f7e 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -446,12 +446,15 @@ static void do_dbs_timer(struct work_struct *work)
 
 	delay -= jiffies % delay;
 
-	if (lock_policy_rwsem_write(cpu) < 0)
+	if (!try_get_online_cpus())
 		return;
 
+	if (lock_policy_rwsem_write(cpu) < 0)
+		goto out;
+
 	if (!dbs_info->enable) {
 		unlock_policy_rwsem_write(cpu);
-		return;
+		goto out;
 	}
 
 	/* Common NORMAL_SAMPLE setup */
@@ -471,6 +474,8 @@ static void do_dbs_timer(struct work_struct *work)
 	}
 	queue_delayed_work_on(cpu, kondemand_wq, &dbs_info->work, delay);
 	unlock_policy_rwsem_write(cpu);
+out:
+	put_online_cpus();
 }
 
 static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info)
-- 
Thanks and Regards
gautham
--
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]

Messages in current thread:
[PATCH 8/8] cpufreq: Nest down_write/read(cpufreq_rwsem) wit..., Gautham R Shenoy, (Tue Apr 29, 9:05 am)
[PATCH 7/8] cpu_hotplug: Introduce try_get_online_cpus(), Gautham R Shenoy, (Tue Apr 29, 9:03 am)
[PATCH 6/8] lockdep: annotate cpu_hotplug, Gautham R Shenoy, (Tue Apr 29, 9:02 am)
[PATCH 5/8] cpu: cpu-hotplug deadlock, Gautham R Shenoy, (Tue Apr 29, 9:02 am)
Re: [PATCH 5/8] cpu: cpu-hotplug deadlock, Oleg Nesterov, (Tue Apr 29, 10:33 am)
Re: [PATCH 5/8] cpu: cpu-hotplug deadlock, Gautham R Shenoy, (Wed Apr 30, 1:37 am)
Re: [PATCH 5/8] cpu: cpu-hotplug deadlock, Oleg Nesterov, (Wed Apr 30, 7:43 am)
Re: [PATCH 5/8] cpu: cpu-hotplug deadlock, Peter Zijlstra, (Tue Apr 29, 11:09 am)
Re: [PATCH 5/8] cpu: cpu-hotplug deadlock, Oleg Nesterov, (Tue Apr 29, 12:45 pm)
Re: [PATCH 5/8] cpu: cpu-hotplug deadlock, Peter Zijlstra, (Tue Apr 29, 1:31 pm)
[PATCH 4/8] net: af_netlink: deadlock, Gautham R Shenoy, (Tue Apr 29, 9:01 am)
Re: Hans Reiser, reiserfs developer, linux-os (Dick Johnson), (Tue Apr 29, 9:19 am)
[PATCH 3/8] lockdep: fix fib_hash softirq inversion, Gautham R Shenoy, (Tue Apr 29, 9:00 am)
Re: [PATCH 3/8] lockdep: fix fib_hash softirq inversion, Peter Zijlstra, (Tue Apr 29, 10:45 am)
[PATCH 2/8] lockdep: reader-in-writer recursion, Gautham R Shenoy, (Tue Apr 29, 8:58 am)
[PATCH 1/8] lockdep: fix recursive read lock validation, Gautham R Shenoy, (Tue Apr 29, 8:57 am)
Re: [PATCH 1/8] lockdep: fix recursive read lock validation, Bart Van Assche, (Tue Apr 29, 9:16 am)
Re: [PATCH 1/8] lockdep: fix recursive read lock validation, Peter Zijlstra, (Tue Apr 29, 10:57 am)
Re: [PATCH 1/8] lockdep: fix recursive read lock validation, Bart Van Assche, (Tue Apr 29, 11:03 am)
Re: [PATCH 1/8] lockdep: fix recursive read lock validation, Peter Zijlstra, (Tue Apr 29, 11:15 am)
Re: [PATCH 1/8] lockdep: fix recursive read lock validation, Bart Van Assche, (Tue Apr 29, 12:03 pm)
Re: [PATCH 1/8] lockdep: fix recursive read lock validation, Peter Zijlstra, (Tue Apr 29, 12:15 pm)
Re: [PATCH 1/8] lockdep: fix recursive read lock validation, Bart Van Assche, (Tue Apr 29, 12:29 pm)
Re: [PATCH 1/8] lockdep: fix recursive read lock validation, Bart Van Assche, (Tue Apr 29, 1:45 pm)