diff options
author | Matthew Wilcox <willy@infradead.org> | 2018-05-16 18:12:54 -0400 |
---|---|---|
committer | Matthew Wilcox <willy@infradead.org> | 2018-10-21 10:46:35 -0400 |
commit | a6906972fe67fb6f73ba04088f7897227fd1cd8f (patch) | |
tree | ae5e24910060321dcdbbae7c1096596f9baaa5c8 /mm/filemap.c | |
parent | 3ece58a270cd1e5026282abe778bd50db7a11d08 (diff) |
page cache; Convert find_get_pages_range_tag to XArray
The 'end' parameter of the xas_for_each iterator avoids a useless
iteration at the end of the range.
Signed-off-by: Matthew Wilcox <willy@infradead.org>
Diffstat (limited to 'mm/filemap.c')
-rw-r--r-- | mm/filemap.c | 68 |
1 files changed, 26 insertions, 42 deletions
diff --git a/mm/filemap.c b/mm/filemap.c index 089b67598100..0df28aa6411c 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
@@ -1789,74 +1789,58 @@ EXPORT_SYMBOL(find_get_pages_contig); | |||
1789 | * @tag. We update @index to index the next page for the traversal. | 1789 | * @tag. We update @index to index the next page for the traversal. |
1790 | */ | 1790 | */ |
1791 | unsigned find_get_pages_range_tag(struct address_space *mapping, pgoff_t *index, | 1791 | unsigned find_get_pages_range_tag(struct address_space *mapping, pgoff_t *index, |
1792 | pgoff_t end, int tag, unsigned int nr_pages, | 1792 | pgoff_t end, xa_mark_t tag, unsigned int nr_pages, |
1793 | struct page **pages) | 1793 | struct page **pages) |
1794 | { | 1794 | { |
1795 | struct radix_tree_iter iter; | 1795 | XA_STATE(xas, &mapping->i_pages, *index); |
1796 | void **slot; | 1796 | struct page *page; |
1797 | unsigned ret = 0; | 1797 | unsigned ret = 0; |
1798 | 1798 | ||
1799 | if (unlikely(!nr_pages)) | 1799 | if (unlikely(!nr_pages)) |
1800 | return 0; | 1800 | return 0; |
1801 | 1801 | ||
1802 | rcu_read_lock(); | 1802 | rcu_read_lock(); |
1803 | radix_tree_for_each_tagged(slot, &mapping->i_pages, &iter, *index, tag) { | 1803 | xas_for_each_marked(&xas, page, end, tag) { |
1804 | struct page *head, *page; | 1804 | struct page *head; |
1805 | 1805 | if (xas_retry(&xas, page)) | |
1806 | if (iter.index > end) | ||
1807 | break; | ||
1808 | repeat: | ||
1809 | page = radix_tree_deref_slot(slot); | ||
1810 | if (unlikely(!page)) | ||
1811 | continue; | 1806 | continue; |
1812 | 1807 | /* | |
1813 | if (radix_tree_exception(page)) { | 1808 | * Shadow entries should never be tagged, but this iteration |
1814 | if (radix_tree_deref_retry(page)) { | 1809 | * is lockless so there is a window for page reclaim to evict |
1815 | slot = radix_tree_iter_retry(&iter); | 1810 | * a page we saw tagged. Skip over it. |
1816 | continue; | 1811 | */ |
1817 | } | 1812 | if (xa_is_value(page)) |
1818 | /* | ||
1819 | * A shadow entry of a recently evicted page. | ||
1820 | * | ||
1821 | * Those entries should never be tagged, but | ||
1822 | * this tree walk is lockless and the tags are | ||
1823 | * looked up in bulk, one radix tree node at a | ||
1824 | * time, so there is a sizable window for page | ||
1825 | * reclaim to evict a page we saw tagged. | ||
1826 | * | ||
1827 | * Skip over it. | ||
1828 | */ | ||
1829 | continue; | 1813 | continue; |
1830 | } | ||
1831 | 1814 | ||
1832 | head = compound_head(page); | 1815 | head = compound_head(page); |
1833 | if (!page_cache_get_speculative(head)) | 1816 | if (!page_cache_get_speculative(head)) |
1834 | goto repeat; | 1817 | goto retry; |
1835 | 1818 | ||
1836 | /* The page was split under us? */ | 1819 | /* The page was split under us? */ |
1837 | if (compound_head(page) != head) { | 1820 | if (compound_head(page) != head) |
1838 | put_page(head); | 1821 | goto put_page; |
1839 | goto repeat; | ||
1840 | } | ||
1841 | 1822 | ||
1842 | /* Has the page moved? */ | 1823 | /* Has the page moved? */ |
1843 | if (unlikely(page != *slot)) { | 1824 | if (unlikely(page != xas_reload(&xas))) |
1844 | put_page(head); | 1825 | goto put_page; |
1845 | goto repeat; | ||
1846 | } | ||
1847 | 1826 | ||
1848 | pages[ret] = page; | 1827 | pages[ret] = page; |
1849 | if (++ret == nr_pages) { | 1828 | if (++ret == nr_pages) { |
1850 | *index = pages[ret - 1]->index + 1; | 1829 | *index = page->index + 1; |
1851 | goto out; | 1830 | goto out; |
1852 | } | 1831 | } |
1832 | continue; | ||
1833 | put_page: | ||
1834 | put_page(head); | ||
1835 | retry: | ||
1836 | xas_reset(&xas); | ||
1853 | } | 1837 | } |
1854 | 1838 | ||
1855 | /* | 1839 | /* |
1856 | * We come here when we got at @end. We take care to not overflow the | 1840 | * We come here when we got to @end. We take care to not overflow the |
1857 | * index @index as it confuses some of the callers. This breaks the | 1841 | * index @index as it confuses some of the callers. This breaks the |
1858 | * iteration when there is page at index -1 but that is already broken | 1842 | * iteration when there is a page at index -1 but that is already |
1859 | * anyway. | 1843 | * broken anyway. |
1860 | */ | 1844 | */ |
1861 | if (end == (pgoff_t)-1) | 1845 | if (end == (pgoff_t)-1) |
1862 | *index = (pgoff_t)-1; | 1846 | *index = (pgoff_t)-1; |