diff options
author | Matthew Wilcox <willy@infradead.org> | 2019-05-13 20:16:44 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-05-14 12:47:45 -0400 |
commit | 5fd4ca2d84b249f0858ce28cf637cf25b61a398f (patch) | |
tree | a7660b8f5f9fa02945070e2ab918eb645c92ba36 /mm/filemap.c | |
parent | cefdca0a86be517bc390fc4541e3674b8e7803b0 (diff) |
mm: page cache: store only head pages in i_pages
Transparent Huge Pages are currently stored in i_pages as pointers to
consecutive subpages. This patch changes that to storing consecutive
pointers to the head page in preparation for storing huge pages more
efficiently in i_pages.
Large parts of this are "inspired" by Kirill's patch
https://lore.kernel.org/lkml/20170126115819.58875-2-kirill.shutemov@linux.intel.com/
[willy@infradead.org: fix swapcache pages]
Link: http://lkml.kernel.org/r/20190324155441.GF10344@bombadil.infradead.org
[kirill@shutemov.name: hugetlb stores pages in page cache differently]
Link: http://lkml.kernel.org/r/20190404134553.vuvhgmghlkiw2hgl@kshutemo-mobl1
Link: http://lkml.kernel.org/r/20190307153051.18815-1-willy@infradead.org
Signed-off-by: Matthew Wilcox <willy@infradead.org>
Acked-by: Jan Kara <jack@suse.cz>
Reviewed-by: Kirill Shutemov <kirill@shutemov.name>
Reviewed-and-tested-by: Song Liu <songliubraving@fb.com>
Tested-by: William Kucharski <william.kucharski@oracle.com>
Reviewed-by: William Kucharski <william.kucharski@oracle.com>
Tested-by: Qian Cai <cai@lca.pw>
Cc: Hugh Dickins <hughd@google.com>
Cc: Song Liu <liu.song.a23@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/filemap.c')
-rw-r--r-- | mm/filemap.c | 159 |
1 files changed, 62 insertions, 97 deletions
diff --git a/mm/filemap.c b/mm/filemap.c index d78f577baef2..4157f858a9c6 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
@@ -279,11 +279,11 @@ EXPORT_SYMBOL(delete_from_page_cache); | |||
279 | * @pvec: pagevec with pages to delete | 279 | * @pvec: pagevec with pages to delete |
280 | * | 280 | * |
281 | * The function walks over mapping->i_pages and removes pages passed in @pvec | 281 | * The function walks over mapping->i_pages and removes pages passed in @pvec |
282 | * from the mapping. The function expects @pvec to be sorted by page index. | 282 | * from the mapping. The function expects @pvec to be sorted by page index |
283 | * and is optimised for it to be dense. | ||
283 | * It tolerates holes in @pvec (mapping entries at those indices are not | 284 | * It tolerates holes in @pvec (mapping entries at those indices are not |
284 | * modified). The function expects only THP head pages to be present in the | 285 | * modified). The function expects only THP head pages to be present in the |
285 | * @pvec and takes care to delete all corresponding tail pages from the | 286 | * @pvec. |
286 | * mapping as well. | ||
287 | * | 287 | * |
288 | * The function expects the i_pages lock to be held. | 288 | * The function expects the i_pages lock to be held. |
289 | */ | 289 | */ |
@@ -292,40 +292,44 @@ static void page_cache_delete_batch(struct address_space *mapping, | |||
292 | { | 292 | { |
293 | XA_STATE(xas, &mapping->i_pages, pvec->pages[0]->index); | 293 | XA_STATE(xas, &mapping->i_pages, pvec->pages[0]->index); |
294 | int total_pages = 0; | 294 | int total_pages = 0; |
295 | int i = 0, tail_pages = 0; | 295 | int i = 0; |
296 | struct page *page; | 296 | struct page *page; |
297 | 297 | ||
298 | mapping_set_update(&xas, mapping); | 298 | mapping_set_update(&xas, mapping); |
299 | xas_for_each(&xas, page, ULONG_MAX) { | 299 | xas_for_each(&xas, page, ULONG_MAX) { |
300 | if (i >= pagevec_count(pvec) && !tail_pages) | 300 | if (i >= pagevec_count(pvec)) |
301 | break; | 301 | break; |
302 | |||
303 | /* A swap/dax/shadow entry got inserted? Skip it. */ | ||
302 | if (xa_is_value(page)) | 304 | if (xa_is_value(page)) |
303 | continue; | 305 | continue; |
304 | if (!tail_pages) { | 306 | /* |
305 | /* | 307 | * A page got inserted in our range? Skip it. We have our |
306 | * Some page got inserted in our range? Skip it. We | 308 | * pages locked so they are protected from being removed. |
307 | * have our pages locked so they are protected from | 309 | * If we see a page whose index is higher than ours, it |
308 | * being removed. | 310 | * means our page has been removed, which shouldn't be |
309 | */ | 311 | * possible because we're holding the PageLock. |
310 | if (page != pvec->pages[i]) { | 312 | */ |
311 | VM_BUG_ON_PAGE(page->index > | 313 | if (page != pvec->pages[i]) { |
312 | pvec->pages[i]->index, page); | 314 | VM_BUG_ON_PAGE(page->index > pvec->pages[i]->index, |
313 | continue; | 315 | page); |
314 | } | 316 | continue; |
315 | WARN_ON_ONCE(!PageLocked(page)); | 317 | } |
316 | if (PageTransHuge(page) && !PageHuge(page)) | 318 | |
317 | tail_pages = HPAGE_PMD_NR - 1; | 319 | WARN_ON_ONCE(!PageLocked(page)); |
320 | |||
321 | if (page->index == xas.xa_index) | ||
318 | page->mapping = NULL; | 322 | page->mapping = NULL; |
319 | /* | 323 | /* Leave page->index set: truncation lookup relies on it */ |
320 | * Leave page->index set: truncation lookup relies | 324 | |
321 | * upon it | 325 | /* |
322 | */ | 326 | * Move to the next page in the vector if this is a regular |
327 | * page or the index is of the last sub-page of this compound | ||
328 | * page. | ||
329 | */ | ||
330 | if (page->index + (1UL << compound_order(page)) - 1 == | ||
331 | xas.xa_index) | ||
323 | i++; | 332 | i++; |
324 | } else { | ||
325 | VM_BUG_ON_PAGE(page->index + HPAGE_PMD_NR - tail_pages | ||
326 | != pvec->pages[i]->index, page); | ||
327 | tail_pages--; | ||
328 | } | ||
329 | xas_store(&xas, NULL); | 333 | xas_store(&xas, NULL); |
330 | total_pages++; | 334 | total_pages++; |
331 | } | 335 | } |
@@ -1491,7 +1495,7 @@ EXPORT_SYMBOL(page_cache_prev_miss); | |||
1491 | struct page *find_get_entry(struct address_space *mapping, pgoff_t offset) | 1495 | struct page *find_get_entry(struct address_space *mapping, pgoff_t offset) |
1492 | { | 1496 | { |
1493 | XA_STATE(xas, &mapping->i_pages, offset); | 1497 | XA_STATE(xas, &mapping->i_pages, offset); |
1494 | struct page *head, *page; | 1498 | struct page *page; |
1495 | 1499 | ||
1496 | rcu_read_lock(); | 1500 | rcu_read_lock(); |
1497 | repeat: | 1501 | repeat: |
@@ -1506,25 +1510,19 @@ repeat: | |||
1506 | if (!page || xa_is_value(page)) | 1510 | if (!page || xa_is_value(page)) |
1507 | goto out; | 1511 | goto out; |
1508 | 1512 | ||
1509 | head = compound_head(page); | 1513 | if (!page_cache_get_speculative(page)) |
1510 | if (!page_cache_get_speculative(head)) | ||
1511 | goto repeat; | 1514 | goto repeat; |
1512 | 1515 | ||
1513 | /* The page was split under us? */ | ||
1514 | if (compound_head(page) != head) { | ||
1515 | put_page(head); | ||
1516 | goto repeat; | ||
1517 | } | ||
1518 | |||
1519 | /* | 1516 | /* |
1520 | * Has the page moved? | 1517 | * Has the page moved or been split? |
1521 | * This is part of the lockless pagecache protocol. See | 1518 | * This is part of the lockless pagecache protocol. See |
1522 | * include/linux/pagemap.h for details. | 1519 | * include/linux/pagemap.h for details. |
1523 | */ | 1520 | */ |
1524 | if (unlikely(page != xas_reload(&xas))) { | 1521 | if (unlikely(page != xas_reload(&xas))) { |
1525 | put_page(head); | 1522 | put_page(page); |
1526 | goto repeat; | 1523 | goto repeat; |
1527 | } | 1524 | } |
1525 | page = find_subpage(page, offset); | ||
1528 | out: | 1526 | out: |
1529 | rcu_read_unlock(); | 1527 | rcu_read_unlock(); |
1530 | 1528 | ||
@@ -1706,7 +1704,6 @@ unsigned find_get_entries(struct address_space *mapping, | |||
1706 | 1704 | ||
1707 | rcu_read_lock(); | 1705 | rcu_read_lock(); |
1708 | xas_for_each(&xas, page, ULONG_MAX) { | 1706 | xas_for_each(&xas, page, ULONG_MAX) { |
1709 | struct page *head; | ||
1710 | if (xas_retry(&xas, page)) | 1707 | if (xas_retry(&xas, page)) |
1711 | continue; | 1708 | continue; |
1712 | /* | 1709 | /* |
@@ -1717,17 +1714,13 @@ unsigned find_get_entries(struct address_space *mapping, | |||
1717 | if (xa_is_value(page)) | 1714 | if (xa_is_value(page)) |
1718 | goto export; | 1715 | goto export; |
1719 | 1716 | ||
1720 | head = compound_head(page); | 1717 | if (!page_cache_get_speculative(page)) |
1721 | if (!page_cache_get_speculative(head)) | ||
1722 | goto retry; | 1718 | goto retry; |
1723 | 1719 | ||
1724 | /* The page was split under us? */ | 1720 | /* Has the page moved or been split? */ |
1725 | if (compound_head(page) != head) | ||
1726 | goto put_page; | ||
1727 | |||
1728 | /* Has the page moved? */ | ||
1729 | if (unlikely(page != xas_reload(&xas))) | 1721 | if (unlikely(page != xas_reload(&xas))) |
1730 | goto put_page; | 1722 | goto put_page; |
1723 | page = find_subpage(page, xas.xa_index); | ||
1731 | 1724 | ||
1732 | export: | 1725 | export: |
1733 | indices[ret] = xas.xa_index; | 1726 | indices[ret] = xas.xa_index; |
@@ -1736,7 +1729,7 @@ export: | |||
1736 | break; | 1729 | break; |
1737 | continue; | 1730 | continue; |
1738 | put_page: | 1731 | put_page: |
1739 | put_page(head); | 1732 | put_page(page); |
1740 | retry: | 1733 | retry: |
1741 | xas_reset(&xas); | 1734 | xas_reset(&xas); |
1742 | } | 1735 | } |
@@ -1778,33 +1771,27 @@ unsigned find_get_pages_range(struct address_space *mapping, pgoff_t *start, | |||
1778 | 1771 | ||
1779 | rcu_read_lock(); | 1772 | rcu_read_lock(); |
1780 | xas_for_each(&xas, page, end) { | 1773 | xas_for_each(&xas, page, end) { |
1781 | struct page *head; | ||
1782 | if (xas_retry(&xas, page)) | 1774 | if (xas_retry(&xas, page)) |
1783 | continue; | 1775 | continue; |
1784 | /* Skip over shadow, swap and DAX entries */ | 1776 | /* Skip over shadow, swap and DAX entries */ |
1785 | if (xa_is_value(page)) | 1777 | if (xa_is_value(page)) |
1786 | continue; | 1778 | continue; |
1787 | 1779 | ||
1788 | head = compound_head(page); | 1780 | if (!page_cache_get_speculative(page)) |
1789 | if (!page_cache_get_speculative(head)) | ||
1790 | goto retry; | 1781 | goto retry; |
1791 | 1782 | ||
1792 | /* The page was split under us? */ | 1783 | /* Has the page moved or been split? */ |
1793 | if (compound_head(page) != head) | ||
1794 | goto put_page; | ||
1795 | |||
1796 | /* Has the page moved? */ | ||
1797 | if (unlikely(page != xas_reload(&xas))) | 1784 | if (unlikely(page != xas_reload(&xas))) |
1798 | goto put_page; | 1785 | goto put_page; |
1799 | 1786 | ||
1800 | pages[ret] = page; | 1787 | pages[ret] = find_subpage(page, xas.xa_index); |
1801 | if (++ret == nr_pages) { | 1788 | if (++ret == nr_pages) { |
1802 | *start = xas.xa_index + 1; | 1789 | *start = xas.xa_index + 1; |
1803 | goto out; | 1790 | goto out; |
1804 | } | 1791 | } |
1805 | continue; | 1792 | continue; |
1806 | put_page: | 1793 | put_page: |
1807 | put_page(head); | 1794 | put_page(page); |
1808 | retry: | 1795 | retry: |
1809 | xas_reset(&xas); | 1796 | xas_reset(&xas); |
1810 | } | 1797 | } |
@@ -1849,7 +1836,6 @@ unsigned find_get_pages_contig(struct address_space *mapping, pgoff_t index, | |||
1849 | 1836 | ||
1850 | rcu_read_lock(); | 1837 | rcu_read_lock(); |
1851 | for (page = xas_load(&xas); page; page = xas_next(&xas)) { | 1838 | for (page = xas_load(&xas); page; page = xas_next(&xas)) { |
1852 | struct page *head; | ||
1853 | if (xas_retry(&xas, page)) | 1839 | if (xas_retry(&xas, page)) |
1854 | continue; | 1840 | continue; |
1855 | /* | 1841 | /* |
@@ -1859,24 +1845,19 @@ unsigned find_get_pages_contig(struct address_space *mapping, pgoff_t index, | |||
1859 | if (xa_is_value(page)) | 1845 | if (xa_is_value(page)) |
1860 | break; | 1846 | break; |
1861 | 1847 | ||
1862 | head = compound_head(page); | 1848 | if (!page_cache_get_speculative(page)) |
1863 | if (!page_cache_get_speculative(head)) | ||
1864 | goto retry; | 1849 | goto retry; |
1865 | 1850 | ||
1866 | /* The page was split under us? */ | 1851 | /* Has the page moved or been split? */ |
1867 | if (compound_head(page) != head) | ||
1868 | goto put_page; | ||
1869 | |||
1870 | /* Has the page moved? */ | ||
1871 | if (unlikely(page != xas_reload(&xas))) | 1852 | if (unlikely(page != xas_reload(&xas))) |
1872 | goto put_page; | 1853 | goto put_page; |
1873 | 1854 | ||
1874 | pages[ret] = page; | 1855 | pages[ret] = find_subpage(page, xas.xa_index); |
1875 | if (++ret == nr_pages) | 1856 | if (++ret == nr_pages) |
1876 | break; | 1857 | break; |
1877 | continue; | 1858 | continue; |
1878 | put_page: | 1859 | put_page: |
1879 | put_page(head); | 1860 | put_page(page); |
1880 | retry: | 1861 | retry: |
1881 | xas_reset(&xas); | 1862 | xas_reset(&xas); |
1882 | } | 1863 | } |
@@ -1912,7 +1893,6 @@ unsigned find_get_pages_range_tag(struct address_space *mapping, pgoff_t *index, | |||
1912 | 1893 | ||
1913 | rcu_read_lock(); | 1894 | rcu_read_lock(); |
1914 | xas_for_each_marked(&xas, page, end, tag) { | 1895 | xas_for_each_marked(&xas, page, end, tag) { |
1915 | struct page *head; | ||
1916 | if (xas_retry(&xas, page)) | 1896 | if (xas_retry(&xas, page)) |
1917 | continue; | 1897 | continue; |
1918 | /* | 1898 | /* |
@@ -1923,26 +1903,21 @@ unsigned find_get_pages_range_tag(struct address_space *mapping, pgoff_t *index, | |||
1923 | if (xa_is_value(page)) | 1903 | if (xa_is_value(page)) |
1924 | continue; | 1904 | continue; |
1925 | 1905 | ||
1926 | head = compound_head(page); | 1906 | if (!page_cache_get_speculative(page)) |
1927 | if (!page_cache_get_speculative(head)) | ||
1928 | goto retry; | 1907 | goto retry; |
1929 | 1908 | ||
1930 | /* The page was split under us? */ | 1909 | /* Has the page moved or been split? */ |
1931 | if (compound_head(page) != head) | ||
1932 | goto put_page; | ||
1933 | |||
1934 | /* Has the page moved? */ | ||
1935 | if (unlikely(page != xas_reload(&xas))) | 1910 | if (unlikely(page != xas_reload(&xas))) |
1936 | goto put_page; | 1911 | goto put_page; |
1937 | 1912 | ||
1938 | pages[ret] = page; | 1913 | pages[ret] = find_subpage(page, xas.xa_index); |
1939 | if (++ret == nr_pages) { | 1914 | if (++ret == nr_pages) { |
1940 | *index = xas.xa_index + 1; | 1915 | *index = xas.xa_index + 1; |
1941 | goto out; | 1916 | goto out; |
1942 | } | 1917 | } |
1943 | continue; | 1918 | continue; |
1944 | put_page: | 1919 | put_page: |
1945 | put_page(head); | 1920 | put_page(page); |
1946 | retry: | 1921 | retry: |
1947 | xas_reset(&xas); | 1922 | xas_reset(&xas); |
1948 | } | 1923 | } |
@@ -1991,7 +1966,6 @@ unsigned find_get_entries_tag(struct address_space *mapping, pgoff_t start, | |||
1991 | 1966 | ||
1992 | rcu_read_lock(); | 1967 | rcu_read_lock(); |
1993 | xas_for_each_marked(&xas, page, ULONG_MAX, tag) { | 1968 | xas_for_each_marked(&xas, page, ULONG_MAX, tag) { |
1994 | struct page *head; | ||
1995 | if (xas_retry(&xas, page)) | 1969 | if (xas_retry(&xas, page)) |
1996 | continue; | 1970 | continue; |
1997 | /* | 1971 | /* |
@@ -2002,17 +1976,13 @@ unsigned find_get_entries_tag(struct address_space *mapping, pgoff_t start, | |||
2002 | if (xa_is_value(page)) | 1976 | if (xa_is_value(page)) |
2003 | goto export; | 1977 | goto export; |
2004 | 1978 | ||
2005 | head = compound_head(page); | 1979 | if (!page_cache_get_speculative(page)) |
2006 | if (!page_cache_get_speculative(head)) | ||
2007 | goto retry; | 1980 | goto retry; |
2008 | 1981 | ||
2009 | /* The page was split under us? */ | 1982 | /* Has the page moved or been split? */ |
2010 | if (compound_head(page) != head) | ||
2011 | goto put_page; | ||
2012 | |||
2013 | /* Has the page moved? */ | ||
2014 | if (unlikely(page != xas_reload(&xas))) | 1983 | if (unlikely(page != xas_reload(&xas))) |
2015 | goto put_page; | 1984 | goto put_page; |
1985 | page = find_subpage(page, xas.xa_index); | ||
2016 | 1986 | ||
2017 | export: | 1987 | export: |
2018 | indices[ret] = xas.xa_index; | 1988 | indices[ret] = xas.xa_index; |
@@ -2021,7 +1991,7 @@ export: | |||
2021 | break; | 1991 | break; |
2022 | continue; | 1992 | continue; |
2023 | put_page: | 1993 | put_page: |
2024 | put_page(head); | 1994 | put_page(page); |
2025 | retry: | 1995 | retry: |
2026 | xas_reset(&xas); | 1996 | xas_reset(&xas); |
2027 | } | 1997 | } |
@@ -2691,7 +2661,7 @@ void filemap_map_pages(struct vm_fault *vmf, | |||
2691 | pgoff_t last_pgoff = start_pgoff; | 2661 | pgoff_t last_pgoff = start_pgoff; |
2692 | unsigned long max_idx; | 2662 | unsigned long max_idx; |
2693 | XA_STATE(xas, &mapping->i_pages, start_pgoff); | 2663 | XA_STATE(xas, &mapping->i_pages, start_pgoff); |
2694 | struct page *head, *page; | 2664 | struct page *page; |
2695 | 2665 | ||
2696 | rcu_read_lock(); | 2666 | rcu_read_lock(); |
2697 | xas_for_each(&xas, page, end_pgoff) { | 2667 | xas_for_each(&xas, page, end_pgoff) { |
@@ -2700,24 +2670,19 @@ void filemap_map_pages(struct vm_fault *vmf, | |||
2700 | if (xa_is_value(page)) | 2670 | if (xa_is_value(page)) |
2701 | goto next; | 2671 | goto next; |
2702 | 2672 | ||
2703 | head = compound_head(page); | ||
2704 | |||
2705 | /* | 2673 | /* |
2706 | * Check for a locked page first, as a speculative | 2674 | * Check for a locked page first, as a speculative |
2707 | * reference may adversely influence page migration. | 2675 | * reference may adversely influence page migration. |
2708 | */ | 2676 | */ |
2709 | if (PageLocked(head)) | 2677 | if (PageLocked(page)) |
2710 | goto next; | 2678 | goto next; |
2711 | if (!page_cache_get_speculative(head)) | 2679 | if (!page_cache_get_speculative(page)) |
2712 | goto next; | 2680 | goto next; |
2713 | 2681 | ||
2714 | /* The page was split under us? */ | 2682 | /* Has the page moved or been split? */ |
2715 | if (compound_head(page) != head) | ||
2716 | goto skip; | ||
2717 | |||
2718 | /* Has the page moved? */ | ||
2719 | if (unlikely(page != xas_reload(&xas))) | 2683 | if (unlikely(page != xas_reload(&xas))) |
2720 | goto skip; | 2684 | goto skip; |
2685 | page = find_subpage(page, xas.xa_index); | ||
2721 | 2686 | ||
2722 | if (!PageUptodate(page) || | 2687 | if (!PageUptodate(page) || |
2723 | PageReadahead(page) || | 2688 | PageReadahead(page) || |