netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 50/51] net/core/flow.c: Fix CPU hotplug callback registration
       [not found] <20140205220251.19080.92336.stgit@srivatsabhat.in.ibm.com>
@ 2014-02-05 22:13 ` Srivatsa S. Bhat
  2014-02-07  4:39   ` David Miller
  2014-02-05 22:13 ` [PATCH 51/51] net/iucv/iucv.c: " Srivatsa S. Bhat
  1 sibling, 1 reply; 6+ messages in thread
From: Srivatsa S. Bhat @ 2014-02-05 22:13 UTC (permalink / raw)
  To: paulus, oleg, rusty, peterz, tglx, akpm
  Cc: mingo, paulmck, tj, walken, ego, linux, linux-kernel,
	srivatsa.bhat, David S. Miller, Li RongQing, Sasha Levin,
	Andrew Morton, Chris Metcalf, netdev, Srivatsa S. Bhat

Subsystems that want to register CPU hotplug callbacks, as well as perform
initialization for the CPUs that are already online, often do it as shown
below:

	get_online_cpus();

	for_each_online_cpu(cpu)
		init_cpu(cpu);

	register_cpu_notifier(&foobar_cpu_notifier);

	put_online_cpus();

This is wrong, since it is prone to ABBA deadlocks involving the
cpu_add_remove_lock and the cpu_hotplug.lock (when running concurrently
with CPU hotplug operations).

Instead, the correct and race-free way of performing the callback
registration is:

	cpu_maps_update_begin();

	for_each_online_cpu(cpu)
		init_cpu(cpu);

	/* Note the use of the double underscored version of the API */
	__register_cpu_notifier(&foobar_cpu_notifier);

	cpu_maps_update_done();


Fix the code in net/core/flow.c by using this latter form of callback
registration.

Cc: "David S. Miller" <davem@davemloft.net>
Cc: Li RongQing <roy.qing.li@gmail.com>
Cc: Sasha Levin <sasha.levin@oracle.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Chris Metcalf <cmetcalf@tilera.com>
Cc: netdev@vger.kernel.org
Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
---

 net/core/flow.c |    8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/net/core/flow.c b/net/core/flow.c
index dfa602c..0f2c995 100644
--- a/net/core/flow.c
+++ b/net/core/flow.c
@@ -456,6 +456,8 @@ static int __init flow_cache_init(struct flow_cache *fc)
 	if (!fc->percpu)
 		return -ENOMEM;
 
+	cpu_maps_update_begin();
+
 	for_each_online_cpu(i) {
 		if (flow_cache_cpu_prepare(fc, i))
 			goto err;
@@ -463,7 +465,9 @@ static int __init flow_cache_init(struct flow_cache *fc)
 	fc->hotcpu_notifier = (struct notifier_block){
 		.notifier_call = flow_cache_cpu,
 	};
-	register_hotcpu_notifier(&fc->hotcpu_notifier);
+	__register_hotcpu_notifier(&fc->hotcpu_notifier);
+
+	cpu_maps_update_done();
 
 	setup_timer(&fc->rnd_timer, flow_cache_new_hashrnd,
 		    (unsigned long) fc);
@@ -479,6 +483,8 @@ err:
 		fcp->hash_table = NULL;
 	}
 
+	cpu_maps_update_done();
+
 	free_percpu(fc->percpu);
 	fc->percpu = NULL;
 

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 51/51] net/iucv/iucv.c: Fix CPU hotplug callback registration
       [not found] <20140205220251.19080.92336.stgit@srivatsabhat.in.ibm.com>
  2014-02-05 22:13 ` [PATCH 50/51] net/core/flow.c: Fix CPU hotplug callback registration Srivatsa S. Bhat
@ 2014-02-05 22:13 ` Srivatsa S. Bhat
  2014-02-07  4:39   ` David Miller
  1 sibling, 1 reply; 6+ messages in thread
