On Thu, Feb 09, 2017 at 07:58:20PM +0300, Kirill A. Shutemov wrote: > I'll look into it. I ended up with this (I'll test it more later): void filemap_map_pages(struct vm_fault *vmf, pgoff_t start_pgoff, pgoff_t end_pgoff) { struct radix_tree_iter iter; void **slot; struct file *file = vmf->vma->vm_file; struct address_space *mapping = file->f_mapping; pgoff_t last_pgoff = start_pgoff; loff_t size; struct page *page; bool mapped; rcu_read_lock(); radix_tree_for_each_slot(slot, &mapping->page_tree, &iter, start_pgoff) { unsigned long index = iter.index; if (index < start_pgoff) index = start_pgoff; if (index > end_pgoff) break; repeat: page = radix_tree_deref_slot(slot); if (unlikely(!page)) continue; if (radix_tree_exception(page)) { if (radix_tree_deref_retry(page)) slot = radix_tree_iter_retry(&iter); continue; } if (!page_cache_get_speculative(page)) goto repeat; /* Has the page moved? */ if (unlikely(page != *slot)) { put_page(page); goto repeat; } /* For multi-order entries, find relevant subpage */ page = find_subpage(page, index); if (!PageUptodate(page) || PageReadahead(page)) goto skip; if (!trylock_page(page)) goto skip; if (page_mapping(page) != mapping || !PageUptodate(page)) goto skip_unlock; size = round_up(i_size_read(mapping->host), PAGE_SIZE); if (compound_head(page)->index >= size >> PAGE_SHIFT) goto skip_unlock; if (file->f_ra.mmap_miss > 0) file->f_ra.mmap_miss--; map_next_subpage: if (PageHWPoison(page)) goto next; vmf->address += (index - last_pgoff) << PAGE_SHIFT; if (vmf->pte) vmf->pte += index - last_pgoff; last_pgoff = index; mapped = !alloc_set_pte(vmf, NULL, page); /* Huge page is mapped or last index? No need to proceed. */ if (pmd_trans_huge(*vmf->pmd) || index == end_pgoff) { unlock_page(page); break; } next: if (page && PageCompound(page)) { /* Last subpage handled? */ if ((index & (compound_nr_pages(page) - 1)) == compound_nr_pages(page) - 1) goto skip_unlock; index++; page++; /* * One page reference goes to page table mapping. * Need additional reference, if last alloc_set_pte() * succeed. */ if (mapped) get_page(page); goto map_next_subpage; } skip_unlock: unlock_page(page); skip: iter.index = compound_head(page)->index + compound_nr_pages(page) - 1; /* Only give up reference if alloc_set_pte() failed. */ if (!mapped) put_page(page); } rcu_read_unlock(); } -- Kirill A. Shutemov