aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorPaolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>2005-11-13 19:07:04 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-11-13 21:14:14 -0500
commitcbc24afa82106b67df804cb434739e4382eecd9a (patch)
treee89a253539f50ea324754af3f75515d19413b48f /arch
parent2ab23c95a0b77d45dc764dd4aed48fe6e8906e59 (diff)
[PATCH] uml: remove bogus WARN_ON, triggerable harmlessly on a page fault race
The below warning was added in place of pte_mkyoung(); if (is_write) pte_mkdirty(); In fact, if the PTE is not marked young/dirty, our dirty/accessed bit emulation would cause the TLB permission not to be changed, and so we'd loop, and given we don't support preemption yet, we'd busy-hang here. However, I've seen this warning trigger without crashes during a loop of concurrent kernel builds, at random times (i.e. like a race condition), and I realized that two concurrent faults on the same page, one on read and one on write, can trigger it. The read fault gets serviced and the PTE gets marked writable but clean (it's possible on a shared-writable mapping), while the generic code sees the PTE was already installed and returns without action. In this case, we'll see another fault and service it normally. Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it> Acked-by: Jeff Dike <jdike@addtoit.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/um/kernel/trap_kern.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c
index 95c8f8733baf..0d4c10a73607 100644
--- a/arch/um/kernel/trap_kern.c
+++ b/arch/um/kernel/trap_kern.c
@@ -95,7 +95,16 @@ survive:
95 pte = pte_offset_kernel(pmd, address); 95 pte = pte_offset_kernel(pmd, address);
96 } while(!pte_present(*pte)); 96 } while(!pte_present(*pte));
97 err = 0; 97 err = 0;
98 /* The below warning was added in place of
99 * pte_mkyoung(); if (is_write) pte_mkdirty();
100 * If it's triggered, we'd see normally a hang here (a clean pte is
101 * marked read-only to emulate the dirty bit).
102 * However, the generic code can mark a PTE writable but clean on a
103 * concurrent read fault, triggering this harmlessly. So comment it out.
104 */
105#if 0
98 WARN_ON(!pte_young(*pte) || (is_write && !pte_dirty(*pte))); 106 WARN_ON(!pte_young(*pte) || (is_write && !pte_dirty(*pte)));
107#endif
99 flush_tlb_page(vma, address); 108 flush_tlb_page(vma, address);
100out: 109out:
101 up_read(&mm->mmap_sem); 110 up_read(&mm->mmap_sem);