From: Srivatsa S. Bhat @ 2014-02-05 22:13 UTC (permalink / raw)
  To: paulus, oleg, rusty, peterz, tglx, akpm
  Cc: mingo, paulmck, tj, walken, ego, linux, linux-kernel,
	srivatsa.bhat, Ursula Braun, David S. Miller, linux-s390, netdev,
	Srivatsa S. Bhat

Subsystems that want to register CPU hotplug callbacks, as well as perform
initialization for the CPUs that are already online, often do it as shown
below:

	get_online_cpus();

	for_each_online_cpu(cpu)
		init_cpu(cpu);

	register_cpu_notifier(&foobar_cpu_notifier);

	put_online_cpus();

This is wrong, since it is prone to ABBA deadlocks involving the
cpu_add_remove_lock and the cpu_hotplug.lock (when running concurrently
with CPU hotplug operations).

Instead, the correct and race-free way of performing the callback
registration is:

	cpu_maps_update_begin();

	for_each_online_cpu(cpu)
		init_cpu(cpu);

	/* Note the use of the double underscored version of the API */
	__register_cpu_notifier(&foobar_cpu_notifier);

	cpu_maps_update_done();


Fix the code in net/iucv/iucv.c by using this latter form of callback
registration. Also, provide helper functions to perform the common memory
allocations and frees, to condense repetitive code.

Cc: Ursula Braun <ursula.braun@de.ibm.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: linux-s390@vger.kernel.org
Cc: netdev@vger.kernel.org
Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
---

 net/iucv/iucv.c |  121 ++++++++++++++++++++++++++-----------------------------
 1 file changed, 57 insertions(+), 64 deletions(-)

diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c
index cd5b8ec..f92348b 100644
--- a/net/iucv/iucv.c
+++ b/net/iucv/iucv.c
@@ -621,6 +621,42 @@ static void iucv_disable(void)
 	put_online_cpus();
 }
 
