2022-10-17 20:29:20

by Vishal Moola

[permalink] [raw]
Subject: [PATCH v3 00/23] Convert to filemap_get_folios_tag()

This patch series replaces find_get_pages_range_tag() with
filemap_get_folios_tag(). This also allows the removal of multiple
calls to compound_head() throughout.
It also makes a good chunk of the straightforward conversions to folios,
and takes the opportunity to introduce a function that grabs a folio
from the pagecache.

F2fs and Ceph have quite alot of work to be done regarding folios, so
for now those patches only have the changes necessary for the removal of
find_get_pages_range_tag(), and only support folios of size 1 (which is
all they use right now anyways).

I've run xfstests on btrfs, ext4, f2fs, and nilfs2, but more testing may be
beneficial. The page-writeback and filemap changes implicitly work. Testing
and review of the other changes (afs, ceph, cifs, gfs2) would be appreciated.

---
v3:
Rebased onto upstream 6.1
Simplified the ceph patch to only necessary changes
Changed commit messages throughout to be clearer
Got an Acked-by for another nilfs patch
Got Tested-by for afs

v2:
Got Acked-By tags for nilfs and btrfs changes
Fixed an error arising in f2fs
- Reported-by: kernel test robot <[email protected]>

Vishal Moola (Oracle) (23):
pagemap: Add filemap_grab_folio()
filemap: Added filemap_get_folios_tag()
filemap: Convert __filemap_fdatawait_range() to use
filemap_get_folios_tag()
page-writeback: Convert write_cache_pages() to use
filemap_get_folios_tag()
afs: Convert afs_writepages_region() to use filemap_get_folios_tag()
btrfs: Convert btree_write_cache_pages() to use
filemap_get_folio_tag()
btrfs: Convert extent_write_cache_pages() to use
filemap_get_folios_tag()
ceph: Convert ceph_writepages_start() to use filemap_get_folios_tag()
cifs: Convert wdata_alloc_and_fillpages() to use
filemap_get_folios_tag()
ext4: Convert mpage_prepare_extent_to_map() to use
filemap_get_folios_tag()
f2fs: Convert f2fs_fsync_node_pages() to use filemap_get_folios_tag()
f2fs: Convert f2fs_flush_inline_data() to use filemap_get_folios_tag()
f2fs: Convert f2fs_sync_node_pages() to use filemap_get_folios_tag()
f2fs: Convert f2fs_write_cache_pages() to use filemap_get_folios_tag()
f2fs: Convert last_fsync_dnode() to use filemap_get_folios_tag()
f2fs: Convert f2fs_sync_meta_pages() to use filemap_get_folios_tag()
gfs2: Convert gfs2_write_cache_jdata() to use filemap_get_folios_tag()
nilfs2: Convert nilfs_lookup_dirty_data_buffers() to use
filemap_get_folios_tag()
nilfs2: Convert nilfs_lookup_dirty_node_buffers() to use
filemap_get_folios_tag()
nilfs2: Convert nilfs_btree_lookup_dirty_buffers() to use
filemap_get_folios_tag()
nilfs2: Convert nilfs_copy_dirty_pages() to use
filemap_get_folios_tag()
nilfs2: Convert nilfs_clear_dirty_pages() to use
filemap_get_folios_tag()
filemap: Remove find_get_pages_range_tag()

fs/afs/write.c | 114 +++++++++++++++++++++-------------------
fs/btrfs/extent_io.c | 57 ++++++++++----------
fs/ceph/addr.c | 58 ++++++++++----------
fs/cifs/file.c | 33 ++++++++++--
fs/ext4/inode.c | 55 ++++++++++---------
fs/f2fs/checkpoint.c | 49 +++++++++--------
fs/f2fs/compress.c | 13 ++---
fs/f2fs/data.c | 69 +++++++++++++-----------
fs/f2fs/f2fs.h | 5 +-
fs/f2fs/node.c | 72 +++++++++++++------------
fs/gfs2/aops.c | 64 ++++++++++++----------
fs/nilfs2/btree.c | 14 ++---
fs/nilfs2/page.c | 59 +++++++++++----------
fs/nilfs2/segment.c | 44 ++++++++--------
include/linux/pagemap.h | 32 +++++++----
include/linux/pagevec.h | 8 ---
mm/filemap.c | 87 +++++++++++++++---------------
mm/page-writeback.c | 44 ++++++++--------
mm/swap.c | 10 ----
19 files changed, 467 insertions(+), 420 deletions(-)

--
2.36.1


2022-10-17 20:30:28

by Vishal Moola

[permalink] [raw]
Subject: [PATCH v3 04/23] page-writeback: Convert write_cache_pages() to use filemap_get_folios_tag()

