Hi, On Thu, Mar 08, 2001 at 09:12:52PM +0100, Manfred Spraul wrote: > > > Fixing the bug is more difficult than I thought: > > Initially I assumed it would be a two-liner (lock, unlock) but kmap() > can sleep. > > Can I reuse a kmap_atomic() type or should I add a new type? I've just tried with the patch below and it seems fine. You don't need to hold the spinlock over the kmap() call: you only need to hold a reference to the page. Cheers, Stephen
--- linux-2.4.2-ac18/kernel/ptrace.c.~1~ Thu Nov 9 03:01:34 2000 +++ linux-2.4.2-ac18/kernel/ptrace.c Mon Mar 12 11:32:30 2001 @@ -28,6 +28,7 @@ struct page *page; repeat: + spin_lock(&mm->page_table_lock); pgdir = pgd_offset(vma->vm_mm, addr); if (pgd_none(*pgdir)) goto fault_in_page; @@ -47,9 +48,13 @@ /* ZERO_PAGE is special: reads from it are ok even though it's marked reserved */ if (page != ZERO_PAGE(addr) || write) { - if ((!VALID_PAGE(page)) || PageReserved(page)) + if ((!VALID_PAGE(page)) || PageReserved(page)) { + spin_unlock(&mm->page_table_lock); return 0; + } } + get_page(page); + spin_unlock(&mm->page_table_lock); flush_cache_page(vma, addr); if (write) { @@ -64,19 +69,23 @@ flush_page_to_ram(page); kunmap(page); } + put_page(page); return len; fault_in_page: + spin_unlock(&mm->page_table_lock); /* -1: out of memory. 0 - unmapped page */ if (handle_mm_fault(mm, vma, addr, write) > 0) goto repeat; return 0; bad_pgd: + spin_unlock(&mm->page_table_lock); pgd_ERROR(*pgdir); return 0; bad_pmd: + spin_unlock(&mm->page_table_lock); pmd_ERROR(*pgmiddle); return 0; }