+static void free_iucv_data(int cpu)
+{
+	kfree(iucv_param_irq[cpu]);
+	iucv_param_irq[cpu] = NULL;
+	kfree(iucv_param[cpu]);
+	iucv_param[cpu] = NULL;
+	kfree(iucv_irq_data[cpu]);
+	iucv_irq_data[cpu] = NULL;
+}
+
+static int alloc_iucv_data(int cpu)
+{
+	/* Note: GFP_DMA used to get memory below 2G */
+	iucv_irq_data[cpu] = kmalloc_node(sizeof(struct iucv_irq_data),
+			     GFP_KERNEL|GFP_DMA, cpu_to_node(cpu));
+	if (!iucv_irq_data[cpu])
+		goto out_free;
+
+	/* Allocate parameter blocks. */
+	iucv_param[cpu] = kmalloc_node(sizeof(union iucv_param),
+			  GFP_KERNEL|GFP_DMA, cpu_to_node(cpu));
+	if (!iucv_param[cpu])
+		goto out_free;
+
+	iucv_param_irq[cpu] = kmalloc_node(sizeof(union iucv_param),
+			  GFP_KERNEL|GFP_DMA, cpu_to_node(cpu));
+	if (!iucv_param_irq[cpu])
+		goto out_free;
+
+	return 0;
+
+out_free:
+	free_iucv_data(cpu);
+	return -ENOMEM;
+}
+
 static int iucv_cpu_notify(struct notifier_block *self,
 				     unsigned long action, void *hcpu)
 {
@@ -630,38 +666,14 @@ static int iucv_cpu_notify(struct notifier_block *self,
 	switch (action) {
 	case CPU_UP_PREPARE:
 	case CPU_UP_PREPARE_FROZEN:
-		iucv_irq_data[cpu] = kmalloc_node(sizeof(struct iucv_irq_data),
-					GFP_KERNEL|GFP_DMA, cpu_to_node(cpu));
-		if (!iucv_irq_data[cpu])
-			return notifier_from_errno(-ENOMEM);
-
-		iucv_param[cpu] = kmalloc_node(sizeof(union iucv_param),
-				     GFP_KERNEL|GFP_DMA, cpu_to_node(cpu));
-		if (!iucv_param[cpu]) {
-			kfree(iucv_irq_data[cpu]);
-			iucv_irq_data[cpu] = NULL;
+		if (alloc_iucv_data(cpu))
 			return notifier_from_errno(-ENOMEM);
-		}
-		iucv_param_irq[cpu] = kmalloc_node(sizeof(union iucv_param),
-					GFP_KERNEL|GFP_DMA, cpu_to_node(cpu));
-		if (!iucv_param_irq[cpu]) {
-			kfree(iucv_param[cpu]);
-			iucv_param[cpu] = NULL;
-			kfree(iucv_irq_data[cpu]);
-			iucv_irq_data[cpu] = NULL;
-			return notifier_from_errno(-ENOMEM);
-		}
 		break;
 	case CPU_UP_CANCELED:
 	case CPU_UP_CANCELED_FROZEN:
 	case CPU_DEAD:
 	case CPU_DEAD_FROZEN:
-		kfree(iucv_param_irq[cpu]);
-		iucv_param_irq[cpu] = NULL;
-		kfree(iucv_param[cpu]);
-		iucv_param[cpu] = NULL;
-		kfree(iucv_irq_data[cpu]);
-		iucv_irq_data[cpu] = NULL;
+		free_iucv_data(cpu);
 		break;
 	case CPU_ONLINE:
 	case CPU_ONLINE_FROZEN:
@@ -2025,33 +2037,20 @@ static int __init iucv_init(void)
 		goto out_int;
 	}
 
-	for_each_online_cpu(cpu) {
-		/* Note: GFP_DMA used to get memory below 2G */
-		iucv_irq_data[cpu] = kmalloc_node(sizeof(struct iucv_irq_data),
-				     GFP_KERNEL|GFP_DMA, cpu_to_node(cpu));
-		if (!iucv_irq_data[cpu]) {
-			rc = -ENOMEM;
-			goto out_free;
-		}
+	cpu_maps_update_begin();
 
-		/* Allocate parameter blocks. */
-		iucv_param[cpu] = kmalloc_node(sizeof(union iucv_param),
-				  GFP_KERNEL|GFP_DMA, cpu_to_node(cpu));
-		if (!iucv_param[cpu]) {
-			rc = -ENOMEM;
-			goto out_free;
-		}
-		iucv_param_irq[cpu] = kmalloc_node(sizeof(union iucv_param),
-				  GFP_KERNEL|GFP_DMA, cpu_to_node(cpu));
-		if (!iucv_param_irq[cpu]) {
+	for_each_online_cpu(cpu) {
+		if (alloc_iucv_data(cpu)) {
 			rc = -ENOMEM;
 			goto out_free;
 		}
-
 	}
-	rc = register_hotcpu_notifier(&iucv_cpu_notifier);
+	rc = __register_hotcpu_notifier(&iucv_cpu_notifier);
 	if (rc)
 		goto out_free;
+
+	cpu_maps_update_done();
+
 	rc = register_reboot_notifier(&iucv_reboot_notifier);
 	if (rc)
 		goto out_cpu;
@@ -2069,16 +2068,14 @@ static int __init iucv_init(void)
 out_reboot:
 	unregister_reboot_notifier(&iucv_reboot_notifier);
 out_cpu:
-	unregister_hotcpu_notifier(&iucv_cpu_notifier);
+	cpu_maps_update_begin();
+	__unregister_hotcpu_notifier(&iucv_cpu_notifier);
 out_free:
-	for_each_possible_cpu(cpu) {
-		kfree(iucv_param_irq[cpu]);
-		iucv_param_irq[cpu] = NULL;
-		kfree(iucv_param[cpu]);
-		iucv_param[cpu] = NULL;
-		kfree(iucv_irq_data[cpu]);
-		iucv_irq_data[cpu] = NULL;
-	}
+	for_each_possible_cpu(cpu)
+		free_iucv_data(cpu);
+
+	cpu_maps_update_done();
+
 	root_device_unregister(iucv_root);
 out_int:
 	unregister_external_interrupt(0x4000, iucv_external_interrupt);
@@ -2105,15 +2102,11 @@ static void __exit iucv_exit(void)
 		kfree(p);
 	spin_unlock_irq(&iucv_queue_lock);
 	unregister_reboot_notifier(&iucv_reboot_notifier);
-	unregister_hotcpu_notifier(&iucv_cpu_notifier);
-	for_each_possible_cpu(cpu) {
-		kfree(iucv_param_irq[cpu]);
-		iucv_param_irq[cpu] = NULL;
-		kfree(iucv_param[cpu]);
-		iucv_param[cpu] = NULL;
-		kfree(iucv_irq_data[cpu]);
-		iucv_irq_data[cpu] = NULL;
-	}
+	cpu_maps_update_begin();
+	__unregister_hotcpu_notifier(&iucv_cpu_notifier);
+	for_each_possible_cpu(cpu)
+		free_iucv_data(cpu);
+	cpu_maps_update_done();
 	root_device_unregister(iucv_root);
 	bus_unregister(&iucv_bus);
 	unregister_external_interrupt(0x4000, iucv_external_interrupt);

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 50/51] net/core/flow.c: Fix CPU hotplug callback registration
  2014-02-05 22:13 ` [PATCH 50/51] net/core/flow.c: Fix CPU hotplug callback registration Srivatsa S. Bhat
@ 2014-02-07  4:39   ` David Miller
  2014-02-07  5:19     ` David Miller
  0 siblings, 1 reply; 6+ messages in thread
From: David Miller @ 2014-02-07  4:39 UTC (permalink / raw)
  To: srivatsa.bhat
  Cc: paulus, oleg, rusty, peterz, tglx, akpm, mingo, paulmck, tj,
	walken, ego, linux, linux-kernel, roy.qing.li, sasha.levin,
	cmetcalf, netdev

From: "Srivatsa S. Bhat" <srivatsa.bhat@linux.vnet.ibm.com>
Date: Thu, 06 Feb 2014 03:43:46 +0530

> Subsystems that want to register CPU hotplug callbacks, as well as perform
> initialization for the CPUs that are already online, often do it as shown
> below:
 ...
> This is wrong, since it is prone to ABBA deadlocks involving the
> cpu_add_remove_lock and the cpu_hotplug.lock (when running concurrently
> with CPU hotplug operations).
> 
> Instead, the correct and race-free way of performing the callback
> registration is:
 ...
> Fix the code in net/core/flow.c by using this latter form of callback
> registration.
> 
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: Li RongQing <roy.qing.li@gmail.com>
> Cc: Sasha Levin <sasha.levin@oracle.com>
> Cc: Andrew Morton <akpm@linux-foundation.org>
> Cc: Chris Metcalf <cmetcalf@tilera.com>
> Cc: netdev@vger.kernel.org
> Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>

Applied.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 51/51] net/iucv/iucv.c: Fix CPU hotplug callback registration
  2014-02-05 22:13 ` [PATCH 51/51] net/iucv/iucv.c: " Srivatsa S. Bhat
@ 2014-02-07  4:39   ` David Miller
  2014-02-07  5:19     ` David Miller
  0 siblings, 1 reply; 6+ messages in thread
From: David Miller @ 2014-02-07  4:39 UTC (permalink / raw)
  To: srivatsa.bhat
  Cc: paulus, oleg, rusty, peterz, tglx, akpm, mingo, paulmck, tj,
	walken, ego, linux, linux-kernel, ursula.braun, linux-s390,
	netdev

From: "Srivatsa S. Bhat" <srivatsa.bhat@linux.vnet.ibm.com>
Date: Thu, 06 Feb 2014 03:43:55 +0530

> Subsystems that want to register CPU hotplug callbacks, as well as perform
> initialization for the CPUs that are already online, often do it as shown
> below:
 ...
> This is wrong, since it is prone to ABBA deadlocks involving the
> cpu_add_remove_lock and the cpu_hotplug.lock (when running concurrently
> with CPU hotplug operations).
> 
> Instead, the correct and race-free way of performing the callback
> registration is:
 ...
> Fix the code in net/iucv/iucv.c by using this latter form of callback
> registration. Also, provide helper functions to perform the common memory
> allocations and frees, to condense repetitive code.
> 
> Cc: Ursula Braun <ursula.braun@de.ibm.com>
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: linux-s390@vger.kernel.org
> Cc: netdev@vger.kernel.org
> Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>

Applied.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 51/51] net/iucv/iucv.c: Fix CPU hotplug callback registration
  2014-02-07  4:39   ` David Miller
@ 2014-02-07  5:19     ` David Miller
  0 siblings, 0 replies; 6+ messages in thread
From: David Miller @ 2014-02-07  5:19 UTC (permalink / raw)
  To: srivatsa.bhat
  Cc: paulus, oleg, rusty, peterz, tglx, akpm, mingo, paulmck, tj,
	walken, ego, linux, linux-kernel, ursula.braun, linux-s390,
	netdev

From: David Miller <davem@davemloft.net>
Date: Thu, 06 Feb 2014 20:39:35 -0800 (PST)

> Applied.

I just realized that this has a dependency not in the 'net'
tree, so I reverted and assume you will merge this with the
patch that provides the necessary interface(s).

Signed-off-by: David S. Miller <davem@davemloft.net>

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 50/51] net/core/flow.c: Fix CPU hotplug callback registration
  2014-02-07  4:39   ` David Miller
@ 2014-02-07  5:19     ` David Miller
  0 siblings, 0 replies; 6+ messages in thread
From: David Miller @ 2014-02-07  5:19 UTC (permalink / raw)
  To: srivatsa.bhat
  Cc: paulus, oleg, rusty, peterz, tglx, akpm, mingo, paulmck, tj,
	walken, ego, linux, linux-kernel, roy.qing.li, sasha.levin,
	cmetcalf, netdev

From: David Miller <davem@davemloft.net>
Date: Thu, 06 Feb 2014 20:39:21 -0800 (PST)

> From: "Srivatsa S. Bhat" <srivatsa.bhat@linux.vnet.ibm.com>
> Date: Thu, 06 Feb 2014 03:43:46 +0530
> 
>> Subsystems that want to register CPU hotplug callbacks, as well as perform
>> initialization for the CPUs that are already online, often do it as shown
>> below:
>  ...
>> This is wrong, since it is prone to ABBA deadlocks involving the
>> cpu_add_remove_lock and the cpu_hotplug.lock (when running concurrently
>> with CPU hotplug operations).
>> 
>> Instead, the correct and race-free way of performing the callback
>> registration is:
>  ...
>> Fix the code in net/core/flow.c by using this latter form of callback
>> registration.
>> 
>> Cc: "David S. Miller" <davem@davemloft.net>
>> Cc: Li RongQing <roy.qing.li@gmail.com>
>> Cc: Sasha Levin <sasha.levin@oracle.com>
>> Cc: Andrew Morton <akpm@linux-foundation.org>
>> Cc: Chris Metcalf <cmetcalf@tilera.com>
>> Cc: netdev@vger.kernel.org
>> Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
> 
> Applied.

I just realized that this has a dependency not in the 'net'
tree, so I reverted and assume you will merge this with the
patch that provides the necessary interface(s).

Signed-off-by: David S. Miller <davem@davemloft.net>

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2014-02-07  5:19 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <20140205220251.19080.92336.stgit@srivatsabhat.in.ibm.com>
2014-02-05 22:13 ` [PATCH 50/51] net/core/flow.c: Fix CPU hotplug callback registration Srivatsa S. Bhat
2014-02-07  4:39   ` David Miller
2014-02-07  5:19     ` David Miller
2014-02-05 22:13 ` [PATCH 51/51] net/iucv/iucv.c: " Srivatsa S. Bhat
2014-02-07  4:39   ` David Miller
2014-02-07  5:19     ` David Miller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).