From: Greg KH <gregkh@suse.de>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: torvalds@linux-foundation.org, akpm@linux-foundation.org,
alan@lxorguk.ukuu.org.uk,
"Srivatsa S. Bhat" <srivatsa.bhat@linux.vnet.ibm.com>,
Al Viro <viro@zeniv.linux.org.uk>
Subject: [32/67] VFS: Fix race between CPU hotplug and lglocks
Date: Tue, 03 Jan 2012 14:29:50 -0800 [thread overview]
Message-ID: <20120103223034.049889098@clark.kroah.org> (raw)
In-Reply-To: <20120103223043.GA26738@kroah.com>
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: "Srivatsa S. Bhat" <srivatsa.bhat@linux.vnet.ibm.com>
commit e30e2fdfe56288576ee9e04dbb06b4bd5f282203 upstream.
Currently, the *_global_[un]lock_online() routines are not at all synchronized
with CPU hotplug. Soft-lockups detected as a consequence of this race was
reported earlier at https://lkml.org/lkml/2011/8/24/185. (Thanks to Cong Meng
for finding out that the root-cause of this issue is the race condition
between br_write_[un]lock() and CPU hotplug, which results in the lock states
getting messed up).
Fixing this race by just adding {get,put}_online_cpus() at appropriate places
in *_global_[un]lock_online() is not a good option, because, then suddenly
br_write_[un]lock() would become blocking, whereas they have been kept as
non-blocking all this time, and we would want to keep them that way.
So, overall, we want to ensure 3 things:
1. br_write_lock() and br_write_unlock() must remain as non-blocking.
2. The corresponding lock and unlock of the per-cpu spinlocks must not happen
for different sets of CPUs.
3. Either prevent any new CPU online operation in between this lock-unlock, or
ensure that the newly onlined CPU does not proceed with its corresponding
per-cpu spinlock unlocked.
To achieve all this:
(a) We introduce a new spinlock that is taken by the *_global_lock_online()
routine and released by the *_global_unlock_online() routine.
(b) We register a callback for CPU hotplug notifications, and this callback
takes the same spinlock as above.
(c) We maintain a bitmap which is close to the cpu_online_mask, and once it is
initialized in the lock_init() code, all future updates to it are done in
the callback, under the above spinlock.
(d) The above bitmap is used (instead of cpu_online_mask) while locking and
unlocking the per-cpu locks.
The callback takes the spinlock upon the CPU_UP_PREPARE event. So, if the
br_write_lock-unlock sequence is in progress, the callback keeps spinning,
thus preventing the CPU online operation till the lock-unlock sequence is
complete. This takes care of requirement (3).
The bitmap that we maintain remains unmodified throughout the lock-unlock
sequence, since all updates to it are managed by the callback, which takes
the same spinlock as the one taken by the lock code and released only by the
unlock routine. Combining this with (d) above, satisfies requirement (2).
Overall, since we use a spinlock (mentioned in (a)) to prevent CPU hotplug
operations from racing with br_write_lock-unlock, requirement (1) is also
taken care of.
By the way, it is to be noted that a CPU offline operation can actually run
in parallel with our lock-unlock sequence, because our callback doesn't react
to notifications earlier than CPU_DEAD (in order to maintain our bitmap
properly). And this means, since we use our own bitmap (which is stale, on
purpose) during the lock-unlock sequence, we could end up unlocking the
per-cpu lock of an offline CPU (because we had locked it earlier, when the
CPU was online), in order to satisfy requirement (2). But this is harmless,
though it looks a bit awkward.
Debugged-by: Cong Meng <mc@linux.vnet.ibm.com>
Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
include/linux/lglock.h | 36 ++++++++++++++++++++++++++++++++----
1 file changed, 32 insertions(+), 4 deletions(-)
--- a/include/linux/lglock.h
+++ b/include/linux/lglock.h
@@ -22,6 +22,7 @@
#include <linux/spinlock.h>
#include <linux/lockdep.h>
#include <linux/percpu.h>
+#include <linux/cpu.h>
/* can make br locks by using local lock for read side, global lock for write */
#define br_lock_init(name) name##_lock_init()
@@ -72,9 +73,31 @@
#define DEFINE_LGLOCK(name) \
\
+ DEFINE_SPINLOCK(name##_cpu_lock); \
+ cpumask_t name##_cpus __read_mostly; \
DEFINE_PER_CPU(arch_spinlock_t, name##_lock); \
DEFINE_LGLOCK_LOCKDEP(name); \
\
+ static int \
+ name##_lg_cpu_callback(struct notifier_block *nb, \
+ unsigned long action, void *hcpu) \
+ { \
+ switch (action & ~CPU_TASKS_FROZEN) { \
+ case CPU_UP_PREPARE: \
+ spin_lock(&name##_cpu_lock); \
+ cpu_set((unsigned long)hcpu, name##_cpus); \
+ spin_unlock(&name##_cpu_lock); \
+ break; \
+ case CPU_UP_CANCELED: case CPU_DEAD: \
+ spin_lock(&name##_cpu_lock); \
+ cpu_clear((unsigned long)hcpu, name##_cpus); \
+ spin_unlock(&name##_cpu_lock); \
+ } \
+ return NOTIFY_OK; \
+ } \
+ static struct notifier_block name##_lg_cpu_notifier = { \
+ .notifier_call = name##_lg_cpu_callback, \
+ }; \
void name##_lock_init(void) { \
int i; \
LOCKDEP_INIT_MAP(&name##_lock_dep_map, #name, &name##_lock_key, 0); \
@@ -83,6 +106,11 @@
lock = &per_cpu(name##_lock, i); \
*lock = (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED; \
} \
+ register_hotcpu_notifier(&name##_lg_cpu_notifier); \
+ get_online_cpus(); \
+ for_each_online_cpu(i) \
+ cpu_set(i, name##_cpus); \
+ put_online_cpus(); \
} \
EXPORT_SYMBOL(name##_lock_init); \
\
@@ -124,9 +152,9 @@
\
void name##_global_lock_online(void) { \
int i; \
- preempt_disable(); \
+ spin_lock(&name##_cpu_lock); \
rwlock_acquire(&name##_lock_dep_map, 0, 0, _RET_IP_); \
- for_each_online_cpu(i) { \
+ for_each_cpu(i, &name##_cpus) { \
arch_spinlock_t *lock; \
lock = &per_cpu(name##_lock, i); \
arch_spin_lock(lock); \
@@ -137,12 +165,12 @@
void name##_global_unlock_online(void) { \
int i; \
rwlock_release(&name##_lock_dep_map, 1, _RET_IP_); \
- for_each_online_cpu(i) { \
+ for_each_cpu(i, &name##_cpus) { \
arch_spinlock_t *lock; \
lock = &per_cpu(name##_lock, i); \
arch_spin_unlock(lock); \
} \
- preempt_enable(); \
+ spin_unlock(&name##_cpu_lock); \
} \
EXPORT_SYMBOL(name##_global_unlock_online); \
\
next prev parent reply other threads:[~2012-01-03 22:36 UTC|newest]
Thread overview: 82+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-01-03 22:30 [00/67] 3.0.16-stable review Greg KH
2012-01-03 22:29 ` [01/67] ARM: OMAP: rx51: fix USB Greg KH
2012-01-03 22:29 ` [02/67] ipip, sit: copy parms.name after register_netdevice Greg KH
2012-01-03 22:29 ` [03/67] rtc: Expire alarms after the time is set Greg KH
2012-01-03 22:46 ` John Stultz
2012-01-03 22:47 ` Greg KH
2012-01-03 23:11 ` John Stultz
2012-01-03 22:29 ` [04/67] rtc: m41t80: Workaround broken alarm functionality Greg KH
2012-01-03 22:29 ` [05/67] drm/i915: prevent division by zero when asking for chipset power Greg KH
2012-01-03 22:29 ` [06/67] cfq-iosched: free cic_index if blkio_alloc_blkg_stats fails Greg KH
2012-01-03 22:29 ` [07/67] cfq-iosched: fix cfq_cic_link() race confition Greg KH
2012-01-03 22:29 ` [08/67] SCSI: zfcp: return early from slave_destroy if slave_alloc returned early Greg KH
2012-01-03 22:29 ` [09/67] SCSI: mpt2sas: _scsih_smart_predicted_fault uses GFP_KERNEL in interrupt context Greg KH
2012-01-03 22:29 ` [10/67] SCSI: fcoe: Fix preempt count leak in fcoe_filter_frames() Greg KH
2012-01-03 22:29 ` [11/67] mac80211: fix another race in aggregation start Greg KH
2012-01-03 22:29 ` [12/67] block: initialize request_queues numa node during Greg KH
2012-01-03 22:29 ` [13/67] ssb: fix init regression with SoCs Greg KH
2012-01-03 22:29 ` [14/67] MXC PWM: should active during DOZE/WAIT/DBG mode Greg KH
2012-01-03 22:29 ` [15/67] Input: synaptics - fix touchpad not working after S2R on Vostro V13 Greg KH
2012-01-03 22:29 ` [16/67] percpu: fix per_cpu_ptr_to_phys() handling of non-page-aligned addresses Greg KH
2012-01-03 22:29 ` [17/67] binary_sysctl(): fix memory leak Greg KH
2012-01-03 22:29 ` [18/67] oom: fix integer overflow of points in oom_badness Greg KH
2012-01-03 22:29 ` [19/67] oprofile: Fix uninitialized memory access when writing to writing to oprofilefs Greg KH
2012-01-03 22:29 ` [20/67] NFSv4.1: Ensure that we handle _all_ SEQUENCE status bits Greg KH
2012-01-03 22:29 ` [21/67] SELinux: Fix RCU deref check warning in sel_netport_insert() Greg KH
2012-01-03 22:29 ` [22/67] nilfs2: unbreak compat ioctl Greg KH
2012-01-03 22:29 ` [23/67] mmc: vub300: fix type of firmware_rom_wait_states module parameter Greg KH
2012-01-03 22:29 ` [24/67] cgroups: fix a css_set not found bug in cgroup_attach_proc Greg KH
2012-01-03 22:29 ` [25/67] mfd: Fix twl-core oops while calling twl_i2c_* for unbound driver Greg KH
2012-01-03 22:29 ` [26/67] vfs: __read_cache_page should use gfp argument rather than GFP_KERNEL Greg KH
2012-01-03 22:29 ` [27/67] media: s5p-fimc: Use correct fourcc for RGB565 colour format Greg KH
2012-01-03 22:29 ` [28/67] ath9k: fix max phy rate at rate control init Greg KH
2012-01-03 22:29 ` [29/67] iwlwifi: do not set the sequence control bit is not needed Greg KH
2012-01-03 22:29 ` [30/67] iwlwifi: allow to switch to HT40 if not associated Greg KH
2012-01-03 22:29 ` [31/67] memcg: keep root group unchanged if creation fails Greg KH
2012-01-03 22:29 ` Greg KH [this message]
2012-01-03 22:29 ` [33/67] ARM:imx:fix pwm period value Greg KH
2012-01-03 22:29 ` [34/67] ARM: 7214/1: mmc: mmci: Fixup handling of MCI_STARTBITERR Greg KH
2012-01-03 22:29 ` [35/67] ARM: 7220/1: mmc: mmci: Fixup error handling for dma Greg KH
2012-01-03 22:29 ` [36/67] oprofile, arm/sh: Fix oprofile_arch_exit() linkage issue Greg KH
2012-01-03 22:29 ` [37/67] futex: Fix uninterruptible loop due to gate_area Greg KH
2012-01-03 22:29 ` [38/67] watchdog: hpwdt: Changes to handle NX secure bit in 32bit path Greg KH
2012-01-03 22:29 ` [39/67] drm/radeon/kms: bail on BTC parts if MC ucode is missing Greg KH
2012-01-03 22:29 ` [40/67] mm: hugetlb: fix non-atomic enqueue of huge page Greg KH
2012-01-03 22:29 ` [41/67] mpt2sas crashes on shutdown Greg KH
2012-01-03 22:30 ` [42/67] sparc64: Fix MSIQ HV call ordering in pci_sun4v_msiq_build_irq() Greg KH
2012-01-03 22:30 ` [43/67] sparc32: Be less strict in matching %lo part of relocation Greg KH
2012-01-03 22:30 ` [44/67] sparc64: Patch sun4v code sequences properly on module load Greg KH
2012-01-03 22:30 ` [45/67] sparc: Kill custom io_remap_pfn_range() Greg KH
2012-01-03 22:30 ` [46/67] sparc32: Remove non-kernel code from memcpy implementation Greg KH
2012-01-03 22:30 ` [47/67] sparc32: Remove uses of %g7 in " Greg KH
2012-01-03 22:30 ` [48/67] sparc32: Correct the return value of memcpy Greg KH
2012-01-03 22:30 ` [49/67] sparc64: Fix masking and shifting in VIS fpcmp emulation Greg KH
2012-01-03 22:30 ` [50/67] sparc: Fix handling of orig_i0 wrt. debugging when restarting syscalls Greg KH
2012-01-03 22:30 ` [51/67] net: bpf_jit: fix an off-one bug in x86_64 cond jump target Greg KH
2012-01-03 22:30 ` [52/67] ppp: fix pptp double release_sock in pptp_bind() Greg KH
2012-01-03 22:30 ` [53/67] llc: llc_cmsg_rcv was getting called after sk_eat_skb Greg KH
2012-01-03 22:30 ` [54/67] mqprio: Avoid panic if no options are provided Greg KH
2012-01-03 22:30 ` [55/67] net: have ipconfig not wait if no dev is available Greg KH
2012-01-03 22:30 ` [56/67] sch_gred: should not use GFP_KERNEL while holding a spinlock Greg KH
2012-01-03 22:30 ` [57/67] sctp: fix incorrect overflow check on autoclose Greg KH
2012-01-03 22:30 ` [58/67] sctp: Do not account for sizeof(struct sk_buff) in estimated rwnd Greg KH
2012-01-03 22:30 ` [59/67] ipv4: flush route cache after change accept_local Greg KH
2012-01-03 22:30 ` [60/67] ipv4: reintroduce route cache garbage collector Greg KH
2012-01-03 22:30 ` [61/67] ipv4: using prefetch requires including prefetch.h Greg KH
2012-01-03 22:30 ` [62/67] iwlwifi: update SCD BC table for all SCD queues Greg KH
2012-01-03 22:30 ` [63/67] mfd: Fix mismatch in twl4030 mutex lock-unlock Greg KH
2012-01-03 22:30 ` [64/67] mfd: Copy the device pointer to the twl4030-madc structure Greg KH
2012-01-03 22:30 ` [65/67] mfd: Check for twl4030-madc NULL pointer Greg KH
2012-01-03 22:30 ` [66/67] mfd: Turn on the twl4030-madc MADC clock Greg KH
2012-01-03 22:30 ` [67/67] xen/swiotlb: Use page alignment for early buffer allocation Greg KH
2012-01-05 19:18 ` [00/67] 3.0.16-stable review Greg KH
2012-01-05 19:26 ` Greg KH
2012-01-05 22:46 ` Greg KH
2012-01-05 22:44 ` [40/73] mpt2sas: fix non-x86 crash on shutdown Greg KH
2012-01-05 22:44 ` [67/73] xfs: log the inode in ->write_inode calls for kupdate Greg KH
2012-01-05 22:44 ` [68/73] xfs: log all dirty inodes in xfs_fs_sync_fs Greg KH
2012-01-05 22:44 ` [69/73] drm/radeon/kms/atom: fix possible segfault in pm setup Greg KH
2012-01-05 22:44 ` [70/73] hung_task: fix false positive during vfork Greg KH
2012-01-05 22:44 ` [71/73] Revert "rtc: Disable the alarm in the hardware" Greg KH
2012-01-05 22:44 ` [72/73] ptrace: partially fix the do_wait(WEXITED) vs EXIT_DEAD->EXIT_ZOMBIE race Greg KH
2012-01-05 22:44 ` [73/73] ath9k: Fix kernel panic in AR2427 in AP mode Greg KH
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=20120103223034.049889098@clark.kroah.org \
--to=gregkh@suse.de \
--cc=akpm@linux-foundation.org \
--cc=alan@lxorguk.ukuu.org.uk \
--cc=linux-kernel@vger.kernel.org \
--cc=srivatsa.bhat@linux.vnet.ibm.com \
--cc=stable@vger.kernel.org \
--cc=torvalds@linux-foundation.org \
--cc=viro@zeniv.linux.org.uk \
/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
Powered by JetHome