--- include/linux/mm.h | 2 +- mm/filemap.c | 2 +- mm/memory.c | 24 +++++++++++++----------- mm/migrate.c | 1 + 4 files changed, 16 insertions(+), 13 deletions(-) Index: linux-2.6/mm/filemap.c =================================================================== --- linux-2.6.orig/mm/filemap.c 2007-09-10 18:13:06.000000000 -0700 +++ linux-2.6/mm/filemap.c 2007-09-10 18:22:23.000000000 -0700 @@ -1322,7 +1322,7 @@ int filemap_fault(struct vm_area_struct int ret = 0; pgoff_t pgoff = vmf->pgoff >> mapping_order(mapping); - vmf->base_page_index = + vmf->page_index = vmf->pgoff & ((1 << mapping_order(mapping)) -1); size = page_cache_next(mapping, i_size_read(inode)); if (pgoff >= size) Index: linux-2.6/mm/memory.c =================================================================== --- linux-2.6.orig/mm/memory.c 2007-09-10 18:18:57.000000000 -0700 +++ linux-2.6/mm/memory.c 2007-09-10 18:24:52.000000000 -0700 @@ -646,11 +646,10 @@ static unsigned long zap_pte_range(struc (*zap_work) -= PAGE_SIZE; if (pte_present(ptent)) { - struct page *spage; int page_index = 0; - int index; + int index = 0; + struct page *page = vm_normal_page(vma, addr, ptent); - page = vm_normal_page(vma, addr, ptent); if (page) { struct page *p = page_cache_head(page); @@ -658,6 +657,7 @@ static unsigned long zap_pte_range(struc page = p; } index = page->index << page_cache_order(page) + page_index; + if (unlikely(details) && page) { /* * unmap_shared_mapping_pages() wants to @@ -914,7 +914,9 @@ unsigned long zap_page_range(struct vm_a /* * Do a quick page-table lookup for a single page. * - * This may return a tail page. + * follow_page() may return a tail page. However, the reference count + * is taken on the head page. The head page must be determined + * to drop the refcount again. */ struct page *follow_page(struct vm_area_struct *vma, unsigned long address, unsigned int flags) @@ -1657,7 +1659,7 @@ static int do_wp_page(struct mm_struct * { struct page *old_page, *new_page; pte_t entry; - int reuse = 0, ret = 0, subpage_index = 0; + int reuse = 0, ret = 0, page_index = 0; struct page *dirty_page = NULL; old_page = vm_normal_page(vma, address, orig_pte); @@ -1667,7 +1669,7 @@ static int do_wp_page(struct mm_struct * if (PageTail(old_page)) { struct page *head = page_cache_head(old_page); - subpage_index = old_page - head; + page_index = old_page - head; old_page = head; } @@ -1748,7 +1750,7 @@ gotten: new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, address); if (!new_page) goto oom; - cow_user_page(new_page, old_page + subpage_index, + cow_user_page(new_page, old_page + page_index, address, vma); } @@ -2353,7 +2355,7 @@ static int __do_fault(struct mm_struct * vmf.pgoff = pgoff; vmf.flags = flags; vmf.page = NULL; - vmf.base_page_index = 0; + vmf.page_index = 0; pte_unmap(page_table); BUG_ON(vma->vm_flags & VM_PFNMAP); @@ -2400,7 +2402,7 @@ static int __do_fault(struct mm_struct * goto out; } copy_user_highpage(page, - vmf.page + vmf.base_page_index, address, vma); + vmf.page + vmf.page_index, address, vma); } else { /* * If the page will be shareable, see if the backing @@ -2446,8 +2448,8 @@ static int __do_fault(struct mm_struct * */ /* Only go through if we didn't race with anybody else... */ if (likely(pte_same(*page_table, orig_pte))) { - flush_icache_page(vma, page + vmf.base_page_index); - entry = mk_pte(page + vmf.base_page_index, vma->vm_page_prot); + flush_icache_page(vma, page + vmf.page_index); + entry = mk_pte(page + vmf.page_index, vma->vm_page_prot); if (flags & FAULT_FLAG_WRITE) entry = maybe_mkwrite(pte_mkdirty(entry), vma); set_pte_at(mm, address, page_table, entry); Index: linux-2.6/include/linux/mm.h =================================================================== --- linux-2.6.orig/include/linux/mm.h 2007-09-10 18:13:06.000000000 -0700 +++ linux-2.6/include/linux/mm.h 2007-09-10 18:22:23.000000000 -0700 @@ -216,7 +216,7 @@ struct vm_fault { * is set (which is also implied by * VM_FAULT_ERROR). */ - int base_page_index; + int page_index; }; /* Index: linux-2.6/mm/migrate.c =================================================================== --- linux-2.6.orig/mm/migrate.c 2007-09-10 16:53:20.000000000 -0700 +++ linux-2.6/mm/migrate.c 2007-09-10 18:22:23.000000000 -0700 @@ -826,6 +826,7 @@ static int do_move_pages(struct mm_struc if (!page) goto set_status; + page = page_cache_head(page); if (PageReserved(page)) /* Check for zero page */ goto put_and_set;