[PATCH] afs: Use a pagevec in afs_writepages()

Matthew Wilcox (Oracle) willy at infradead.org
Mon Aug 24 14:34:24 EDT 2020


This amortises the overhead of retrieving pages from the pagecache
and the overhead of freeing pages if we happen to end up with the
last references to the pages.

Signed-off-by: Matthew Wilcox (Oracle) <willy at infradead.org>
---
 fs/afs/write.c | 41 ++++++++++++++++++++++++-----------------
 1 file changed, 24 insertions(+), 17 deletions(-)

diff --git a/fs/afs/write.c b/fs/afs/write.c
index a121c247d95a..2d20037c7ff0 100644
--- a/fs/afs/write.c
+++ b/fs/afs/write.c
@@ -673,16 +673,24 @@ static int afs_writepages_region(struct address_space *mapping,
 				 struct writeback_control *wbc,
 				 pgoff_t index, pgoff_t end, pgoff_t *_next)
 {
-	struct page *page;
-	int ret, n;
+	struct pagevec pvec;
+	int ret, i = 0;
 
 	_enter(",,%lx,%lx,", index, end);
 
+	pagevec_init(&pvec);
 	do {
-		n = find_get_pages_range_tag(mapping, &index, end,
-					PAGECACHE_TAG_DIRTY, 1, &page);
-		if (!n)
-			break;
+		struct page *page;
+
+		if (i == pagevec_count(&pvec)) {
+			pagevec_release(&pvec);
+			if (!pagevec_lookup_range_tag(&pvec, mapping,
+					&index, end, PAGECACHE_TAG_DIRTY))
+				break;
+			i = 0;
+		}
+
+		page = pvec.pages[i++];
 
 		_debug("wback %lx", page->index);
 
@@ -693,15 +701,11 @@ static int afs_writepages_region(struct address_space *mapping,
 		 * back from swapper_space to tmpfs file mapping
 		 */
 		ret = lock_page_killable(page);
-		if (ret < 0) {
-			put_page(page);
-			_leave(" = %d", ret);
-			return ret;
-		}
+		if (ret < 0)
+			goto err;
 
 		if (page->mapping != mapping || !PageDirty(page)) {
 			unlock_page(page);
-			put_page(page);
 			continue;
 		}
 
@@ -709,7 +713,6 @@ static int afs_writepages_region(struct address_space *mapping,
 			unlock_page(page);
 			if (wbc->sync_mode != WB_SYNC_NONE)
 				wait_on_page_writeback(page);
-			put_page(page);
 			continue;
 		}
 
@@ -717,19 +720,23 @@ static int afs_writepages_region(struct address_space *mapping,
 			BUG();
 		ret = afs_write_back_from_locked_page(mapping, wbc, page, end);
 		put_page(page);
-		if (ret < 0) {
-			_leave(" = %d", ret);
-			return ret;
-		}
+		if (ret < 0)
+			goto err;
 
 		wbc->nr_to_write -= ret;
 
 		cond_resched();
 	} while (index < end && wbc->nr_to_write > 0);
 
+	pagevec_release(&pvec);
 	*_next = index;
 	_leave(" = 0 [%lx]", *_next);
 	return 0;
+
+err:
+	pagevec_release(&pvec);
+	_leave(" = %d", ret);
+	return ret;
 }
 
 /*
-- 
2.28.0




More information about the linux-afs mailing list