diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-09-06 23:49:49 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-09-06 23:49:49 -0400 |
commit | d34fc1adf01ff87026da85fb972dc259dc347540 (patch) | |
tree | 27356073d423187157b7cdb69da32b53102fb9e7 /mm/filemap.c | |
parent | 1c9fe4409ce3e9c78b1ed96ee8ed699d4f03bf33 (diff) | |
parent | d2cd9ede6e193dd7d88b6d27399e96229a551b19 (diff) |
Merge branch 'akpm' (patches from Andrew)
Merge updates from Andrew Morton:
- various misc bits
- DAX updates
- OCFS2
- most of MM
* emailed patches from Andrew Morton <akpm@linux-foundation.org>: (119 commits)
mm,fork: introduce MADV_WIPEONFORK
x86,mpx: make mpx depend on x86-64 to free up VMA flag
mm: add /proc/pid/smaps_rollup
mm: hugetlb: clear target sub-page last when clearing huge page
mm: oom: let oom_reap_task and exit_mmap run concurrently
swap: choose swap device according to numa node
mm: replace TIF_MEMDIE checks by tsk_is_oom_victim
mm, oom: do not rely on TIF_MEMDIE for memory reserves access
z3fold: use per-cpu unbuddied lists
mm, swap: don't use VMA based swap readahead if HDD is used as swap
mm, swap: add sysfs interface for VMA based swap readahead
mm, swap: VMA based swap readahead
mm, swap: fix swap readahead marking
mm, swap: add swap readahead hit statistics
mm/vmalloc.c: don't reinvent the wheel but use existing llist API
mm/vmstat.c: fix wrong comment
selftests/memfd: add memfd_create hugetlbfs selftest
mm/shmem: add hugetlbfs support to memfd_create()
mm, devm_memremap_pages: use multi-order radix for ZONE_DEVICE lookups
mm/vmalloc.c: halve the number of comparisons performed in pcpu_get_vm_areas()
...
Diffstat (limited to 'mm/filemap.c')
-rw-r--r-- | mm/filemap.c | 67 |
1 files changed, 39 insertions, 28 deletions
diff --git a/mm/filemap.c b/mm/filemap.c index 1e01cb6e5173..9d21afd692b9 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
@@ -130,17 +130,8 @@ static int page_cache_tree_insert(struct address_space *mapping, | |||
130 | return -EEXIST; | 130 | return -EEXIST; |
131 | 131 | ||
132 | mapping->nrexceptional--; | 132 | mapping->nrexceptional--; |
133 | if (!dax_mapping(mapping)) { | 133 | if (shadowp) |
134 | if (shadowp) | 134 | *shadowp = p; |
135 | *shadowp = p; | ||
136 | } else { | ||
137 | /* DAX can replace empty locked entry with a hole */ | ||
138 | WARN_ON_ONCE(p != | ||
139 | dax_radix_locked_entry(0, RADIX_DAX_EMPTY)); | ||
140 | /* Wakeup waiters for exceptional entry lock */ | ||
141 | dax_wake_mapping_entry_waiter(mapping, page->index, p, | ||
142 | true); | ||
143 | } | ||
144 | } | 135 | } |
145 | __radix_tree_replace(&mapping->page_tree, node, slot, page, | 136 | __radix_tree_replace(&mapping->page_tree, node, slot, page, |
146 | workingset_update_node, mapping); | 137 | workingset_update_node, mapping); |
@@ -402,8 +393,7 @@ bool filemap_range_has_page(struct address_space *mapping, | |||
402 | { | 393 | { |
403 | pgoff_t index = start_byte >> PAGE_SHIFT; | 394 | pgoff_t index = start_byte >> PAGE_SHIFT; |
404 | pgoff_t end = end_byte >> PAGE_SHIFT; | 395 | pgoff_t end = end_byte >> PAGE_SHIFT; |
405 | struct pagevec pvec; | 396 | struct page *page; |
406 | bool ret; | ||
407 | 397 | ||
408 | if (end_byte < start_byte) | 398 | if (end_byte < start_byte) |
409 | return false; | 399 | return false; |
@@ -411,12 +401,10 @@ bool filemap_range_has_page(struct address_space *mapping, | |||
411 | if (mapping->nrpages == 0) | 401 | if (mapping->nrpages == 0) |
412 | return false; | 402 | return false; |
413 | 403 | ||
414 | pagevec_init(&pvec, 0); | 404 | if (!find_get_pages_range(mapping, &index, end, 1, &page)) |
415 | if (!pagevec_lookup(&pvec, mapping, index, 1)) | ||
416 | return false; | 405 | return false; |
417 | ret = (pvec.pages[0]->index <= end); | 406 | put_page(page); |
418 | pagevec_release(&pvec); | 407 | return true; |
419 | return ret; | ||
420 | } | 408 | } |
421 | EXPORT_SYMBOL(filemap_range_has_page); | 409 | EXPORT_SYMBOL(filemap_range_has_page); |
422 | 410 | ||
@@ -1564,23 +1552,29 @@ export: | |||
1564 | } | 1552 | } |
1565 | 1553 | ||
1566 | /** | 1554 | /** |
1567 | * find_get_pages - gang pagecache lookup | 1555 | * find_get_pages_range - gang pagecache lookup |
1568 | * @mapping: The address_space to search | 1556 | * @mapping: The address_space to search |
1569 | * @start: The starting page index | 1557 | * @start: The starting page index |
1558 | * @end: The final page index (inclusive) | ||
1570 | * @nr_pages: The maximum number of pages | 1559 | * @nr_pages: The maximum number of pages |
1571 | * @pages: Where the resulting pages are placed | 1560 | * @pages: Where the resulting pages are placed |
1572 | * | 1561 | * |
1573 | * find_get_pages() will search for and return a group of up to | 1562 | * find_get_pages_range() will search for and return a group of up to @nr_pages |
1574 | * @nr_pages pages in the mapping. The pages are placed at @pages. | 1563 | * pages in the mapping starting at index @start and up to index @end |
1575 | * find_get_pages() takes a reference against the returned pages. | 1564 | * (inclusive). The pages are placed at @pages. find_get_pages_range() takes |
1565 | * a reference against the returned pages. | ||
1576 | * | 1566 | * |
1577 | * The search returns a group of mapping-contiguous pages with ascending | 1567 | * The search returns a group of mapping-contiguous pages with ascending |
1578 | * indexes. There may be holes in the indices due to not-present pages. | 1568 | * indexes. There may be holes in the indices due to not-present pages. |
1569 | * We also update @start to index the next page for the traversal. | ||
1579 | * | 1570 | * |
1580 | * find_get_pages() returns the number of pages which were found. | 1571 | * find_get_pages_range() returns the number of pages which were found. If this |
1572 | * number is smaller than @nr_pages, the end of specified range has been | ||
1573 | * reached. | ||
1581 | */ | 1574 | */ |
1582 | unsigned find_get_pages(struct address_space *mapping, pgoff_t start, | 1575 | unsigned find_get_pages_range(struct address_space *mapping, pgoff_t *start, |
1583 | unsigned int nr_pages, struct page **pages) | 1576 | pgoff_t end, unsigned int nr_pages, |
1577 | struct page **pages) | ||
1584 | { | 1578 | { |
1585 | struct radix_tree_iter iter; | 1579 | struct radix_tree_iter iter; |
1586 | void **slot; | 1580 | void **slot; |
@@ -1590,8 +1584,11 @@ unsigned find_get_pages(struct address_space *mapping, pgoff_t start, | |||
1590 | return 0; | 1584 | return 0; |
1591 | 1585 | ||
1592 | rcu_read_lock(); | 1586 | rcu_read_lock(); |
1593 | radix_tree_for_each_slot(slot, &mapping->page_tree, &iter, start) { | 1587 | radix_tree_for_each_slot(slot, &mapping->page_tree, &iter, *start) { |
1594 | struct page *head, *page; | 1588 | struct page *head, *page; |
1589 | |||
1590 | if (iter.index > end) | ||
1591 | break; | ||
1595 | repeat: | 1592 | repeat: |
1596 | page = radix_tree_deref_slot(slot); | 1593 | page = radix_tree_deref_slot(slot); |
1597 | if (unlikely(!page)) | 1594 | if (unlikely(!page)) |
@@ -1627,11 +1624,25 @@ repeat: | |||
1627 | } | 1624 | } |
1628 | 1625 | ||
1629 | pages[ret] = page; | 1626 | pages[ret] = page; |
1630 | if (++ret == nr_pages) | 1627 | if (++ret == nr_pages) { |
1631 | break; | 1628 | *start = pages[ret - 1]->index + 1; |
1629 | goto out; | ||
1630 | } | ||
1632 | } | 1631 | } |
1633 | 1632 | ||
1633 | /* | ||
1634 | * We come here when there is no page beyond @end. We take care to not | ||
1635 | * overflow the index @start as it confuses some of the callers. This | ||
1636 | * breaks the iteration when there is page at index -1 but that is | ||
1637 | * already broken anyway. | ||
1638 | */ | ||
1639 | if (end == (pgoff_t)-1) | ||
1640 | *start = (pgoff_t)-1; | ||
1641 | else | ||
1642 | *start = end + 1; | ||
1643 | out: | ||
1634 | rcu_read_unlock(); | 1644 | rcu_read_unlock(); |
1645 | |||
1635 | return ret; | 1646 | return ret; |
1636 | } | 1647 | } |
1637 | 1648 | ||