aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/kernel/traps.c
diff options
context:
space:
mode:
authorGraf Yang <graf.yang@analog.com>2010-01-13 06:09:34 +0000
committerMike Frysinger <vapier@gentoo.org>2010-03-09 00:30:49 -0500
commitc6669c223a409199a45bb8f31a2e160ee26d19cc (patch)
treecb46eb31a6ed699ce7ed31e874e965a38f987bd5 /arch/blackfin/kernel/traps.c
parentBlackfin: bf533-{ezkit,stamp}: add sound platform devices (diff)
downloadlinux-dev-c6669c223a409199a45bb8f31a2e160ee26d19cc.tar.xz
linux-dev-c6669c223a409199a45bb8f31a2e160ee26d19cc.zip
Blackfin: fix up mm locking in address dumping
The locking code in the address dumper needs to grab the mm's mmap_sem so that other CPUs do not get an inconsistent view. On UP systems this really wasn't a problem, but it is easy to trigger a race on SMP systems when another CPU removes a mapping. Signed-off-by: Graf Yang <graf.yang@analog.com> Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'arch/blackfin/kernel/traps.c')
-rw-r--r--arch/blackfin/kernel/traps.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c
index 870d74b1b407..85766805b03a 100644
--- a/arch/blackfin/kernel/traps.c
+++ b/arch/blackfin/kernel/traps.c
@@ -138,6 +138,12 @@ static void decode_address(char *buf, unsigned long address)
if (!mm)
continue;
+ if (!down_read_trylock(&mm->mmap_sem)) {
+ if (!in_atomic)
+ mmput(mm);
+ continue;
+ }
+
for (n = rb_first(&mm->mm_rb); n; n = rb_next(n)) {
struct vm_area_struct *vma;
@@ -177,6 +183,7 @@ static void decode_address(char *buf, unsigned long address)
sprintf(buf, "[ %s vma:0x%lx-0x%lx]",
name, vma->vm_start, vma->vm_end);
+ up_read(&mm->mmap_sem);
if (!in_atomic)
mmput(mm);
@@ -186,11 +193,16 @@ static void decode_address(char *buf, unsigned long address)
goto done;
}
}
+
+ up_read(&mm->mmap_sem);
if (!in_atomic)
mmput(mm);
}
- /* we were unable to find this address anywhere */
+ /*
+ * we were unable to find this address anywhere,
+ * or some MMs were skipped because they were in use.
+ */
sprintf(buf, "/* kernel dynamic memory */");
done: