linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
From: "Srivatsa S. Bhat" <srivatsa.bhat@linux.vnet.ibm.com>
To: paulus@samba.org, oleg@redhat.com, mingo@kernel.org,
	rjw@rjwysocki.net, rusty@rustcorp.com.au, peterz@infradead.org,
	tglx@linutronix.de, akpm@linux-foundation.org
Cc: linux-arch@vger.kernel.org, ego@linux.vnet.ibm.com,
	walken@google.com, linux@arm.linux.org.uk,
	linux-pm@vger.kernel.org, linux-s390@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	Ursula Braun <ursula.braun@de.ibm.com>,
	linuxppc-dev@ozlabs.org, "David S. Miller" <davem@davemloft.net>,
	"Srivatsa S. Bhat" <srivatsa.bhat@linux.vnet.ibm.com>,
	netdev@vger.kernel.org, tj@kernel.org,
	paulmck@linux.vnet.ibm.com, Ingo Molnar <mingo@kernel.org>
Subject: [PATCH v3 52/52] net/iucv/iucv.c: Fix CPU hotplug callback registration
Date: Tue, 11 Mar 2014 02:12:57 +0530	[thread overview]
Message-ID: <20140310204257.10746.50242.stgit@srivatsabhat.in.ibm.com> (raw)
In-Reply-To: <20140310203312.10746.310.stgit@srivatsabhat.in.ibm.com>

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_notifier_register_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_notifier_register_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: Ingo Molnar <mingo@kernel.org>
Cc: linux-s390@vger.kernel.org
Cc: netdev@vger.kernel.org
Acked-by: David S. Miller <davem@davemloft.net>
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..79a0ce9 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_notifier_register_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_notifier_register_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_notifier_register_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_notifier_register_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_notifier_register_begin();
+	__unregister_hotcpu_notifier(&iucv_cpu_notifier);
+	for_each_possible_cpu(cpu)
+		free_iucv_data(cpu);
+	cpu_notifier_register_done();
 	root_device_unregister(iucv_root);
 	bus_unregister(&iucv_bus);
 	unregister_external_interrupt(0x4000, iucv_external_interrupt);

  parent reply	other threads:[~2014-03-10 20:43 UTC|newest]

