mm/filemap.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/mm/filemap.c b/mm/filemap.c index 42d7a58e3a14..74384f9f1776 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -3022,6 +3022,8 @@ vm_fault_t filemap_map_pages(struct vm_fault *vmf, unsigned long address, struct page *head, *page; unsigned int mmap_miss = READ_ONCE(file->f_ra.mmap_miss); vm_fault_t ret = 0; + pte_t *orig_pte; + unsigned long orig_address; rcu_read_lock(); head = first_map_page(vmf, &xas, end_pgoff); @@ -3037,6 +3039,14 @@ vm_fault_t filemap_map_pages(struct vm_fault *vmf, unsigned long address, vmf->pte = pte_offset_map_lock(vma->vm_mm, vmf->pmd, vmf->address, &vmf->ptl); + + /* + * Disgusting - we should not update vmf->pte and ->address, + * but do_set_pte() needs it + */ + orig_pte = vmf->pte; + orig_address = vmf->address; + do { page = find_subpage(head, xas.xa_index); if (PageHWPoison(page)) @@ -3066,6 +3076,10 @@ vm_fault_t filemap_map_pages(struct vm_fault *vmf, unsigned long address, unlock_page(head); put_page(head); } while ((head = next_map_page(vmf, &xas, end_pgoff)) != NULL); + + /* Hackety hack - reset the vmf state back */ + vmf->pte = orig_pte; + vmf->address = orig_address; pte_unmap_unlock(vmf->pte, vmf->ptl); rcu_read_unlock(); WRITE_ONCE(file->f_ra.mmap_miss, mmap_miss);