summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorMatthew Wilcox <willy@infradead.org>2018-05-16 14:00:33 -0800
committerMatthew Wilcox <willy@infradead.org>2018-10-21 06:46:34 -0800
commit3ece58a270cd1e5026282abe778bd50db7a11d08 (patch)
treeed4feeec0489b4fa9e513e8817363944da48dd3d
parentfd1b3cee2a867868d39bb8cbcc4b00c36d07cc01 (diff)
downloadlinux-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-format1
-rw-r--r--include/linux/radix-tree.h17
-rw-r--r--mm/filemap.c53
-rw-r--r--tools/testing/radix-tree/regression3.c23
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:
1721unsigned find_get_pages_contig(struct address_space *mapping, pgoff_t index, 1721unsigned 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;
1734repeat: 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;
1769put_page:
1770 put_page(head);
1771retry:
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) {