Thread overview: 63+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-03-10 20:33 [PATCH v3 00/52] CPU hotplug: Fix issues with callback registration Srivatsa S. Bhat
2014-03-10 20:34 ` [PATCH v3 01/52] CPU hotplug: Add lockdep annotations to get/put_online_cpus() Srivatsa S. Bhat
2014-03-10 20:34 ` [PATCH v3 02/52] CPU hotplug: Provide lockless versions of callback registration functions Srivatsa S. Bhat
2014-03-10 20:34 ` [PATCH v3 03/52] Doc/cpu-hotplug: Specify race-free way to register CPU hotplug callbacks Srivatsa S. Bhat
2014-03-10 20:34 ` [PATCH v3 04/52] CPU hotplug, perf: Fix CPU hotplug callback registration Srivatsa S. Bhat
2014-03-10 20:34 ` [PATCH v3 05/52] ia64, salinfo: Fix " Srivatsa S. Bhat
2014-03-10 20:34 ` [PATCH v3 06/52] ia64, palinfo: Fix CPU " Srivatsa S. Bhat
2014-03-10 20:34 ` [PATCH v3 07/52] ia64, topology: " Srivatsa S. Bhat
2014-03-10 20:35 ` [PATCH v3 08/52] ia64, err-inject: " Srivatsa S. Bhat
2014-03-10 20:35 ` [PATCH v3 09/52] arm, hw-breakpoint: " Srivatsa S. Bhat
2014-03-10 20:35 ` [PATCH v3 10/52] arm, kvm: " Srivatsa S. Bhat
2014-03-12 23:21   ` Christoffer Dall
2014-03-14  5:43     ` Srivatsa S. Bhat
2014-03-14 19:10       ` Christoffer Dall
2014-03-18 10:23         ` [UPDATED PATCH " Srivatsa S. Bhat
2014-03-18 22:08           ` Christoffer Dall
2014-03-10 20:35 ` [PATCH v3 11/52] s390, cacheinfo: " Srivatsa S. Bhat
2014-03-10 20:35 ` [PATCH v3 12/52] s390, smp: " Srivatsa S. Bhat
2014-03-10 20:36 ` [PATCH v3 13/52] sparc, sysfs: " Srivatsa S. Bhat
2014-03-10 20:36 ` [PATCH v3 14/52] powerpc, " Srivatsa S. Bhat
2014-03-10 20:36 ` [PATCH v3 15/52] x86, msr: " Srivatsa S. Bhat
2014-03-10 20:36 ` [PATCH v3 16/52] x86, cpuid: " Srivatsa S. Bhat
2014-03-10 20:36 ` [PATCH v3 17/52] x86, vsyscall: " Srivatsa S. Bhat
2014-03-10 20:36 ` [PATCH v3 18/52] x86, intel, uncore: " Srivatsa S. Bhat
2014-03-10 20:37 ` [PATCH v3 19/52] x86, mce: " Srivatsa S. Bhat
2014-03-10 20:37 ` [PATCH v3 20/52] x86, therm_throt.c: " Srivatsa S. Bhat
2014-03-10 20:37 ` [PATCH v3 21/52] x86, therm_throt.c: Remove unused therm_cpu_lock Srivatsa S. Bhat
2014-03-10 20:37 ` [PATCH v3 22/52] x86, amd, ibs: Fix CPU hotplug callback registration Srivatsa S. Bhat
2014-03-10 20:37 ` [PATCH v3 23/52] x86, intel, cacheinfo: " Srivatsa S. Bhat
2014-03-10 20:38 ` [PATCH v3 24/52] x86, intel, rapl: " Srivatsa S. Bhat
2014-03-10 20:38 ` [PATCH v3 25/52] x86, amd, uncore: " Srivatsa S. Bhat
2014-03-10 20:38 ` [PATCH v3 26/52] x86, hpet: " Srivatsa S. Bhat
2014-03-10 20:38 ` [PATCH v3 27/52] x86, pci, amd-bus: " Srivatsa S. Bhat
2014-03-10 20:38 ` [PATCH v3 28/52] x86, oprofile, nmi: " Srivatsa S. Bhat
2014-03-10 20:39 ` [PATCH v3 29/52] x86, kvm: " Srivatsa S. Bhat
2014-03-10 20:39 ` [PATCH v3 30/52] arm64, hw_breakpoint.c: " Srivatsa S. Bhat
2014-03-10 20:39 ` [PATCH v3 31/52] arm64, debug-monitors: " Srivatsa S. Bhat
2014-03-10 20:39 ` [PATCH v3 32/52] powercap, intel-rapl: " Srivatsa S. Bhat
2014-03-12 22:27   ` Jacob Pan
2014-03-10 20:39 ` [PATCH v3 33/52] scsi, bnx2i: " Srivatsa S. Bhat
2014-03-10 20:39 ` [PATCH v3 34/52] scsi, bnx2fc: " Srivatsa S. Bhat
2014-03-10 20:39 ` [PATCH v3 35/52] scsi, fcoe: " Srivatsa S. Bhat
2014-03-10 20:39 ` [PATCH v3 36/52] zsmalloc: " Srivatsa S. Bhat
2014-03-14  6:41   ` Minchan Kim
2014-03-10 20:40 ` [PATCH v3 37/52] acpi-cpufreq: " Srivatsa S. Bhat
2014-03-10 20:40 ` [PATCH v3 38/52] drivers/base/topology.c: " Srivatsa S. Bhat
2014-03-10 20:40 ` [PATCH v3 39/52] clocksource, dummy-timer: " Srivatsa S. Bhat
2014-03-10 20:40 ` [PATCH v3 40/52] intel-idle: " Srivatsa S. Bhat
2014-03-10 20:40 ` [PATCH v3 41/52] oprofile, nmi-timer: " Srivatsa S. Bhat
2014-03-10 20:40 ` [PATCH v3 42/52] octeon, watchdog: " Srivatsa S. Bhat
2014-03-10 20:40 ` [PATCH v3 43/52] thermal, x86-pkg-temp: " Srivatsa S. Bhat
2014-03-10 20:41 ` [PATCH v3 44/52] hwmon, coretemp: " Srivatsa S. Bhat
2014-03-10 20:41 ` [PATCH v3 45/52] hwmon, via-cputemp: " Srivatsa S. Bhat
2014-03-10 20:41 ` [PATCH v3 46/52] xen, balloon: " Srivatsa S. Bhat
2014-03-10 20:41 ` [PATCH v3 47/52] trace, ring-buffer: " Srivatsa S. Bhat
2014-03-10 20:42 ` [PATCH v3 48/52] profile: " Srivatsa S. Bhat
2014-03-10 20:42 ` [PATCH v3 49/52] mm, vmstat: " Srivatsa S. Bhat
2014-03-10 20:42 ` [PATCH v3 50/52] mm, zswap: " Srivatsa S. Bhat
2014-03-10 20:42 ` [PATCH v3 51/52] net/core/flow.c: " Srivatsa S. Bhat
2014-03-10 20:42 ` Srivatsa S. Bhat [this message]
2014-03-11  0:31 ` [PATCH v3 00/52] CPU hotplug: Fix issues with " Rafael J. Wysocki
2014-03-11 22:07 ` Andrew Morton
2014-03-12 20:48   ` Srivatsa S. Bhat

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20140310204257.10746.50242.stgit@srivatsabhat.in.ibm.com \
    --to=srivatsa.bhat@linux.vnet.ibm.com \
    --cc=akpm@linux-foundation.org \
    --cc=davem@davemloft.net \
    --cc=ego@linux.vnet.ibm.com \
    --cc=linux-arch@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pm@vger.kernel.org \
    --cc=linux-s390@vger.kernel.org \
    --cc=linux@arm.linux.org.uk \
    --cc=linuxppc-dev@ozlabs.org \
    --cc=mingo@kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=oleg@redhat.com \
    --cc=paulmck@linux.vnet.ibm.com \
    --cc=paulus@samba.org \
    --cc=peterz@infradead.org \
    --cc=rjw@rjwysocki.net \
    --cc=rusty@rustcorp.com.au \
    --cc=tglx@linutronix.de \
    --cc=tj@kernel.org \
    --cc=ursula.braun@de.ibm.com \
    --cc=walken@google.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).