aboutsummaryrefslogtreecommitdiffstats
path: root/mm/page-writeback.c
diff options
context:
space:
mode:
authorMatthew Wilcox <mawilcox@microsoft.com>2016-12-14 18:08:55 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2016-12-14 19:04:10 -0500
commit268f42de718128cd0301293177e79c08c38e39a6 (patch)
tree6668c85388c327f64ce9b51e77d70e245ec52b57 /mm/page-writeback.c
parent478922e2b0f41567e4a530771bfb3f693f857d45 (diff)
radix-tree: delete radix_tree_range_tag_if_tagged()
This is an exceptionally complicated function with just one caller (tag_pages_for_writeback). We devote a large portion of the runtime of the test suite to testing this one function which has one caller. By introducing the new function radix_tree_iter_tag_set(), we can eliminate all of the complexity while keeping the performance. The caller can now use a fairly standard radix_tree_for_each() loop, and it doesn't need to worry about tricksy things like 'start' wrapping. The test suite continues to spend a large amount of time investigating this function, but now it's testing the underlying primitives such as radix_tree_iter_resume() and the radix_tree_for_each_tagged() iterator which are also used by other parts of the kernel. Link: http://lkml.kernel.org/r/1480369871-5271-57-git-send-email-mawilcox@linuxonhyperv.com Signed-off-by: Matthew Wilcox <willy@infradead.org> Tested-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Cc: Konstantin Khlebnikov <koct9i@gmail.com> Cc: Ross Zwisler <ross.zwisler@linux.intel.com> Cc: Matthew Wilcox <mawilcox@microsoft.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/page-writeback.c')
-rw-r--r--mm/page-writeback.c28
1 files changed, 18 insertions, 10 deletions
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 52e2f8e3b472..290e8b7d3181 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -2106,18 +2106,26 @@ void tag_pages_for_writeback(struct address_space *mapping,
2106 pgoff_t start, pgoff_t end) 2106 pgoff_t start, pgoff_t end)
2107{ 2107{
2108#define WRITEBACK_TAG_BATCH 4096 2108#define WRITEBACK_TAG_BATCH 4096
2109 unsigned long tagged; 2109 unsigned long tagged = 0;
2110 2110 struct radix_tree_iter iter;
2111 do { 2111 void **slot;
2112 spin_lock_irq(&mapping->tree_lock); 2112
2113 tagged = radix_tree_range_tag_if_tagged(&mapping->page_tree, 2113 spin_lock_irq(&mapping->tree_lock);
2114 &start, end, WRITEBACK_TAG_BATCH, 2114 radix_tree_for_each_tagged(slot, &mapping->page_tree, &iter, start,
2115 PAGECACHE_TAG_DIRTY, PAGECACHE_TAG_TOWRITE); 2115 PAGECACHE_TAG_DIRTY) {
2116 if (iter.index > end)
2117 break;
2118 radix_tree_iter_tag_set(&mapping->page_tree, &iter,
2119 PAGECACHE_TAG_TOWRITE);
2120 tagged++;
2121 if ((tagged % WRITEBACK_TAG_BATCH) != 0)
2122 continue;
2123 slot = radix_tree_iter_resume(slot, &iter);
2116 spin_unlock_irq(&mapping->tree_lock); 2124 spin_unlock_irq(&mapping->tree_lock);
2117 WARN_ON_ONCE(tagged > WRITEBACK_TAG_BATCH);
2118 cond_resched(); 2125 cond_resched();
2119 /* We check 'start' to handle wrapping when end == ~0UL */ 2126 spin_lock_irq(&mapping->tree_lock);
2120 } while (tagged >= WRITEBACK_TAG_BATCH && start); 2127 }
2128 spin_unlock_irq(&mapping->tree_lock);
2121} 2129}
2122EXPORT_SYMBOL(tag_pages_for_writeback); 2130EXPORT_SYMBOL(tag_pages_for_writeback);
2123 2131