diff options
| author | Matthew Wilcox <willy@infradead.org> | 2018-05-16 14:00:33 -0800 |
|---|---|---|
| committer | Matthew Wilcox <willy@infradead.org> | 2018-10-21 06:46:34 -0800 |
| commit | 3ece58a270cd1e5026282abe778bd50db7a11d08 (patch) | |
| tree | ed4feeec0489b4fa9e513e8817363944da48dd3d | |
| parent | fd1b3cee2a867868d39bb8cbcc4b00c36d07cc01 (diff) | |
| download | linux-stable-3ece58a270cd1e5026282abe778bd50db7a11d08.tar.gz linux-stable-3ece58a270cd1e5026282abe778bd50db7a11d08.tar.bz2 linux-stable-3ece58a270cd1e5026282abe778bd50db7a11d08.tar.xz linux-stable-3ece58a270cd1e5026282abe778bd50db7a11d08.zip | |
page cache: Convert find_get_pages_contig to XArray
There's no direct replacement for radix_tree_for_each_contig()
in the XArray API as it's an unusual thing to do. Instead,
open-code a loop using xas_next(). This removes the only user of
radix_tree_for_each_contig() so delete the iterator from the API and
the test suite code for it.
Signed-off-by: Matthew Wilcox <willy@infradead.org>
| -rw-r--r-- | .clang-format | 1 | ||||
| -rw-r--r-- | include/linux/radix-tree.h | 17 | ||||
| -rw-r--r-- | mm/filemap.c | 53 | ||||
| -rw-r--r-- | tools/testing/radix-tree/regression3.c | 23 |
4 files changed, 22 insertions, 72 deletions
diff --git a/.clang-format b/.clang-format index 1d5da22e0ba5..e6080f5834a3 100644 --- a/.clang-format +++ b/.clang-format | |||
| @@ -323,7 +323,6 @@ ForEachMacros: | |||
| 323 | - 'protocol_for_each_card' | 323 | - 'protocol_for_each_card' |
| 324 | - 'protocol_for_each_dev' | 324 | - 'protocol_for_each_dev' |
| 325 | - 'queue_for_each_hw_ctx' | 325 | - 'queue_for_each_hw_ctx' |
| 326 | - 'radix_tree_for_each_contig' | ||
| 327 | - 'radix_tree_for_each_slot' | 326 | - 'radix_tree_for_each_slot' |
| 328 | - 'radix_tree_for_each_tagged' | 327 | - 'radix_tree_for_each_tagged' |
| 329 | - 'rbtree_postorder_for_each_entry_safe' | 328 | - 'rbtree_postorder_for_each_entry_safe' |
diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h index d55de428a589..023e888e1163 100644 --- a/include/linux/radix-tree.h +++ b/include/linux/radix-tree.h | |||
| @@ -523,23 +523,6 @@ static __always_inline void __rcu **radix_tree_next_slot(void __rcu **slot, | |||
| 523 | slot = radix_tree_next_slot(slot, iter, 0)) | 523 | slot = radix_tree_next_slot(slot, iter, 0)) |
| 524 | 524 | ||
| 525 | /** | 525 | /** |
| 526 | * radix_tree_for_each_contig - iterate over contiguous slots | ||
| 527 | * | ||
| 528 | * @slot: the void** variable for pointer to slot | ||
| 529 | * @root: the struct radix_tree_root pointer | ||
| 530 | * @iter: the struct radix_tree_iter pointer | ||
| 531 | * @start: iteration starting index | ||
| 532 | * | ||
| 533 | * @slot points to radix tree slot, @iter->index contains its index. | ||
| 534 | */ | ||
| 535 | #define radix_tree_for_each_contig(slot, root, iter, start) \ | ||
| 536 | for (slot = radix_tree_iter_init(iter, start) ; \ | ||
| 537 | slot || (slot = radix_tree_next_chunk(root, iter, \ | ||
| 538 | RADIX_TREE_ITER_CONTIG)) ; \ | ||
| 539 | slot = radix_tree_next_slot(slot, iter, \ | ||
| 540 | RADIX_TREE_ITER_CONTIG)) | ||
| 541 | |||
| 542 | /** | ||
| 543 | * radix_tree_for_each_tagged - iterate over tagged slots | 526 | * radix_tree_for_each_tagged - iterate over tagged slots |
| 544 | * | 527 | * |
| 545 | * @slot: the void** variable for pointer to slot | 528 | * @slot: the void** variable for pointer to slot |
diff --git a/mm/filemap.c b/mm/filemap.c index b72c39fe61c2..089b67598100 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
| @@ -1721,57 +1721,43 @@ out: | |||
| 1721 | unsigned find_get_pages_contig(struct address_space *mapping, pgoff_t index, | 1721 | unsigned find_get_pages_contig(struct address_space *mapping, pgoff_t index, |
| 1722 | unsigned int nr_pages, struct page **pages) | 1722 | unsigned int nr_pages, struct page **pages) |
| 1723 | { | 1723 | { |
| 1724 | struct radix_tree_iter iter; | 1724 | XA_STATE(xas, &mapping->i_pages, index); |
| 1725 | void **slot; | 1725 | struct page *page; |
| 1726 | unsigned int ret = 0; | 1726 | unsigned int ret = 0; |
| 1727 | 1727 | ||
| 1728 | if (unlikely(!nr_pages)) | 1728 | if (unlikely(!nr_pages)) |
| 1729 | return 0; | 1729 | return 0; |
| 1730 | 1730 | ||
| 1731 | rcu_read_lock(); | 1731 | rcu_read_lock(); |
| 1732 | radix_tree_for_each_contig(slot, &mapping->i_pages, &iter, index) { | 1732 | for (page = xas_load(&xas); page; page = xas_next(&xas)) { |
| 1733 | struct page *head, *page; | 1733 | struct page *head; |
| 1734 | repeat: | 1734 | if (xas_retry(&xas, page)) |
| 1735 | page = radix_tree_deref_slot(slot); | 1735 | continue; |
| 1736 | /* The hole, there no reason to continue */ | 1736 | /* |
| 1737 | if (unlikely(!page)) | 1737 | * If the entry has been swapped out, we can stop looking. |
| 1738 | break; | 1738 | * No current caller is looking for DAX entries. |
| 1739 | 1739 | */ | |
| 1740 | if (radix_tree_exception(page)) { | 1740 | if (xa_is_value(page)) |
| 1741 | if (radix_tree_deref_retry(page)) { | ||
| 1742 | slot = radix_tree_iter_retry(&iter); | ||
| 1743 | continue; | ||
| 1744 | } | ||
| 1745 | /* | ||
| 1746 | * A shadow entry of a recently evicted page, | ||
| 1747 | * or a swap entry from shmem/tmpfs. Stop | ||
| 1748 | * looking for contiguous pages. | ||
| 1749 | */ | ||
| 1750 | break; | 1741 | break; |
| 1751 | } | ||
| 1752 | 1742 | ||
| 1753 | head = compound_head(page); | 1743 | head = compound_head(page); |
| 1754 | if (!page_cache_get_speculative(head)) | 1744 | if (!page_cache_get_speculative(head)) |
| 1755 | goto repeat; | 1745 | goto retry; |
| 1756 | 1746 | ||
| 1757 | /* The page was split under us? */ | 1747 | /* The page was split under us? */ |
| 1758 | if (compound_head(page) != head) { | 1748 | if (compound_head(page) != head) |
| 1759 | put_page(head); | 1749 | goto put_page; |
| 1760 | goto repeat; | ||
| 1761 | } | ||
| 1762 | 1750 | ||
| 1763 | /* Has the page moved? */ | 1751 | /* Has the page moved? */ |
| 1764 | if (unlikely(page != *slot)) { | 1752 | if (unlikely(page != xas_reload(&xas))) |
| 1765 | put_page(head); | 1753 | goto put_page; |
| 1766 | goto repeat; | ||
| 1767 | } | ||
| 1768 | 1754 | ||
| 1769 | /* | 1755 | /* |
| 1770 | * must check mapping and index after taking the ref. | 1756 | * must check mapping and index after taking the ref. |
| 1771 | * otherwise we can get both false positives and false | 1757 | * otherwise we can get both false positives and false |
| 1772 | * negatives, which is just confusing to the caller. | 1758 | * negatives, which is just confusing to the caller. |
| 1773 | */ | 1759 | */ |
| 1774 | if (page->mapping == NULL || page_to_pgoff(page) != iter.index) { | 1760 | if (!page->mapping || page_to_pgoff(page) != xas.xa_index) { |
| 1775 | put_page(page); | 1761 | put_page(page); |
| 1776 | break; | 1762 | break; |
| 1777 | } | 1763 | } |
| @@ -1779,6 +1765,11 @@ repeat: | |||
| 1779 | pages[ret] = page; | 1765 | pages[ret] = page; |
| 1780 | if (++ret == nr_pages) | 1766 | if (++ret == nr_pages) |
| 1781 | break; | 1767 | break; |
| 1768 | continue; | ||
| 1769 | put_page: | ||
| 1770 | put_page(head); | ||
| 1771 | retry: | ||
| 1772 | xas_reset(&xas); | ||
| 1782 | } | 1773 | } |
| 1783 | rcu_read_unlock(); | 1774 | rcu_read_unlock(); |
| 1784 | return ret; | 1775 | return ret; |
diff --git a/tools/testing/radix-tree/regression3.c b/tools/testing/radix-tree/regression3.c index ace2543c3eda..9f9a3b280f56 100644 --- a/tools/testing/radix-tree/regression3.c +++ b/tools/testing/radix-tree/regression3.c | |||
| @@ -69,21 +69,6 @@ void regression3_test(void) | |||
| 69 | continue; | 69 | continue; |
| 70 | } | 70 | } |
| 71 | } | 71 | } |
| 72 | radix_tree_delete(&root, 1); | ||
| 73 | |||
| 74 | first = true; | ||
| 75 | radix_tree_for_each_contig(slot, &root, &iter, 0) { | ||
| 76 | printv(2, "contig %ld %p\n", iter.index, *slot); | ||
| 77 | if (first) { | ||
| 78 | radix_tree_insert(&root, 1, ptr); | ||
| 79 | first = false; | ||
| 80 | } | ||
| 81 | if (radix_tree_deref_retry(*slot)) { | ||
| 82 | printv(2, "retry at %ld\n", iter.index); | ||
| 83 | slot = radix_tree_iter_retry(&iter); | ||
| 84 | continue; | ||
| 85 | } | ||
| 86 | } | ||
| 87 | 72 | ||
| 88 | radix_tree_for_each_slot(slot, &root, &iter, 0) { | 73 | radix_tree_for_each_slot(slot, &root, &iter, 0) { |
| 89 | printv(2, "slot %ld %p\n", iter.index, *slot); | 74 | printv(2, "slot %ld %p\n", iter.index, *slot); |
| @@ -93,14 +78,6 @@ void regression3_test(void) | |||
| 93 | } | 78 | } |
| 94 | } | 79 | } |
| 95 | 80 | ||
| 96 | radix_tree_for_each_contig(slot, &root, &iter, 0) { | ||
| 97 | printv(2, "contig %ld %p\n", iter.index, *slot); | ||
| 98 | if (!iter.index) { | ||
| 99 | printv(2, "next at %ld\n", iter.index); | ||
| 100 | slot = radix_tree_iter_resume(slot, &iter); | ||
| 101 | } | ||
| 102 | } | ||
| 103 | |||
| 104 | radix_tree_tag_set(&root, 0, 0); | 81 | radix_tree_tag_set(&root, 0, 0); |
| 105 | radix_tree_tag_set(&root, 1, 0); | 82 | radix_tree_tag_set(&root, 1, 0); |
| 106 | radix_tree_for_each_tagged(slot, &root, &iter, 0, 0) { | 83 | radix_tree_for_each_tagged(slot, &root, &iter, 0, 0) { |
