[PATCH] afs: Use a pagevec in afs_writepages()
From: Matthew Wilcox (Oracle)
Date: Mon Aug 24 2020 - 14:34:34 EST
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@xxxxxxxxxxxxx>
---
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