linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
* [Bug 2219] New: kernel BUG at mm/rmap.c:306
@ 2004-02-28 15:44 Martin J. Bligh
  2004-03-07  1:53 ` [PATCH] [Bug 2219] " Hugh Dickins
  0 siblings, 1 reply; 2+ messages in thread
From: Martin J. Bligh @ 2004-02-28 15:44 UTC (permalink / raw)
  To: linux-kernel, linux-mm mailing list; +Cc: castetm

           Summary: kernel BUG at mm/rmap.c:306
    Kernel Version: 2.6.3
            Status: NEW
          Severity: high
             Owner: akpm@digeo.com
         Submitter: castetm@ensimag.imag.fr


Distribution: gentoo
Hardware Environment:pentium-3/512 Mo RAM

I have try overcommit-accounting with strict overcommit, but when i launch a
program like [1], there was a kernel bug [2]


[1]
int main()
{
        while(fork() != -1) {}
        while(malloc(1024)) {}
        while(1) {}
}
------------------------------------------------
[2]
Out of Memory: Killed process 8289 (a.out).
Out of Memory: Killed process 8297 (a.out).
swap_free: Bad swap offset entry 001c2790
------------[ cut here ]------------
kernel BUG at mm/rmap.c:306!
invalid operand: 0000 [#1]
CPU:    0
EIP:    0060:[<c014baf0>]    Not tainted
EFLAGS: 00010246
EIP is at try_to_unmap_one+0x1e0/0x1f0
eax: 00000000   ebx: 000c0000   ecx: 00000009   edx: c1000000
esi: c14662e8   edi: df55e300   ebp: c14662e8   esp: dfa99d48
ds: 007b   es: 007b   ss: 0068
Process kswapd0 (pid: 8, threadinfo=dfa98000 task=dfa9eca0)
Stack: df55e300 00000009 1c279005 00000000 00000000 00000004 c14662e8 da675ac0
       00000000 c014bbab d4a5d440 00000004 00000000 da675ac0 00000000 c14662e8
       00000001 dfa98000 c0142554 c1416c20 dfa99db8 c036a6f4 dfa98000 00000028
Call Trace:
 [<c014bbab>] try_to_unmap+0xab/0x160
 [<c0142554>] shrink_list+0x224/0x560
 [<c0142a30>] shrink_cache+0x1a0/0x320
 [<c0143243>] shrink_zone+0x83/0xb0
 [<c014365a>] balance_pgdat+0x19a/0x220
 [<c01437f5>] kswapd+0x115/0x130
 [<c011d7e0>] autoremove_wake_function+0x0/0x50
 [<c0109302>] ret_from_fork+0x6/0x14
 [<c011d7e0>] autoremove_wake_function+0x0/0x50
 [<c01436e0>] kswapd+0x0/0x130
 [<c01072a5>] kernel_thread_helper+0x5/0x10

Code: 0f 0b 32 01 13 c0 32 c0 e9 78 fe ff ff 8d 76 00 55 57 56 89
 <6>note: kswapd0[8] exited with preempt_count 2
Out of Memory: Killed process 12353 (a.out).


--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>

^ permalink raw reply	[flat|nested] 2+ messages in thread

* [PATCH] [Bug 2219] kernel BUG at mm/rmap.c:306
  2004-02-28 15:44 [Bug 2219] New: kernel BUG at mm/rmap.c:306 Martin J. Bligh
@ 2004-03-07  1:53 ` Hugh Dickins
  0 siblings, 0 replies; 2+ messages in thread
From: Hugh Dickins @ 2004-03-07  1:53 UTC (permalink / raw)
  To: Andrew Morton; +Cc: Matthieu Castet, mulix, linux-kernel, linux-mm

fork's dup_mmap leaves child mm_rb as copied from parent mm while doing
all the copy_page_ranges, and then calls build_mmap_rb without holding
page_table_lock.  try_to_unmap_one's find_vma (holding page_table_lock
not mmap_sem) coming on another cpu may cause mm mayhem.  It may leave
the child's mmap_cache pointing to a vma of the parent mm.  When parent
exits and child faults, quite what happens rather depends on what junk
then inhabits vm_page_prot, which gets set in the page table, with
page_add_rmap adding the ptep, but junk pte likely to fail the tests
for page_remove_rmap.  Eventually child exits, page table is freed,
try_to_unmap_one oopses on null ptep_to_mm (but in a kernel with rss
limiting, usually page_referenced hits the null ptep_to_mm first).

