Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1579796
| From | "Kirill A. Shutemov" <kirill@shutemov.name> |
|---|---|
| Newsgroups | linux.kernel |
| Subject | Re: [PATCHv6 01/37] mm, shmem: swich huge tmpfs to multi-order radix-tree entries |
| Date | 2017-02-13 14:50 +0100 |
| Message-ID | <tapaW-4mz-13@gated-at.bofh.it> (permalink) |
| References | <t3QSB-6QS-5@gated-at.bofh.it> <t3R2j-79n-49@gated-at.bofh.it> <t8O3M-Pu-5@gated-at.bofh.it> <t90eC-98-23@gated-at.bofh.it> |
| Organization | linux.* mail to news gateway |
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
Back to linux.kernel | Previous | Next — Previous in thread | Find similar | Unroll thread
Re: [PATCHv6 01/37] mm, shmem: swich huge tmpfs to multi-order radix-tree entries Matthew Wilcox <willy@infradead.org> - 2017-02-09 05:00 +0100
Re: [PATCHv6 01/37] mm, shmem: swich huge tmpfs to multi-order radix-tree entries "Kirill A. Shutemov" <kirill@shutemov.name> - 2017-02-09 18:00 +0100
Re: [PATCHv6 01/37] mm, shmem: swich huge tmpfs to multi-order radix-tree entries "Kirill A. Shutemov" <kirill@shutemov.name> - 2017-02-13 14:50 +0100
csiph-web