android_kernel_google_msm/kernel
Srivatsa S. Bhat b96d7e4f12 CPU hotplug: Provide lockless versions of callback registration functions
(cherry pick from commit 93ae4f978c)

The following method of CPU hotplug callback registration is not safe
due to the possibility of an ABBA deadlock involving the cpu_add_remove_lock
and the cpu_hotplug.lock.

	get_online_cpus();

	for_each_online_cpu(cpu)
		init_cpu(cpu);

	register_cpu_notifier(&foobar_cpu_notifier);

	put_online_cpus();

The deadlock is shown below:

          CPU 0                                         CPU 1
          -----                                         -----

   Acquire cpu_hotplug.lock
   [via get_online_cpus()]

                                              CPU online/offline operation
                                              takes cpu_add_remove_lock
                                              [via cpu_maps_update_begin()]

   Try to acquire
   cpu_add_remove_lock
   [via register_cpu_notifier()]

                                              CPU online/offline operation
                                              tries to acquire cpu_hotplug.lock
                                              [via cpu_hotplug_begin()]

                            *** DEADLOCK! ***

The problem here is that callback registration takes the locks in one order
whereas the CPU hotplug operations take the same locks in the opposite order.
To avoid this issue and to provide a race-free method to register CPU hotplug
callbacks (along with initialization of already online CPUs), introduce new
variants of the callback registration APIs that simply register the callbacks
without holding the cpu_add_remove_lock during the registration. That way,
we can avoid the ABBA scenario. However, we will need to hold the
cpu_add_remove_lock throughout the entire critical section, to protect updates
to the callback/notifier chain.

This can be achieved by writing the callback registration code as follows:

	cpu_maps_update_begin(); [ or cpu_notifier_register_begin(); see below ]

	for_each_online_cpu(cpu)
		init_cpu(cpu);

	/* This doesn't take the cpu_add_remove_lock */
	__register_cpu_notifier(&foobar_cpu_notifier);

	cpu_maps_update_done();  [ or cpu_notifier_register_done(); see below ]

Note that we can't use get_online_cpus() here instead of cpu_maps_update_begin()
because the cpu_hotplug.lock is dropped during the invocation of CPU_POST_DEAD
notifiers, and hence get_online_cpus() cannot provide the necessary
synchronization to protect the callback/notifier chains against concurrent
reads and writes. On the other hand, since the cpu_add_remove_lock protects
the entire hotplug operation (including CPU_POST_DEAD), we can use
cpu_maps_update_begin/done() to guarantee proper synchronization.

Also, since cpu_maps_update_begin/done() is like a super-set of
get/put_online_cpus(), the former naturally protects the critical sections
from concurrent hotplug operations.

Since the names cpu_maps_update_begin/done() don't make much sense in CPU
hotplug callback registration scenarios, we'll introduce new APIs named
cpu_notifier_register_begin/done() and map them to cpu_maps_update_begin/done().

In summary, introduce the lockless variants of un/register_cpu_notifier() and
also export the cpu_notifier_register_begin/done() APIs for use by modules.
This way, we provide a race-free way to register hotplug callbacks as well as
perform initialization for the CPUs that are already online.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ingo Molnar <mingo@kernel.org>
Acked-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Toshi Kani <toshi.kani@hp.com>
Reviewed-by: Gautham R. Shenoy <ego@linux.vnet.ibm.com>
Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Bug: 24810447
Change-Id: I5f85fcb5cfaa5f5f04a29eefc361851e9c345a99
2018-01-01 21:26:45 +03:00
..
debug Merge remote-tracking branch 'stable/linux-3.4.y' into lineage-15.1 2017-12-27 17:13:15 +03:00
events Merge remote-tracking branch 'stable/linux-3.4.y' into lineage-15.1 2017-12-27 17:13:15 +03:00
gcov
irq Merge remote-tracking branch 'stable/linux-3.4.y' into lineage-15.1 2017-12-27 17:13:15 +03:00
power Merge remote-tracking branch 'stable/linux-3.4.y' into lineage-15.1 2017-12-27 17:13:15 +03:00
sched Merge remote-tracking branch 'stable/linux-3.4.y' into lineage-15.1 2017-12-27 17:13:15 +03:00
time Merge remote-tracking branch 'stable/linux-3.4.y' into lineage-15.1 2017-12-27 17:13:15 +03:00
trace Merge remote-tracking branch 'stable/linux-3.4.y' into lineage-15.1 2017-12-27 17:13:15 +03:00
.gitignore kernel/hz.bc: ignore. 2016-10-29 23:12:15 +08:00
acct.c
async.c Fix a dead loop in async_synchronize_full() 2012-10-02 10:30:35 -07:00
audit.c audit: wait_for_auditd() should use TASK_UNINTERRUPTIBLE 2014-04-14 06:44:15 -07:00
audit.h
audit_tree.c Merge remote-tracking branch 'stable/linux-3.4.y' into lineage-15.1 2017-12-27 17:13:15 +03:00
audit_watch.c get rid of kern_path_parent() 2017-09-22 19:11:54 +03:00
auditfilter.c
auditsc.c Merge remote-tracking branch 'stable/linux-3.4.y' into lineage-15.1 2017-12-27 17:13:15 +03:00
backtracetest.c
bounds.c
capability.c
cgroup.c Merge remote-tracking branch 'stable/linux-3.4.y' into lineage-15.1 2017-12-27 17:13:15 +03:00
cgroup_freezer.c cgroup: cgroup_subsys->fork() should be called after the task is added to css_set 2014-03-11 16:10:03 -07:00
compat.c compat: Fix RT signal mask corruption via sigprocmask 2012-05-10 08:58:33 -07:00
configs.c
cpu.c CPU hotplug: Provide lockless versions of callback registration functions 2018-01-01 21:26:45 +03:00
cpu_pm.c
cpuset.c cpuset: PF_SPREAD_PAGE and PF_SPREAD_SLAB should be atomic flags 2014-12-01 18:02:38 +08:00
crash_dump.c
cred.c cred: copy_process() should clear child->replacement_session_keyring 2012-04-11 08:20:11 -07:00
delayacct.c
dma.c Remove all #inclusions of asm/system.h 2012-03-28 18:30:03 +01:00
elfcore.c
exec_domain.c ANDROID: exec_domains: Disable request_module() call for personalities 2017-12-27 22:46:26 +03:00
exit.c Merge remote-tracking branch 'stable/linux-3.4.y' into lineage-15.1 2017-12-27 17:13:15 +03:00
extable.c
fork.c seccomp: Replace BUG(!spin_is_locked()) with assert_spin_lock 2017-12-27 22:42:09 +03:00
freezer.c Merge remote-tracking branch 'stable/linux-3.4.y' into lineage-15.1 2017-12-27 17:13:15 +03:00
futex.c Merge remote-tracking branch 'stable/linux-3.4.y' into lineage-15.1 2017-12-27 17:13:15 +03:00
futex_compat.c futex: Revert "futex: Mark get_robust_list as deprecated" 2013-02-28 06:59:01 -08:00
groups.c
hrtimer.c Merge remote-tracking branch 'stable/linux-3.4.y' into lineage-15.1 2017-12-27 17:13:15 +03:00
hung_task.c
irq_work.c irq_work: fix compile failure on tile from missing include 2012-04-13 13:15:16 -04:00
itimer.c itimer: Use printk_once instead of WARN_ONCE 2012-04-10 11:00:30 +02:00
jump_label.c
kallsyms.c vsprintf: Fix %ps on non symbols when using kallsyms 2013-02-08 15:14:22 -08:00
Kconfig.freezer
Kconfig.hz
Kconfig.locks locking/kconfig: Simplify INLINE_SPIN_UNLOCK usage 2012-03-23 13:18:57 +01:00
Kconfig.preempt locking/kconfig: Simplify INLINE_SPIN_UNLOCK usage 2012-03-23 13:18:57 +01:00
kexec.c Merge branch 'akpm' (Andrew's patch-bomb) 2012-03-28 17:19:28 -07:00
kfifo.c
kmod.c usermodehelper: check subprocess_info->path != NULL 2013-05-19 10:54:50 -07:00
kprobes.c
ksysfs.c rcu: Add a module parameter to force use of expedited RCU primitives 2016-10-29 23:12:17 +08:00
kthread.c Merge remote-tracking branch 'stable/linux-3.4.y' into lineage-15.1 2017-12-27 17:13:15 +03:00
latencytop.c
lglock.c brlocks/lglocks: turn into functions 2015-07-13 11:17:40 -07:00
lockdep.c lockdep: remove task argument from debug_check_no_locks_held 2013-07-12 14:22:56 -07:00
lockdep_internals.h
lockdep_proc.c
lockdep_states.h
Makefile hotplug: Fix UP bug in smpboot hotplug code 2016-10-29 23:12:39 +08:00
module.c module: Fix locking in symbol_put_addr() 2016-04-27 18:55:19 +08:00
mutex-debug.c
mutex-debug.h
mutex.c
mutex.h
notifier.c
nsproxy.c userns: make each net (net_ns) belong to a user_ns 2017-09-01 13:38:07 +03:00
padata.c padata: Fix cpu hotplug 2012-03-29 19:52:46 +08:00
panic.c Merge remote-tracking branch 'stable/linux-3.4.y' into lineage-15.1 2017-12-27 17:13:15 +03:00
params.c params: <level>_initcall-like kernel parameters 2012-03-26 12:50:51 +10:30
pid.c proc: Usable inode numbers for the namespace file descriptors. 2015-07-13 11:18:01 -07:00
pid_namespace.c proc: Usable inode numbers for the namespace file descriptors. 2015-07-13 11:18:01 -07:00
posix-cpu-timers.c posix-cpu-timers: Fix nanosleep task_struct leak 2013-02-28 06:58:59 -08:00
posix-timers.c posix-timers: Fix stack info leak in timer_create() 2015-02-02 17:05:05 +08:00
printk.c Merge remote-tracking branch 'stable/linux-3.4.y' into lineage-15.1 2017-12-27 17:13:15 +03:00
profile.c
ptrace.c Merge remote-tracking branch 'stable/linux-3.4.y' into lineage-15.1 2017-12-27 17:13:15 +03:00
range.c
rcu.h rcu: Add a module parameter to force use of expedited RCU primitives 2016-10-29 23:12:17 +08:00
rcupdate.c rcu: Make exit_rcu() more precise and consolidate 2016-10-29 23:12:17 +08:00
rcutiny.c rcu: Correctly handle non-empty Tiny RCU callback list with none ready 2015-10-22 09:20:02 +08:00
rcutiny_plugin.h rcu: Make exit_rcu() more precise and consolidate 2016-10-29 23:12:17 +08:00
rcutorture.c
rcutree.c rcu: Use smp_hotplug_thread facility for RCUs per-CPU kthread 2016-10-29 23:12:39 +08:00
rcutree.h rcu: Use smp_hotplug_thread facility for RCUs per-CPU kthread 2016-10-29 23:12:39 +08:00
rcutree_plugin.h rcu: Use smp_hotplug_thread facility for RCUs per-CPU kthread 2016-10-29 23:12:39 +08:00
rcutree_trace.c rcu: Use smp_hotplug_thread facility for RCUs per-CPU kthread 2016-10-29 23:12:39 +08:00
relay.c splice: fix racy pipe->buffers uses 2012-07-16 09:04:42 -07:00
res_counter.c
resource.c Merge remote-tracking branch 'stable/linux-3.4.y' into lineage-15.1 2017-12-27 17:13:15 +03:00
rtmutex-debug.c
rtmutex-debug.h rtmutex: Handle deadlock detection smarter 2014-07-17 15:39:50 -07:00
rtmutex-tester.c
rtmutex.c rtmutex: Plug slow unlock race 2014-07-17 15:39:50 -07:00
rtmutex.h rtmutex: Handle deadlock detection smarter 2014-07-17 15:39:50 -07:00
rtmutex_common.h
rwsem.c Remove all #inclusions of asm/system.h 2012-03-28 18:30:03 +01:00
seccomp.c seccomp: Replace BUG(!spin_is_locked()) with assert_spin_lock 2017-12-27 22:42:09 +03:00
semaphore.c
signal.c BACKPORT: signal: allow to send any siginfo to itself 2017-12-27 22:49:08 +03:00
smp.c Merge remote-tracking branch 'stable/linux-3.4.y' into lineage-15.1 2017-12-27 17:13:15 +03:00
smpboot.c smpboot: use kmemleak_not_leak for smpboot_thread_data 2016-10-29 23:12:40 +08:00
smpboot.h smpboot: Provide infrastructure for percpu hotplug threads 2016-10-29 23:12:39 +08:00
softirq.c Merge remote-tracking branch 'stable/linux-3.4.y' into lineage-15.1 2017-12-27 17:13:15 +03:00
spinlock.c locking/kconfig: Simplify INLINE_SPIN_UNLOCK usage 2012-03-23 13:18:57 +01:00
srcu.c
stacktrace.c
stop_machine.c stop_machine: Mark per cpu stopper enabled early 2016-10-29 23:12:39 +08:00
sys.c Merge remote-tracking branch 'stable/linux-3.4.y' into lineage-15.1 2017-12-27 17:13:15 +03:00
sys_ni.c seccomp: add "seccomp" syscall 2014-10-31 19:46:27 -07:00
sysctl.c Merge remote-tracking branch 'stable/linux-3.4.y' into lineage-15.1 2017-12-27 17:13:15 +03:00
sysctl_binary.c Merge remote-tracking branch 'stable/linux-3.4.y' into lineage-15.1 2017-12-27 17:13:15 +03:00
taskstats.c
test_kprobes.c
time.c jiffies: Fix timeval conversion to jiffies 2016-10-29 23:12:15 +08:00
timeconst.bc kernel: Replace timeconst.pl with a bc script 2016-10-29 23:12:15 +08:00
timer.c tick: Upstream fixes 2017-08-25 20:00:22 +03:00
tracepoint.c tracepoint: Do not waste memory on mods with no tracepoints 2014-05-18 05:25:56 -07:00
tsacct.c
uid16.c
up.c
user-return-notifier.c
user.c proc: Usable inode numbers for the namespace file descriptors. 2015-07-13 11:18:01 -07:00
user_namespace.c proc: Usable inode numbers for the namespace file descriptors. 2015-07-13 11:18:01 -07:00
utsname.c proc: Usable inode numbers for the namespace file descriptors. 2015-07-13 11:18:01 -07:00
utsname_sysctl.c
wait.c
watchdog.c kernel/watchdog.c: touch_nmi_watchdog should only touch local cpu not every one 2016-03-21 09:17:57 +08:00
workqueue.c Merge remote-tracking branch 'stable/linux-3.4.y' into lineage-15.1 2017-12-27 17:13:15 +03:00
workqueue_sched.h