This took me days and days to unravel!
Big thanks to Matthieu for reporting it with a good test case.
Patch below against 2.6.4-rc2, in case you want to rush it to Linus.
Sorry, I've not updated the Bugzilla 2219 entry at all.

Hugh

--- 2.6.4-rc2/include/linux/mm.h	2004-03-04 12:05:05.000000000 +0000
+++ linux/include/linux/mm.h	2004-03-06 22:13:56.829496520 +0000
@@ -530,7 +530,8 @@
 
 /* mmap.c */
 extern void insert_vm_struct(struct mm_struct *, struct vm_area_struct *);
-extern void build_mmap_rb(struct mm_struct *);
+extern void __vma_link_rb(struct mm_struct *, struct vm_area_struct *,
+	struct rb_node **, struct rb_node *);
 extern void exit_mmap(struct mm_struct *);
 
 extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
--- 2.6.4-rc2/kernel/fork.c	2004-03-04 12:05:06.000000000 +0000
+++ linux/kernel/fork.c	2004-03-06 22:13:56.865491048 +0000
@@ -265,6 +265,7 @@
 static inline int dup_mmap(struct mm_struct * mm, struct mm_struct * oldmm)
 {
 	struct vm_area_struct * mpnt, *tmp, **pprev;
+	struct rb_node **rb_link, *rb_parent;
 	int retval;
 	unsigned long charge = 0;
 
@@ -277,6 +278,9 @@
 	mm->map_count = 0;
 	mm->rss = 0;
 	cpus_clear(mm->cpu_vm_mask);
+	mm->mm_rb = RB_ROOT;
+	rb_link = &mm->mm_rb.rb_node;
+	rb_parent = NULL;
 	pprev = &mm->mmap;
 
 	/*
@@ -324,11 +328,17 @@
 
 		/*
 		 * Link in the new vma and copy the page table entries:
-		 * link in first so that swapoff can see swap entries.
+		 * link in first so that swapoff can see swap entries,
+		 * and try_to_unmap_one's find_vma find the new vma.
 		 */
 		spin_lock(&mm->page_table_lock);
 		*pprev = tmp;
 		pprev = &tmp->vm_next;
+
+		__vma_link_rb(mm, tmp, rb_link, rb_parent);
+		rb_link = &tmp->vm_rb.rb_right;
+		rb_parent = &tmp->vm_rb;
+
 		mm->map_count++;
 		retval = copy_page_range(mm, current->mm, tmp);
 		spin_unlock(&mm->page_table_lock);
@@ -340,7 +350,6 @@
 			goto fail;
 	}
 	retval = 0;
-	build_mmap_rb(mm);
 
 out:
 	flush_tlb_mm(current->mm);
--- 2.6.4-rc2/mm/mmap.c	2004-03-04 12:05:07.000000000 +0000
+++ linux/mm/mmap.c	2004-03-06 22:13:56.912483904 +0000
@@ -222,8 +222,8 @@
 	}
 }
 
-static void __vma_link_rb(struct mm_struct *mm, struct vm_area_struct *vma,
-			struct rb_node **rb_link, struct rb_node *rb_parent)
+void __vma_link_rb(struct mm_struct *mm, struct vm_area_struct *vma,
+		struct rb_node **rb_link, struct rb_node *rb_parent)
 {
 	rb_link_node(&vma->vm_rb, rb_parent, rb_link);
 	rb_insert_color(&vma->vm_rb, &mm->mm_rb);
@@ -1404,22 +1404,6 @@
 
 EXPORT_SYMBOL(do_brk);
 
-/* Build the RB tree corresponding to the VMA list. */
-void build_mmap_rb(struct mm_struct * mm)
-{
-	struct vm_area_struct * vma;
-	struct rb_node ** rb_link, * rb_parent;
-
-	mm->mm_rb = RB_ROOT;
-	rb_link = &mm->mm_rb.rb_node;
-	rb_parent = NULL;
-	for (vma = mm->mmap; vma; vma = vma->vm_next) {
-		__vma_link_rb(mm, vma, rb_link, rb_parent);
-		rb_parent = &vma->vm_rb;
-		rb_link = &rb_parent->rb_right;
-	}
-}
-
 /* Release all mmaps. */
 void exit_mmap(struct mm_struct *mm)
 {

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2004-03-07  1:53 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-02-28 15:44 [Bug 2219] New: kernel BUG at mm/rmap.c:306 Martin J. Bligh
2004-03-07  1:53 ` [PATCH] [Bug 2219] " Hugh Dickins

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox