diff options
author | Matthew Wilcox <willy@infradead.org> | 2018-05-16 23:56:04 -0400 |
---|---|---|
committer | Matthew Wilcox <willy@infradead.org> | 2018-10-21 10:46:35 -0400 |
commit | c1901cd33cf407d77a181f8dd4ffff98041ef480 (patch) | |
tree | 4a7b69052ae6e402db04c329a6087b819b703fbb /mm/filemap.c | |
parent | a6906972fe67fb6f73ba04088f7897227fd1cd8f (diff) |
page cache: Convert find_get_entries_tag to XArray
Slightly shorter and simpler code.
Signed-off-by: Matthew Wilcox <willy@infradead.org>
Diffstat (limited to 'mm/filemap.c')
-rw-r--r-- | mm/filemap.c | 54 |
1 files changed, 24 insertions, 30 deletions
diff --git a/mm/filemap.c b/mm/filemap.c index 0df28aa6411c..35ae011971e1 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
@@ -1866,57 +1866,51 @@ EXPORT_SYMBOL(find_get_pages_range_tag); | |||
1866 | * @tag. | 1866 | * @tag. |
1867 | */ | 1867 | */ |
1868 | unsigned find_get_entries_tag(struct address_space *mapping, pgoff_t start, | 1868 | unsigned find_get_entries_tag(struct address_space *mapping, pgoff_t start, |
1869 | int tag, unsigned int nr_entries, | 1869 | xa_mark_t tag, unsigned int nr_entries, |
1870 | struct page **entries, pgoff_t *indices) | 1870 | struct page **entries, pgoff_t *indices) |
1871 | { | 1871 | { |
1872 | void **slot; | 1872 | XA_STATE(xas, &mapping->i_pages, start); |
1873 | struct page *page; | ||
1873 | unsigned int ret = 0; | 1874 | unsigned int ret = 0; |
1874 | struct radix_tree_iter iter; | ||
1875 | 1875 | ||
1876 | if (!nr_entries) | 1876 | if (!nr_entries) |
1877 | return 0; | 1877 | return 0; |
1878 | 1878 | ||
1879 | rcu_read_lock(); | 1879 | rcu_read_lock(); |
1880 | radix_tree_for_each_tagged(slot, &mapping->i_pages, &iter, start, tag) { | 1880 | xas_for_each_marked(&xas, page, ULONG_MAX, tag) { |
1881 | struct page *head, *page; | 1881 | struct page *head; |
1882 | repeat: | 1882 | if (xas_retry(&xas, page)) |
1883 | page = radix_tree_deref_slot(slot); | ||
1884 | if (unlikely(!page)) | ||
1885 | continue; | 1883 | continue; |
1886 | if (radix_tree_exception(page)) { | 1884 | /* |
1887 | if (radix_tree_deref_retry(page)) { | 1885 | * A shadow entry of a recently evicted page, a swap |
1888 | slot = radix_tree_iter_retry(&iter); | 1886 | * entry from shmem/tmpfs or a DAX entry. Return it |
1889 | continue; | 1887 | * without attempting to raise page count. |
1890 | } | 1888 | */ |
1891 | 1889 | if (xa_is_value(page)) | |
1892 | /* | ||
1893 | * A shadow entry of a recently evicted page, a swap | ||
1894 | * entry from shmem/tmpfs or a DAX entry. Return it | ||
1895 | * without attempting to raise page count. | ||
1896 | */ | ||
1897 | goto export; | 1890 | goto export; |
1898 | } | ||
1899 | 1891 | ||
1900 | head = compound_head(page); | 1892 | head = compound_head(page); |
1901 | if (!page_cache_get_speculative(head)) | 1893 | if (!page_cache_get_speculative(head)) |
1902 | goto repeat; | 1894 | goto retry; |
1903 | 1895 | ||
1904 | /* The page was split under us? */ | 1896 | /* The page was split under us? */ |
1905 | if (compound_head(page) != head) { | 1897 | if (compound_head(page) != head) |
1906 | put_page(head); | 1898 | goto put_page; |
1907 | goto repeat; | ||
1908 | } | ||
1909 | 1899 | ||
1910 | /* Has the page moved? */ | 1900 | /* Has the page moved? */ |
1911 | if (unlikely(page != *slot)) { | 1901 | if (unlikely(page != xas_reload(&xas))) |
1912 | put_page(head); | 1902 | goto put_page; |
1913 | goto repeat; | 1903 | |
1914 | } | ||
1915 | export: | 1904 | export: |
1916 | indices[ret] = iter.index; | 1905 | indices[ret] = xas.xa_index; |
1917 | entries[ret] = page; | 1906 | entries[ret] = page; |
1918 | if (++ret == nr_entries) | 1907 | if (++ret == nr_entries) |
1919 | break; | 1908 | break; |
1909 | continue; | ||
1910 | put_page: | ||
1911 | put_page(head); | ||
1912 | retry: | ||
1913 | xas_reset(&xas); | ||
1920 | } | 1914 | } |
1921 | rcu_read_unlock(); | 1915 | rcu_read_unlock(); |
1922 | return ret; | 1916 | return ret; |