Converted function to use folios throughout. This is in preparation for
the removal of find_get_pages_range_tag().

Signed-off-by: Vishal Moola (Oracle) <[email protected]>
---
mm/page-writeback.c | 44 +++++++++++++++++++++++---------------------
1 file changed, 23 insertions(+), 21 deletions(-)

diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 7e9d8d857ecc..aeec8b196232 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -2286,15 +2286,15 @@ int write_cache_pages(struct address_space *mapping,
int ret = 0;
int done = 0;
int error;
- struct pagevec pvec;
- int nr_pages;
+ struct folio_batch fbatch;
+ int nr_folios;
pgoff_t index;
pgoff_t end; /* Inclusive */
pgoff_t done_index;
int range_whole = 0;
xa_mark_t tag;

- pagevec_init(&pvec);
+ folio_batch_init(&fbatch);
if (wbc->range_cyclic) {
index = mapping->writeback_index; /* prev offset */
end = -1;
@@ -2314,17 +2314,18 @@ int write_cache_pages(struct address_space *mapping,
while (!done && (index <= end)) {
int i;

- nr_pages = pagevec_lookup_range_tag(&pvec, mapping, &index, end,
- tag);
- if (nr_pages == 0)
+ nr_folios = filemap_get_folios_tag(mapping, &index, end,
+ tag, &fbatch);
+
+ if (nr_folios == 0)
break;

- for (i = 0; i < nr_pages; i++) {
- struct page *page = pvec.pages[i];
+ for (i = 0; i < nr_folios; i++) {
+ struct folio *folio = fbatch.folios[i];

- done_index = page->index;
+ done_index = folio->index;

- lock_page(page);
+ folio_lock(folio);

/*
* Page truncated or invalidated. We can freely skip it
@@ -2334,30 +2335,30 @@ int write_cache_pages(struct address_space *mapping,
* even if there is now a new, dirty page at the same
* pagecache address.
*/
- if (unlikely(page->mapping != mapping)) {
+ if (unlikely(folio->mapping != mapping)) {
continue_unlock:
- unlock_page(page);
+ folio_unlock(folio);
continue;
}

- if (!PageDirty(page)) {
+ if (!folio_test_dirty(folio)) {
/* someone wrote it for us */
goto continue_unlock;
}

- if (PageWriteback(page)) {
+ if (folio_test_writeback(folio)) {
if (wbc->sync_mode != WB_SYNC_NONE)
- wait_on_page_writeback(page);
+ folio_wait_writeback(folio);
else
goto continue_unlock;
}

- BUG_ON(PageWriteback(page));
- if (!clear_page_dirty_for_io(page))
+ BUG_ON(folio_test_writeback(folio));
+ if (!folio_clear_dirty_for_io(folio))
goto continue_unlock;

trace_wbc_writepage(wbc, inode_to_bdi(mapping->host));
- error = (*writepage)(page, wbc, data);
+ error = writepage(&folio->page, wbc, data);
if (unlikely(error)) {
/*
* Handle errors according to the type of
@@ -2372,11 +2373,12 @@ int write_cache_pages(struct address_space *mapping,
* the first error.
*/
if (error == AOP_WRITEPAGE_ACTIVATE) {
- unlock_page(page);
+ folio_unlock(folio);
error = 0;
} else if (wbc->sync_mode != WB_SYNC_ALL) {
ret = error;
- done_index = page->index + 1;
+ done_index = folio->index +
+ folio_nr_pages(folio);
done = 1;
break;
}
@@ -2396,7 +2398,7 @@ int write_cache_pages(struct address_space *mapping,
break;
}
}
- pagevec_release(&pvec);
+ folio_batch_release(&fbatch);
cond_resched();
}

--
2.36.1

2022-10-17 20:32:18

by Vishal Moola

[permalink] [raw]
Subject: [PATCH v3 17/23] gfs2: Convert gfs2_write_cache_jdata() to use filemap_get_folios_tag()

Converted function to use folios throughout. This is in preparation for
the removal of find_get_pgaes_range_tag().

Also had to modify and rename gfs2_write_jdata_pagevec() to take in
and utilize folio_batch rather than pagevec and use folios rather
than pages. gfs2_write_jdata_batch() now supports large folios.

Signed-off-by: Vishal Moola (Oracle) <[email protected]>
---
fs/gfs2/aops.c | 64 +++++++++++++++++++++++++++-----------------------
1 file changed, 35 insertions(+), 29 deletions(-)

diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index 05bee80ac7de..8f87c2551a3d 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -195,67 +195,71 @@ static int gfs2_writepages(struct address_space *mapping,
}

/**
- * gfs2_write_jdata_pagevec - Write back a pagevec's worth of pages
+ * gfs2_write_jdata_batch - Write back a folio batch's worth of folios
* @mapping: The mapping
* @wbc: The writeback control
- * @pvec: The vector of pages
- * @nr_pages: The number of pages to write
+ * @fbatch: The batch of folios
* @done_index: Page index
*
* Returns: non-zero if loop should terminate, zero otherwise
*/

-static int gfs2_write_jdata_pagevec(struct address_space *mapping,
+static int gfs2_write_jdata_batch(struct address_space *mapping,
struct writeback_control *wbc,
- struct pagevec *pvec,
- int nr_pages,
+ struct folio_batch *fbatch,
pgoff_t *done_index)
{
struct inode *inode = mapping->host;
struct gfs2_sbd *sdp = GFS2_SB(inode);
- unsigned nrblocks = nr_pages * (PAGE_SIZE >> inode->i_blkbits);
+ unsigned nrblocks;
int i;
int ret;
+ int nr_pages = 0;
+ int nr_folios = folio_batch_count(fbatch);
+
+ for (i = 0; i < nr_folios; i++)
+ nr_pages += folio_nr_pages(fbatch->folios[i]);
+ nrblocks = nr_pages * (PAGE_SIZE >> inode->i_blkbits);

ret = gfs2_trans_begin(sdp, nrblocks, nrblocks);
if (ret < 0)
return ret;

- for(i = 0; i < nr_pages; i++) {
- struct page *page = pvec->pages[i];
+ for (i = 0; i < nr_folios; i++) {
+ struct folio *folio = fbatch->folios[i];

- *done_index = page->index;
+ *done_index = folio->index;

- lock_page(page);
+ folio_lock(folio);

- if (unlikely(page->mapping != mapping)) {
+ if (unlikely(folio->mapping != mapping)) {
continue_unlock:
- unlock_page(page);
+ folio_unlock(folio);
continue;
}

- if (!PageDirty(page)) {
+ if (!folio_test_dirty(folio)) {
/* someone wrote it for us */
goto continue_unlock;
}

- if (PageWriteback(page)) {
+ if (folio_test_writeback(folio)) {
if (wbc->sync_mode != WB_SYNC_NONE)
- wait_on_page_writeback(page);
+ folio_wait_writeback(folio);
else
goto continue_unlock;
}

- BUG_ON(PageWriteback(page));
- if (!clear_page_dirty_for_io(page))
+ BUG_ON(folio_test_writeback(folio));
+ if (!folio_clear_dirty_for_io(folio))
goto continue_unlock;

trace_wbc_writepage(wbc, inode_to_bdi(inode));

- ret = __gfs2_jdata_writepage(page, wbc);
+ ret = __gfs2_jdata_writepage(&folio->page, wbc);
if (unlikely(ret)) {
if (ret == AOP_WRITEPAGE_ACTIVATE) {
- unlock_page(page);
+ folio_unlock(folio);
ret = 0;
} else {

@@ -268,7 +272,8 @@ static int gfs2_write_jdata_pagevec(struct address_space *mapping,
* not be suitable for data integrity
* writeout).
*/
- *done_index = page->index + 1;
+ *done_index = folio->index +
+ folio_nr_pages(folio);
ret = 1;
break;
}
@@ -305,8 +310,8 @@ static int gfs2_write_cache_jdata(struct address_space *mapping,
{
int ret = 0;
int done = 0;
- struct pagevec pvec;
- int nr_pages;
+ struct folio_batch fbatch;
+ int nr_folios;
pgoff_t writeback_index;
pgoff_t index;
pgoff_t end;
@@ -315,7 +320,7 @@ static int gfs2_write_cache_jdata(struct address_space *mapping,
int range_whole = 0;
xa_mark_t tag;

- pagevec_init(&pvec);
+ folio_batch_init(&fbatch);
if (wbc->range_cyclic) {
writeback_index = mapping->writeback_index; /* prev offset */
index = writeback_index;
@@ -341,17 +346,18 @@ static int gfs2_write_cache_jdata(struct address_space *mapping,
tag_pages_for_writeback(mapping, index, end);
done_index = index;
while (!done && (index <= end)) {
- nr_pages = pagevec_lookup_range_tag(&pvec, mapping, &index, end,
- tag);
- if (nr_pages == 0)
+ nr_folios = filemap_get_folios_tag(mapping, &index, end,
+ tag, &fbatch);
+ if (nr_folios == 0)
break;

- ret = gfs2_write_jdata_pagevec(mapping, wbc, &pvec, nr_pages, &done_index);
+ ret = gfs2_write_jdata_batch(mapping, wbc, &fbatch,
+ &done_index);
if (ret)
done = 1;
if (ret > 0)
ret = 0;
- pagevec_release(&pvec);
+ folio_batch_release(&fbatch);
cond_resched();
}

--
2.36.1