Blackfin: fix up mm locking in address dumping
authorGraf Yang <graf.yang@analog.com>
Wed, 13 Jan 2010 06:09:34 +0000 (06:09 +0000)
committerMike Frysinger <vapier@gentoo.org>
Tue, 9 Mar 2010 05:30:49 +0000 (00:30 -0500)
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>
arch/blackfin/kernel/traps.c

index 870d74b1b407197f02a8243634253b378ae004bd..85766805b03a67eba195e4bb281ce35d5061c967 100644 (file)
@@ -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: