mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v2 0/7] btrfs: convert some struct page users to folios
@ 2026-09-07 20:19 Tal Zussman
  2026-09-07 20:19 ` [PATCH v2 1/7] btrfs: tests: rename process_page_range() to process_folio_range() Tal Zussman
                   ` (7 more replies)
  0 siblings, 8 replies; 14+ messages in thread
From: Tal Zussman @ 2026-09-07 20:19 UTC (permalink / raw)
  To: David Sterba, Chris Mason, Qu Wenruo
  Cc: Matthew Wilcox (Oracle), linux-btrfs, linux-kernel, Tal Zussman

This series converts three areas of btrfs that still use struct page:

1. The extent-io tests. test_find_delalloc() uses the page APIs, and the
   extent buffer memory checks assume one page per folio.

2. Compression. btrfs_compr_pool_scan() walks the folio pool as struct
   page, the last use of page->lru in btrfs, and the heuristic sampler
   is the last caller of find_get_page().

3. Super block reads. btrfs_read_disk_super() and the zoned super block
   log comparison are the last page cache lookups by page in btrfs.

Tested with KASAN, lockdep, DEBUG_VM and the btrfs selftests enabled.
xfstests' compress group under compress=zstd and the btrfs group both
pass.

---
Changes in v2:
- Add tags (Thanks Qu!)
- Patch 2: Assert that test_find_delalloc()'s folios are order-0, per Qu
- Drop the v1 free space cache patches (8-10), per Qu. The v1 space
  cache will be removed instead
- Link to v1: https://patch.msgid.link/20260906-btrfs-folio-conversions-v1-0-834b9d7b06f5@columbia.edu

---
Tal Zussman (7):
      btrfs: tests: rename process_page_range() to process_folio_range()
      btrfs: tests: convert test_find_delalloc() to use folios
      btrfs: tests: use eb folio helpers in extent buffer memory checks
      btrfs: convert btrfs_compr_pool_scan() to use folios
      btrfs: convert heuristic_collect_sample() to use folios
      btrfs: fix stale function references in compression comments
      btrfs: use folios for reading super blocks from the block device

 fs/btrfs/compression.c           |  20 +++---
 fs/btrfs/tests/extent-io-tests.c | 131 +++++++++++++++++++++------------------
 fs/btrfs/volumes.c               |  16 +++--
 fs/btrfs/zoned.c                 |  12 ++--
 4 files changed, 93 insertions(+), 86 deletions(-)
---
base-commit: 69b26c13e520480d1869171e2c2b8a59f0c857ec
change-id: 20260905-btrfs-folio-conversions-47950cc1faca

Best regards,
--  
Tal Zussman <tz2294@columbia.edu>


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v2 1/7] btrfs: tests: rename process_page_range() to process_folio_range()
  2026-09-07 20:19 [PATCH v2 0/7] btrfs: convert some struct page users to folios Tal Zussman
@ 2026-09-07 20:19 ` Tal Zussman
  2026-09-07 20:19 ` [PATCH v2 2/7] btrfs: tests: convert test_find_delalloc() to use folios Tal Zussman
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 14+ messages in thread
From: Tal Zussman @ 2026-09-07 20:19 UTC (permalink / raw)
  To: David Sterba, Chris Mason, Qu Wenruo
  Cc: Matthew Wilcox (Oracle), linux-btrfs, linux-kernel, Tal Zussman

It already operates on folios. No functional change.

Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
---
 fs/btrfs/tests/extent-io-tests.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/fs/btrfs/tests/extent-io-tests.c b/fs/btrfs/tests/extent-io-tests.c
index 23459cd4e503..6eb55bfb2bd4 100644
--- a/fs/btrfs/tests/extent-io-tests.c
+++ b/fs/btrfs/tests/extent-io-tests.c
@@ -18,8 +18,8 @@
 #define PROCESS_RELEASE		(1U << 1)
 #define PROCESS_TEST_LOCKED	(1U << 2)
 
-static noinline int process_page_range(struct inode *inode, u64 start, u64 end,
-				       unsigned long flags)
+static noinline int process_folio_range(struct inode *inode, u64 start, u64 end,
+					unsigned long flags)
 {
 	int ret;
 	struct folio_batch fbatch;
@@ -221,8 +221,8 @@ static int test_find_delalloc(u32 sectorsize, u32 nodesize)
 				test_start, max_bytes - 1, start, end);
 		goto out_bits;
 	}
-	if (process_page_range(inode, start, end,
-			       PROCESS_TEST_LOCKED | PROCESS_UNLOCK)) {
+	if (process_folio_range(inode, start, end,
+				PROCESS_TEST_LOCKED | PROCESS_UNLOCK)) {
 		test_err("there were unlocked pages in the range");
 		goto out_bits;
 	}
@@ -276,8 +276,8 @@ static int test_find_delalloc(u32 sectorsize, u32 nodesize)
 			 test_start, total_dirty - 1, start, end);
 		goto out_bits;
 	}
-	if (process_page_range(inode, start, end,
-			       PROCESS_TEST_LOCKED | PROCESS_UNLOCK)) {
+	if (process_folio_range(inode, start, end,
+				PROCESS_TEST_LOCKED | PROCESS_UNLOCK)) {
 		test_err("pages in range were not all locked");
 		goto out_bits;
 	}
@@ -317,8 +317,8 @@ static int test_find_delalloc(u32 sectorsize, u32 nodesize)
 			 test_start, test_start + PAGE_SIZE - 1, start, end);
 		goto out_bits;
 	}
-	if (process_page_range(inode, start, end, PROCESS_TEST_LOCKED |
-			       PROCESS_UNLOCK)) {
+	if (process_folio_range(inode, start, end, PROCESS_TEST_LOCKED |
+				PROCESS_UNLOCK)) {
 		test_err("pages in range were not all locked");
 		goto out_bits;
 	}
@@ -330,8 +330,8 @@ static int test_find_delalloc(u32 sectorsize, u32 nodesize)
 out:
 	if (locked_page)
 		put_page(locked_page);
-	process_page_range(inode, 0, total_dirty - 1,
-			   PROCESS_UNLOCK | PROCESS_RELEASE);
+	process_folio_range(inode, 0, total_dirty - 1,
+			    PROCESS_UNLOCK | PROCESS_RELEASE);
 	iput(inode);
 out_root_info:
 	btrfs_free_dummy_root(root);

-- 
2.39.5


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v2 2/7] btrfs: tests: convert test_find_delalloc() to use folios
  2026-09-07 20:19 [PATCH v2 0/7] btrfs: convert some struct page users to folios Tal Zussman
  2026-09-07 20:19 ` [PATCH v2 1/7] btrfs: tests: rename process_page_range() to process_folio_range() Tal Zussman
@ 2026-09-07 20:19 ` Tal Zussman
  2026-09-09  4:56   ` Qu Wenruo
  2026-09-07 20:19 ` [PATCH v2 3/7] btrfs: tests: use eb folio helpers in extent buffer memory checks Tal Zussman
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 14+ messages in thread
From: Tal Zussman @ 2026-09-07 20:19 UTC (permalink / raw)
  To: David Sterba, Chris Mason, Qu Wenruo
  Cc: Matthew Wilcox (Oracle), linux-btrfs, linux-kernel, Tal Zussman

This removes the last btrfs callers of find_or_create_page(),
find_lock_page(), SetPageDirty(), ClearPageDirty(), and get_page(), and
15 calls to compound_head(). The folio lookups return an ERR_PTR instead
of NULL, so adjust the error handling.

Update the comments and test messages accordingly.

The test still works in PAGE_SIZE units, which relies on the test inode
never getting large folios, so assert that the folios are order-0 where
that matters.

Signed-off-by: Tal Zussman <tz2294@columbia.edu>
---
 fs/btrfs/tests/extent-io-tests.c | 99 +++++++++++++++++++++-------------------
 1 file changed, 51 insertions(+), 48 deletions(-)

diff --git a/fs/btrfs/tests/extent-io-tests.c b/fs/btrfs/tests/extent-io-tests.c
index 6eb55bfb2bd4..e7aa8bc04706 100644
--- a/fs/btrfs/tests/extent-io-tests.c
+++ b/fs/btrfs/tests/extent-io-tests.c
@@ -112,8 +112,8 @@ static int test_find_delalloc(u32 sectorsize, u32 nodesize)
 	struct btrfs_root *root = NULL;
 	struct inode *inode = NULL;
 	struct extent_io_tree *tmp;
-	struct page *page;
-	struct page *locked_page = NULL;
+	struct folio *folio;
+	struct folio *locked_folio = NULL;
 	/* In this test we need at least 2 file extents at its maximum size */
 	u64 max_bytes = BTRFS_MAX_EXTENT_SIZE;
 	u64 total_dirty = 2 * max_bytes;
@@ -152,23 +152,26 @@ static int test_find_delalloc(u32 sectorsize, u32 nodesize)
 	btrfs_extent_io_tree_init(NULL, tmp, IO_TREE_SELFTEST);
 
 	/*
-	 * First go through and create and mark all of our pages dirty, we pin
-	 * everything to make sure our pages don't get evicted and screw up our
+	 * First go through and create and mark all of our folios dirty, we pin
+	 * everything to make sure our folios don't get evicted and screw up our
 	 * test.
 	 */
 	for (pgoff_t index = 0; index < (total_dirty >> PAGE_SHIFT); index++) {
-		page = find_or_create_page(inode->i_mapping, index, GFP_KERNEL);
-		if (!page) {
-			test_err("failed to allocate test page");
-			ret = -ENOMEM;
+		folio = __filemap_get_folio(inode->i_mapping, index,
+				FGP_LOCK | FGP_ACCESSED | FGP_CREAT, GFP_KERNEL);
+		if (IS_ERR(folio)) {
+			test_err("failed to allocate test folio");
+			ret = PTR_ERR(folio);
 			goto out;
 		}
-		SetPageDirty(page);
+		/* The ranges below assume page sized folios. */
+		ASSERT(folio_order(folio) == 0);
+		folio_set_dirty(folio);
 		if (index) {
-			unlock_page(page);
+			folio_unlock(folio);
 		} else {
-			get_page(page);
-			locked_page = page;
+			folio_get(folio);
+			locked_folio = folio;
 		}
 	}
 
@@ -179,8 +182,7 @@ static int test_find_delalloc(u32 sectorsize, u32 nodesize)
 	btrfs_set_extent_bit(tmp, 0, sectorsize - 1, EXTENT_DELALLOC, NULL);
 	start = 0;
 	end = start + PAGE_SIZE - 1;
-	found = find_lock_delalloc_range(inode, page_folio(locked_page), &start,
-					 &end);
+	found = find_lock_delalloc_range(inode, locked_folio, &start, &end);
 	if (!found) {
 		test_err("should have found at least one delalloc");
 		goto out_bits;
@@ -191,8 +193,8 @@ static int test_find_delalloc(u32 sectorsize, u32 nodesize)
 		goto out_bits;
 	}
 	btrfs_unlock_extent(tmp, start, end, NULL);
-	unlock_page(locked_page);
-	put_page(locked_page);
+	folio_unlock(locked_folio);
+	folio_put(locked_folio);
 
 	/*
 	 * Test this scenario
@@ -201,17 +203,18 @@ static int test_find_delalloc(u32 sectorsize, u32 nodesize)
 	 *           |--- search ---|
 	 */
 	test_start = SZ_64M;
-	locked_page = find_lock_page(inode->i_mapping,
-				     test_start >> PAGE_SHIFT);
-	if (!locked_page) {
-		test_err("couldn't find the locked page");
+	locked_folio = filemap_lock_folio(inode->i_mapping,
+					  test_start >> PAGE_SHIFT);
+	if (IS_ERR(locked_folio)) {
+		test_err("couldn't find the locked folio");
+		locked_folio = NULL;
 		goto out_bits;
 	}
+	ASSERT(folio_order(locked_folio) == 0);
 	btrfs_set_extent_bit(tmp, sectorsize, max_bytes - 1, EXTENT_DELALLOC, NULL);
 	start = test_start;
 	end = start + PAGE_SIZE - 1;
-	found = find_lock_delalloc_range(inode, page_folio(locked_page), &start,
-					 &end);
+	found = find_lock_delalloc_range(inode, locked_folio, &start, &end);
 	if (!found) {
 		test_err("couldn't find delalloc in our range");
 		goto out_bits;
@@ -223,12 +226,12 @@ static int test_find_delalloc(u32 sectorsize, u32 nodesize)
 	}
 	if (process_folio_range(inode, start, end,
 				PROCESS_TEST_LOCKED | PROCESS_UNLOCK)) {
-		test_err("there were unlocked pages in the range");
+		test_err("there were unlocked folios in the range");
 		goto out_bits;
 	}
 	btrfs_unlock_extent(tmp, start, end, NULL);
-	/* locked_page was unlocked above */
-	put_page(locked_page);
+	/* locked_folio was unlocked above */
+	folio_put(locked_folio);
 
 	/*
 	 * Test this scenario
@@ -236,16 +239,17 @@ static int test_find_delalloc(u32 sectorsize, u32 nodesize)
 	 *                    |--- search ---|
 	 */
 	test_start = max_bytes + sectorsize;
-	locked_page = find_lock_page(inode->i_mapping, test_start >>
-				     PAGE_SHIFT);
-	if (!locked_page) {
-		test_err("couldn't find the locked page");
+	locked_folio = filemap_lock_folio(inode->i_mapping,
+					  test_start >> PAGE_SHIFT);
+	if (IS_ERR(locked_folio)) {
+		test_err("couldn't find the locked folio");
+		locked_folio = NULL;
 		goto out_bits;
 	}
+	ASSERT(folio_order(locked_folio) == 0);
 	start = test_start;
 	end = start + PAGE_SIZE - 1;
-	found = find_lock_delalloc_range(inode, page_folio(locked_page), &start,
-					 &end);
+	found = find_lock_delalloc_range(inode, locked_folio, &start, &end);
 	if (found) {
 		test_err("found range when we shouldn't have");
 		goto out_bits;
@@ -265,8 +269,7 @@ static int test_find_delalloc(u32 sectorsize, u32 nodesize)
 	btrfs_set_extent_bit(tmp, max_bytes, total_dirty - 1, EXTENT_DELALLOC, NULL);
 	start = test_start;
 	end = start + PAGE_SIZE - 1;
-	found = find_lock_delalloc_range(inode, page_folio(locked_page), &start,
-					 &end);
+	found = find_lock_delalloc_range(inode, locked_folio, &start, &end);
 	if (!found) {
 		test_err("didn't find our range");
 		goto out_bits;
@@ -278,36 +281,36 @@ static int test_find_delalloc(u32 sectorsize, u32 nodesize)
 	}
 	if (process_folio_range(inode, start, end,
 				PROCESS_TEST_LOCKED | PROCESS_UNLOCK)) {
-		test_err("pages in range were not all locked");
+		test_err("folios in range were not all locked");
 		goto out_bits;
 	}
 	btrfs_unlock_extent(tmp, start, end, NULL);
 
 	/*
-	 * Now to test where we run into a page that is no longer dirty in the
+	 * Now to test where we run into a folio that is no longer dirty in the
 	 * range we want to find.
 	 */
-	page = find_get_page(inode->i_mapping,
-			     (max_bytes + SZ_1M) >> PAGE_SHIFT);
-	if (!page) {
-		test_err("couldn't find our page");
+	folio = filemap_get_folio(inode->i_mapping,
+				  (max_bytes + SZ_1M) >> PAGE_SHIFT);
+	if (IS_ERR(folio)) {
+		test_err("couldn't find our folio");
 		goto out_bits;
 	}
-	ClearPageDirty(page);
-	put_page(page);
+	ASSERT(folio_order(folio) == 0);
+	folio_clear_dirty(folio);
+	folio_put(folio);
 
 	/* We unlocked it in the previous test */
-	lock_page(locked_page);
+	folio_lock(locked_folio);
 	start = test_start;
 	end = start + PAGE_SIZE - 1;
 	/*
-	 * Currently if we fail to find dirty pages in the delalloc range we
+	 * Currently if we fail to find dirty folios in the delalloc range we
 	 * will adjust max_bytes down to PAGE_SIZE and then re-search.  If
 	 * this changes at any point in the future we will need to fix this
 	 * tests expected behavior.
 	 */
-	found = find_lock_delalloc_range(inode, page_folio(locked_page), &start,
-					 &end);
+	found = find_lock_delalloc_range(inode, locked_folio, &start, &end);
 	if (!found) {
 		test_err("didn't find our range");
 		goto out_bits;
@@ -319,7 +322,7 @@ static int test_find_delalloc(u32 sectorsize, u32 nodesize)
 	}
 	if (process_folio_range(inode, start, end, PROCESS_TEST_LOCKED |
 				PROCESS_UNLOCK)) {
-		test_err("pages in range were not all locked");
+		test_err("folios in range were not all locked");
 		goto out_bits;
 	}
 	ret = 0;
@@ -328,8 +331,8 @@ static int test_find_delalloc(u32 sectorsize, u32 nodesize)
 		dump_extent_io_tree(tmp);
 	btrfs_clear_extent_bit(tmp, 0, total_dirty - 1, (unsigned)-1, NULL);
 out:
-	if (locked_page)
-		put_page(locked_page);
+	if (locked_folio)
+		folio_put(locked_folio);
 	process_folio_range(inode, 0, total_dirty - 1,
 			    PROCESS_UNLOCK | PROCESS_RELEASE);
 	iput(inode);

-- 
2.39.5


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v2 3/7] btrfs: tests: use eb folio helpers in extent buffer memory checks
  2026-09-07 20:19 [PATCH v2 0/7] btrfs: convert some struct page users to folios Tal Zussman
  2026-09-07 20:19 ` [PATCH v2 1/7] btrfs: tests: rename process_page_range() to process_folio_range() Tal Zussman
  2026-09-07 20:19 ` [PATCH v2 2/7] btrfs: tests: convert test_find_delalloc() to use folios Tal Zussman
@ 2026-09-07 20:19 ` Tal Zussman
  2026-09-07 20:19 ` [PATCH v2 4/7] btrfs: convert btrfs_compr_pool_scan() to use folios Tal Zussman
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 14+ messages in thread
From: Tal Zussman @ 2026-09-07 20:19 UTC (permalink / raw)
  To: David Sterba, Chris Mason, Qu Wenruo
  Cc: Matthew Wilcox (Oracle), linux-btrfs, linux-kernel, Tal Zussman

dump_eb_and_memory_contents() and verify_eb_and_memory() hardcode one
page per folio instead of using get_eb_folio_index() and
get_eb_offset_in_folio() like the rest of the extent buffer code. Use
the helpers and folio_address(). This removes the last struct page usage
in the file.

No functional change. The tests only run with sectorsize == PAGE_SIZE,
and the test extent buffers are backed by order-0 folios.

Assisted-by: Claude:claude-fable-5-1
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
---
 fs/btrfs/tests/extent-io-tests.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/fs/btrfs/tests/extent-io-tests.c b/fs/btrfs/tests/extent-io-tests.c
index e7aa8bc04706..777caace717e 100644
--- a/fs/btrfs/tests/extent-io-tests.c
+++ b/fs/btrfs/tests/extent-io-tests.c
@@ -674,8 +674,9 @@ static void dump_eb_and_memory_contents(struct extent_buffer *eb, void *memory,
 					const char *test_name)
 {
 	for (int i = 0; i < eb->len; i++) {
-		struct page *page = folio_page(eb->folios[i >> PAGE_SHIFT], 0);
-		void *addr = page_address(page) + offset_in_page(i);
+		const unsigned long idx = get_eb_folio_index(eb, i);
+		void *addr = folio_address(eb->folios[idx]) +
+			     get_eb_offset_in_folio(eb, i);
 
 		if (memcmp(addr, memory + i, 1) != 0) {
 			test_err("%s failed", test_name);
@@ -690,9 +691,12 @@ static int verify_eb_and_memory(struct extent_buffer *eb, void *memory,
 				const char *test_name)
 {
 	for (int i = 0; i < (eb->len >> PAGE_SHIFT); i++) {
-		void *eb_addr = folio_address(eb->folios[i]);
+		const unsigned long offset = i << PAGE_SHIFT;
+		const unsigned long idx = get_eb_folio_index(eb, offset);
+		void *eb_addr = folio_address(eb->folios[idx]) +
+				get_eb_offset_in_folio(eb, offset);
 
-		if (memcmp(memory + (i << PAGE_SHIFT), eb_addr, PAGE_SIZE) != 0) {
+		if (memcmp(memory + offset, eb_addr, PAGE_SIZE) != 0) {
 			dump_eb_and_memory_contents(eb, memory, test_name);
 			return -EUCLEAN;
 		}

-- 
2.39.5


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v2 4/7] btrfs: convert btrfs_compr_pool_scan() to use folios
  2026-09-07 20:19 [PATCH v2 0/7] btrfs: convert some struct page users to folios Tal Zussman
                   ` (2 preceding siblings ...)
  2026-09-07 20:19 ` [PATCH v2 3/7] btrfs: tests: use eb folio helpers in extent buffer memory checks Tal Zussman
@ 2026-09-07 20:19 ` Tal Zussman
  2026-09-07 20:19 ` [PATCH v2 5/7] btrfs: convert heuristic_collect_sample() " Tal Zussman
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 14+ messages in thread
From: Tal Zussman @ 2026-09-07 20:19 UTC (permalink / raw)
  To: David Sterba, Chris Mason, Qu Wenruo
  Cc: Matthew Wilcox (Oracle), linux-btrfs, linux-kernel, Tal Zussman

The compression pool holds order-0 folios, but btrfs_compr_pool_scan()
walks it as struct page through page->lru. Walk it as folios, matching
the other compression pool functions. This removes the last use of
page->lru in btrfs and saves a call to compound_head() per freed
folio.

Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
---
 fs/btrfs/compression.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c
index c62b5148d5ac..979b2ffbd8fc 100644
--- a/fs/btrfs/compression.c
+++ b/fs/btrfs/compression.c
@@ -168,10 +168,10 @@ static unsigned long btrfs_compr_pool_scan(struct shrinker *sh, struct shrink_co
 	spin_unlock(&compr_pool.lock);
 
 	list_for_each_safe(tmp, next, &remove) {
-		struct page *page = list_entry(tmp, struct page, lru);
+		struct folio *folio = list_entry(tmp, struct folio, lru);
 
-		ASSERT(page_ref_count(page) == 1);
-		put_page(page);
+		ASSERT(folio_ref_count(folio) == 1);
+		folio_put(folio);
 	}
 
 	return freed;

-- 
2.39.5


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v2 5/7] btrfs: convert heuristic_collect_sample() to use folios
  2026-09-07 20:19 [PATCH v2 0/7] btrfs: convert some struct page users to folios Tal Zussman
                   ` (3 preceding siblings ...)
  2026-09-07 20:19 ` [PATCH v2 4/7] btrfs: convert btrfs_compr_pool_scan() to use folios Tal Zussman
@ 2026-09-07 20:19 ` Tal Zussman
  2026-09-09  1:26   ` David Sterba
  2026-09-07 20:20 ` [PATCH v2 6/7] btrfs: fix stale function references in compression comments Tal Zussman
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 14+ messages in thread
From: Tal Zussman @ 2026-09-07 20:19 UTC (permalink / raw)
  To: David Sterba, Chris Mason, Qu Wenruo
  Cc: Matthew Wilcox (Oracle), linux-btrfs, linux-kernel, Tal Zussman

Convert the sampling loop to folios. This removes the last caller of
find_get_page() in btrfs and saves a call to compound_head() per sampled
page. Document that the lookup is not supposed to fail with an ASSERT().

Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
---
 fs/btrfs/compression.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c
index 979b2ffbd8fc..fa8b92592321 100644
--- a/fs/btrfs/compression.c
+++ b/fs/btrfs/compression.c
@@ -1488,7 +1488,7 @@ static bool sample_repeated_patterns(struct heuristic_ws *ws)
 static void heuristic_collect_sample(struct inode *inode, u64 start, u64 end,
 				     struct heuristic_ws *ws)
 {
-	struct page *page;
+	struct folio *folio;
 	pgoff_t index, index_end;
 	u32 i, curr_sample_pos;
 	u8 *in_data;
@@ -1514,8 +1514,10 @@ static void heuristic_collect_sample(struct inode *inode, u64 start, u64 end,
 
 	curr_sample_pos = 0;
 	while (index < index_end) {
-		page = find_get_page(inode->i_mapping, index);
-		in_data = kmap_local_page(page);
+		folio = filemap_get_folio(inode->i_mapping, index);
+		ASSERT(!IS_ERR(folio));
+		in_data = kmap_local_folio(folio,
+				offset_in_folio(folio, (u64)index << PAGE_SHIFT));
 		/* Handle case where the start is not aligned to PAGE_SIZE */
 		i = start % PAGE_SIZE;
 		while (i < PAGE_SIZE - SAMPLING_READ_SIZE) {
@@ -1529,7 +1531,7 @@ static void heuristic_collect_sample(struct inode *inode, u64 start, u64 end,
 			curr_sample_pos += SAMPLING_READ_SIZE;
 		}
 		kunmap_local(in_data);
-		put_page(page);
+		folio_put(folio);
 
 		index++;
 	}

-- 
2.39.5


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v2 6/7] btrfs: fix stale function references in compression comments
  2026-09-07 20:19 [PATCH v2 0/7] btrfs: convert some struct page users to folios Tal Zussman
                   ` (4 preceding siblings ...)
  2026-09-07 20:19 ` [PATCH v2 5/7] btrfs: convert heuristic_collect_sample() " Tal Zussman
@ 2026-09-07 20:20 ` Tal Zussman
  2026-09-07 20:20 ` [PATCH v2 7/7] btrfs: use folios for reading super blocks from the block device Tal Zussman
  2026-09-09  6:10 ` [PATCH v2 0/7] btrfs: convert some struct page users to folios Qu Wenruo
  7 siblings, 0 replies; 14+ messages in thread
From: Tal Zussman @ 2026-09-07 20:20 UTC (permalink / raw)
  To: David Sterba, Chris Mason, Qu Wenruo
  Cc: Matthew Wilcox (Oracle), linux-btrfs, linux-kernel, Tal Zussman

add_ra_bio_pages() was renamed to add_ra_bio_folios(), and
btrfs_compress_filemap_get_folio() wraps filemap_get_folio(), not
find_get_page(). Update the comments accordingly.

Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
---
 fs/btrfs/compression.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c
index fa8b92592321..20169d028961 100644
--- a/fs/btrfs/compression.c
+++ b/fs/btrfs/compression.c
@@ -431,7 +431,7 @@ static noinline int add_ra_bio_folios(struct inode *inode, u64 compressed_end,
 		}
 
 		/*
-		 * Since add_ra_bio_pages() is always speculative, suppress
+		 * Since add_ra_bio_folios() is always speculative, suppress
 		 * allocation warnings.
 		 */
 		masked_constraint_gfp = mapping_gfp_constraint(mapping, constraint_gfp);
@@ -960,7 +960,7 @@ bool btrfs_compress_level_valid(unsigned int type, int level)
 	return levels->min_level <= level && level <= levels->max_level;
 }
 
-/* Wrapper around find_get_page(), with extra error message. */
+/* Wrapper around filemap_get_folio(), with extra error message. */
 int btrfs_compress_filemap_get_folio(struct address_space *mapping, u64 start,
 				     struct folio **in_folio_ret)
 {

-- 
2.39.5


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v2 7/7] btrfs: use folios for reading super blocks from the block device
  2026-09-07 20:19 [PATCH v2 0/7] btrfs: convert some struct page users to folios Tal Zussman
                   ` (5 preceding siblings ...)
  2026-09-07 20:20 ` [PATCH v2 6/7] btrfs: fix stale function references in compression comments Tal Zussman
@ 2026-09-07 20:20 ` Tal Zussman
  2026-09-09  6:10 ` [PATCH v2 0/7] btrfs: convert some struct page users to folios Qu Wenruo
  7 siblings, 0 replies; 14+ messages in thread
From: Tal Zussman @ 2026-09-07 20:20 UTC (permalink / raw)
  To: David Sterba, Chris Mason, Qu Wenruo
  Cc: Matthew Wilcox (Oracle), linux-btrfs, linux-kernel, Tal Zussman

btrfs_read_disk_super() and the zoned super block log comparison go
through read_cache_page_gfp() and page_address(), and
btrfs_release_disk_super() recovers the page with virt_to_page(). Use
mapping_read_folio_gfp(), folio_address(), and virt_to_folio() instead.
This removes the last callers of read_cache_page_gfp() and put_page()
in btrfs.

Compute the super block address with offset_in_folio() as
write_dev_supers() does, rather than assuming it is at the start of
the page.

Assisted-by: Claude:claude-fable-5-1
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
---
 fs/btrfs/volumes.c | 16 +++++++---------
 fs/btrfs/zoned.c   | 12 ++++++------
 2 files changed, 13 insertions(+), 15 deletions(-)

diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 949e40baff33..4ddabadc9188 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -1327,16 +1327,14 @@ int btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
 
 void btrfs_release_disk_super(struct btrfs_super_block *super)
 {
-	struct page *page = virt_to_page(super);
-
-	put_page(page);
+	folio_put(virt_to_folio(super));
 }
 
 struct btrfs_super_block *btrfs_read_disk_super(struct block_device *bdev,
 						int copy_num, bool drop_cache)
 {
 	struct btrfs_super_block *super;
-	struct page *page;
+	struct folio *folio;
 	u64 bytenr, bytenr_orig;
 	struct address_space *mapping = bdev->bd_mapping;
 	int ret;
@@ -1357,7 +1355,7 @@ struct btrfs_super_block *btrfs_read_disk_super(struct block_device *bdev,
 		ASSERT(copy_num == 0);
 
 		/*
-		 * Drop the page of the primary superblock, so later read will
+		 * Drop the folio of the primary superblock, so later read will
 		 * always read from the device.
 		 */
 		invalidate_inode_pages2_range(mapping, bytenr >> PAGE_SHIFT,
@@ -1365,12 +1363,12 @@ struct btrfs_super_block *btrfs_read_disk_super(struct block_device *bdev,
 	}
 
 	filemap_invalidate_lock_shared(mapping);
-	page = read_cache_page_gfp(mapping, bytenr >> PAGE_SHIFT, GFP_NOFS);
+	folio = mapping_read_folio_gfp(mapping, bytenr >> PAGE_SHIFT, GFP_NOFS);
 	filemap_invalidate_unlock_shared(mapping);
-	if (IS_ERR(page))
-		return ERR_CAST(page);
+	if (IS_ERR(folio))
+		return ERR_CAST(folio);
 
-	super = page_address(page);
+	super = folio_address(folio) + offset_in_folio(folio, bytenr);
 	if (btrfs_super_magic(super) != BTRFS_MAGIC ||
 	    btrfs_super_bytenr(super) != bytenr_orig) {
 		btrfs_release_disk_super(super);
diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c
index 08a15465a087..a1ef8caaacda 100644
--- a/fs/btrfs/zoned.c
+++ b/fs/btrfs/zoned.c
@@ -123,24 +123,24 @@ static int sb_write_pointer(struct block_device *bdev, struct blk_zone *zones,
 	} else if (full[0] && full[1]) {
 		/* Compare two super blocks */
 		struct address_space *mapping = bdev->bd_mapping;
-		struct page *page[BTRFS_NR_SB_LOG_ZONES];
 		struct btrfs_super_block *super[BTRFS_NR_SB_LOG_ZONES];
 
 		for (int i = 0; i < BTRFS_NR_SB_LOG_ZONES; i++) {
 			u64 zone_end = (zones[i].start + zones[i].capacity) << SECTOR_SHIFT;
 			u64 bytenr = ALIGN_DOWN(zone_end, BTRFS_SUPER_INFO_SIZE) -
 						BTRFS_SUPER_INFO_SIZE;
+			struct folio *folio;
 
 			filemap_invalidate_lock_shared(mapping);
-			page[i] = read_cache_page_gfp(mapping,
-					bytenr >> PAGE_SHIFT, GFP_NOFS);
+			folio = mapping_read_folio_gfp(mapping, bytenr >> PAGE_SHIFT,
+						       GFP_NOFS);
 			filemap_invalidate_unlock_shared(mapping);
-			if (IS_ERR(page[i])) {
+			if (IS_ERR(folio)) {
 				if (i == 1)
 					btrfs_release_disk_super(super[0]);
-				return PTR_ERR(page[i]);
+				return PTR_ERR(folio);
 			}
-			super[i] = page_address(page[i]);
+			super[i] = folio_address(folio) + offset_in_folio(folio, bytenr);
 		}
 
 		if (btrfs_super_generation(super[0]) >

-- 
2.39.5


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v2 5/7] btrfs: convert heuristic_collect_sample() to use folios
  2026-09-07 20:19 ` [PATCH v2 5/7] btrfs: convert heuristic_collect_sample() " Tal Zussman
@ 2026-09-09  1:26   ` David Sterba
  2026-09-09  4:25     ` Tal Zussman
  0 siblings, 1 reply; 14+ messages in thread
From: David Sterba @ 2026-09-09  1:26 UTC (permalink / raw)
  To: Tal Zussman
  Cc: David Sterba, Chris Mason, Qu Wenruo, Matthew Wilcox (Oracle),
	linux-btrfs, linux-kernel

On Mon, Sep 07, 2026 at 04:19:59PM -0400, Tal Zussman wrote:
> Convert the sampling loop to folios. This removes the last caller of
> find_get_page() in btrfs and saves a call to compound_head() per sampled
> page. Document that the lookup is not supposed to fail with an ASSERT().
> 
> Reviewed-by: Qu Wenruo <wqu@suse.com>
> Signed-off-by: Tal Zussman <tz2294@columbia.edu>
> ---
>  fs/btrfs/compression.c | 10 ++++++----
>  1 file changed, 6 insertions(+), 4 deletions(-)
> 
> diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c
> index 979b2ffbd8fc..fa8b92592321 100644
> --- a/fs/btrfs/compression.c
> +++ b/fs/btrfs/compression.c
> @@ -1488,7 +1488,7 @@ static bool sample_repeated_patterns(struct heuristic_ws *ws)
>  static void heuristic_collect_sample(struct inode *inode, u64 start, u64 end,
>  				     struct heuristic_ws *ws)
>  {
> -	struct page *page;
> +	struct folio *folio;
>  	pgoff_t index, index_end;
>  	u32 i, curr_sample_pos;
>  	u8 *in_data;
> @@ -1514,8 +1514,10 @@ static void heuristic_collect_sample(struct inode *inode, u64 start, u64 end,
>  
>  	curr_sample_pos = 0;
>  	while (index < index_end) {
> -		page = find_get_page(inode->i_mapping, index);
> -		in_data = kmap_local_page(page);
> +		folio = filemap_get_folio(inode->i_mapping, index);
> +		ASSERT(!IS_ERR(folio));
> +		in_data = kmap_local_folio(folio,
> +				offset_in_folio(folio, (u64)index << PAGE_SHIFT));

It would be better to avoid the cast, this is source of subtle errors so
we try to avoid that. With demise of 32bit architectures it's less of a
problem because index (pgoff_t) is 64 bit type but still.

Please insert a patch that changes the type of index and index_end to
u64, we initialize them from a u64 type anyway and we know the value
fits to pgoff_t (as argument to filemap_get_folio()).

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v2 5/7] btrfs: convert heuristic_collect_sample() to use folios
  2026-09-09  1:26   ` David Sterba
@ 2026-09-09  4:25     ` Tal Zussman
  0 siblings, 0 replies; 14+ messages in thread
From: Tal Zussman @ 2026-09-09  4:25 UTC (permalink / raw)
  To: dsterba
  Cc: David Sterba, Chris Mason, Qu Wenruo, Matthew Wilcox (Oracle),
	linux-btrfs, linux-kernel

On 9/9/26 4:26 AM, David Sterba wrote:
> On Mon, Sep 07, 2026 at 04:19:59PM -0400, Tal Zussman wrote:
>> Convert the sampling loop to folios. This removes the last caller of
>> find_get_page() in btrfs and saves a call to compound_head() per sampled
>> page. Document that the lookup is not supposed to fail with an ASSERT().
>> 
>> Reviewed-by: Qu Wenruo <wqu@suse.com>
>> Signed-off-by: Tal Zussman <tz2294@columbia.edu>
>> ---
>>  fs/btrfs/compression.c | 10 ++++++----
>>  1 file changed, 6 insertions(+), 4 deletions(-)
>> 
>> diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c
>> index 979b2ffbd8fc..fa8b92592321 100644
>> --- a/fs/btrfs/compression.c
>> +++ b/fs/btrfs/compression.c
>> @@ -1488,7 +1488,7 @@ static bool sample_repeated_patterns(struct heuristic_ws *ws)
>>  static void heuristic_collect_sample(struct inode *inode, u64 start, u64 end,
>>  				     struct heuristic_ws *ws)
>>  {
>> -	struct page *page;
>> +	struct folio *folio;
>>  	pgoff_t index, index_end;
>>  	u32 i, curr_sample_pos;
>>  	u8 *in_data;
>> @@ -1514,8 +1514,10 @@ static void heuristic_collect_sample(struct inode *inode, u64 start, u64 end,
>>  
>>  	curr_sample_pos = 0;
>>  	while (index < index_end) {
>> -		page = find_get_page(inode->i_mapping, index);
>> -		in_data = kmap_local_page(page);
>> +		folio = filemap_get_folio(inode->i_mapping, index);
>> +		ASSERT(!IS_ERR(folio));
>> +		in_data = kmap_local_folio(folio,
>> +				offset_in_folio(folio, (u64)index << PAGE_SHIFT));
> 
> It would be better to avoid the cast, this is source of subtle errors so
> we try to avoid that. With demise of 32bit architectures it's less of a
> problem because index (pgoff_t) is 64 bit type but still.
> 
> Please insert a patch that changes the type of index and index_end to
> u64, we initialize them from a u64 type anyway and we know the value
> fits to pgoff_t (as argument to filemap_get_folio()).
> 

Makes sense, will do.


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v2 2/7] btrfs: tests: convert test_find_delalloc() to use folios
  2026-09-07 20:19 ` [PATCH v2 2/7] btrfs: tests: convert test_find_delalloc() to use folios Tal Zussman
@ 2026-09-09  4:56   ` Qu Wenruo
  0 siblings, 0 replies; 14+ messages in thread
From: Qu Wenruo @ 2026-09-09  4:56 UTC (permalink / raw)
  To: Tal Zussman, David Sterba, Chris Mason
  Cc: Matthew Wilcox (Oracle), linux-btrfs, linux-kernel



在 2026/9/8 05:49, Tal Zussman 写道:
> This removes the last btrfs callers of find_or_create_page(),
> find_lock_page(), SetPageDirty(), ClearPageDirty(), and get_page(), and
> 15 calls to compound_head(). The folio lookups return an ERR_PTR instead
> of NULL, so adjust the error handling.
> 
> Update the comments and test messages accordingly.
> 
> The test still works in PAGE_SIZE units, which relies on the test inode
> never getting large folios, so assert that the folios are order-0 where
> that matters.
> 
> Signed-off-by: Tal Zussman <tz2294@columbia.edu>

Reviewed-by: Qu Wenruo <wqu@suse.com>

Thanks,
Qu> ---
>   fs/btrfs/tests/extent-io-tests.c | 99 +++++++++++++++++++++-------------------
>   1 file changed, 51 insertions(+), 48 deletions(-)
> 
> diff --git a/fs/btrfs/tests/extent-io-tests.c b/fs/btrfs/tests/extent-io-tests.c
> index 6eb55bfb2bd4..e7aa8bc04706 100644
> --- a/fs/btrfs/tests/extent-io-tests.c
> +++ b/fs/btrfs/tests/extent-io-tests.c
> @@ -112,8 +112,8 @@ static int test_find_delalloc(u32 sectorsize, u32 nodesize)
>   	struct btrfs_root *root = NULL;
>   	struct inode *inode = NULL;
>   	struct extent_io_tree *tmp;
> -	struct page *page;
> -	struct page *locked_page = NULL;
> +	struct folio *folio;
> +	struct folio *locked_folio = NULL;
>   	/* In this test we need at least 2 file extents at its maximum size */
>   	u64 max_bytes = BTRFS_MAX_EXTENT_SIZE;
>   	u64 total_dirty = 2 * max_bytes;
> @@ -152,23 +152,26 @@ static int test_find_delalloc(u32 sectorsize, u32 nodesize)
>   	btrfs_extent_io_tree_init(NULL, tmp, IO_TREE_SELFTEST);
>   
>   	/*
> -	 * First go through and create and mark all of our pages dirty, we pin
> -	 * everything to make sure our pages don't get evicted and screw up our
> +	 * First go through and create and mark all of our folios dirty, we pin
> +	 * everything to make sure our folios don't get evicted and screw up our
>   	 * test.
>   	 */
>   	for (pgoff_t index = 0; index < (total_dirty >> PAGE_SHIFT); index++) {
> -		page = find_or_create_page(inode->i_mapping, index, GFP_KERNEL);
> -		if (!page) {
> -			test_err("failed to allocate test page");
> -			ret = -ENOMEM;
> +		folio = __filemap_get_folio(inode->i_mapping, index,
> +				FGP_LOCK | FGP_ACCESSED | FGP_CREAT, GFP_KERNEL);
> +		if (IS_ERR(folio)) {
> +			test_err("failed to allocate test folio");
> +			ret = PTR_ERR(folio);
>   			goto out;
>   		}
> -		SetPageDirty(page);
> +		/* The ranges below assume page sized folios. */
> +		ASSERT(folio_order(folio) == 0);
> +		folio_set_dirty(folio);
>   		if (index) {
> -			unlock_page(page);
> +			folio_unlock(folio);
>   		} else {
> -			get_page(page);
> -			locked_page = page;
> +			folio_get(folio);
> +			locked_folio = folio;
>   		}
>   	}
>   
> @@ -179,8 +182,7 @@ static int test_find_delalloc(u32 sectorsize, u32 nodesize)
>   	btrfs_set_extent_bit(tmp, 0, sectorsize - 1, EXTENT_DELALLOC, NULL);
>   	start = 0;
>   	end = start + PAGE_SIZE - 1;
> -	found = find_lock_delalloc_range(inode, page_folio(locked_page), &start,
> -					 &end);
> +	found = find_lock_delalloc_range(inode, locked_folio, &start, &end);
>   	if (!found) {
>   		test_err("should have found at least one delalloc");
>   		goto out_bits;
> @@ -191,8 +193,8 @@ static int test_find_delalloc(u32 sectorsize, u32 nodesize)
>   		goto out_bits;
>   	}
>   	btrfs_unlock_extent(tmp, start, end, NULL);
> -	unlock_page(locked_page);
> -	put_page(locked_page);
> +	folio_unlock(locked_folio);
> +	folio_put(locked_folio);
>   
>   	/*
>   	 * Test this scenario
> @@ -201,17 +203,18 @@ static int test_find_delalloc(u32 sectorsize, u32 nodesize)
>   	 *           |--- search ---|
>   	 */
>   	test_start = SZ_64M;
> -	locked_page = find_lock_page(inode->i_mapping,
> -				     test_start >> PAGE_SHIFT);
> -	if (!locked_page) {
> -		test_err("couldn't find the locked page");
> +	locked_folio = filemap_lock_folio(inode->i_mapping,
> +					  test_start >> PAGE_SHIFT);
> +	if (IS_ERR(locked_folio)) {
> +		test_err("couldn't find the locked folio");
> +		locked_folio = NULL;
>   		goto out_bits;
>   	}
> +	ASSERT(folio_order(locked_folio) == 0);
>   	btrfs_set_extent_bit(tmp, sectorsize, max_bytes - 1, EXTENT_DELALLOC, NULL);
>   	start = test_start;
>   	end = start + PAGE_SIZE - 1;
> -	found = find_lock_delalloc_range(inode, page_folio(locked_page), &start,
> -					 &end);
> +	found = find_lock_delalloc_range(inode, locked_folio, &start, &end);
>   	if (!found) {
>   		test_err("couldn't find delalloc in our range");
>   		goto out_bits;
> @@ -223,12 +226,12 @@ static int test_find_delalloc(u32 sectorsize, u32 nodesize)
>   	}
>   	if (process_folio_range(inode, start, end,
>   				PROCESS_TEST_LOCKED | PROCESS_UNLOCK)) {
> -		test_err("there were unlocked pages in the range");
> +		test_err("there were unlocked folios in the range");
>   		goto out_bits;
>   	}
>   	btrfs_unlock_extent(tmp, start, end, NULL);
> -	/* locked_page was unlocked above */
> -	put_page(locked_page);
> +	/* locked_folio was unlocked above */
> +	folio_put(locked_folio);
>   
>   	/*
>   	 * Test this scenario
> @@ -236,16 +239,17 @@ static int test_find_delalloc(u32 sectorsize, u32 nodesize)
>   	 *                    |--- search ---|
>   	 */
>   	test_start = max_bytes + sectorsize;
> -	locked_page = find_lock_page(inode->i_mapping, test_start >>
> -				     PAGE_SHIFT);
> -	if (!locked_page) {
> -		test_err("couldn't find the locked page");
> +	locked_folio = filemap_lock_folio(inode->i_mapping,
> +					  test_start >> PAGE_SHIFT);
> +	if (IS_ERR(locked_folio)) {
> +		test_err("couldn't find the locked folio");
> +		locked_folio = NULL;
>   		goto out_bits;
>   	}
> +	ASSERT(folio_order(locked_folio) == 0);
>   	start = test_start;
>   	end = start + PAGE_SIZE - 1;
> -	found = find_lock_delalloc_range(inode, page_folio(locked_page), &start,
> -					 &end);
> +	found = find_lock_delalloc_range(inode, locked_folio, &start, &end);
>   	if (found) {
>   		test_err("found range when we shouldn't have");
>   		goto out_bits;
> @@ -265,8 +269,7 @@ static int test_find_delalloc(u32 sectorsize, u32 nodesize)
>   	btrfs_set_extent_bit(tmp, max_bytes, total_dirty - 1, EXTENT_DELALLOC, NULL);
>   	start = test_start;
>   	end = start + PAGE_SIZE - 1;
> -	found = find_lock_delalloc_range(inode, page_folio(locked_page), &start,
> -					 &end);
> +	found = find_lock_delalloc_range(inode, locked_folio, &start, &end);
>   	if (!found) {
>   		test_err("didn't find our range");
>   		goto out_bits;
> @@ -278,36 +281,36 @@ static int test_find_delalloc(u32 sectorsize, u32 nodesize)
>   	}
>   	if (process_folio_range(inode, start, end,
>   				PROCESS_TEST_LOCKED | PROCESS_UNLOCK)) {
> -		test_err("pages in range were not all locked");
> +		test_err("folios in range were not all locked");
>   		goto out_bits;
>   	}
>   	btrfs_unlock_extent(tmp, start, end, NULL);
>   
>   	/*
> -	 * Now to test where we run into a page that is no longer dirty in the
> +	 * Now to test where we run into a folio that is no longer dirty in the
>   	 * range we want to find.
>   	 */
> -	page = find_get_page(inode->i_mapping,
> -			     (max_bytes + SZ_1M) >> PAGE_SHIFT);
> -	if (!page) {
> -		test_err("couldn't find our page");
> +	folio = filemap_get_folio(inode->i_mapping,
> +				  (max_bytes + SZ_1M) >> PAGE_SHIFT);
> +	if (IS_ERR(folio)) {
> +		test_err("couldn't find our folio");
>   		goto out_bits;
>   	}
> -	ClearPageDirty(page);
> -	put_page(page);
> +	ASSERT(folio_order(folio) == 0);
> +	folio_clear_dirty(folio);
> +	folio_put(folio);
>   
>   	/* We unlocked it in the previous test */
> -	lock_page(locked_page);
> +	folio_lock(locked_folio);
>   	start = test_start;
>   	end = start + PAGE_SIZE - 1;
>   	/*
> -	 * Currently if we fail to find dirty pages in the delalloc range we
> +	 * Currently if we fail to find dirty folios in the delalloc range we
>   	 * will adjust max_bytes down to PAGE_SIZE and then re-search.  If
>   	 * this changes at any point in the future we will need to fix this
>   	 * tests expected behavior.
>   	 */
> -	found = find_lock_delalloc_range(inode, page_folio(locked_page), &start,
> -					 &end);
> +	found = find_lock_delalloc_range(inode, locked_folio, &start, &end);
>   	if (!found) {
>   		test_err("didn't find our range");
>   		goto out_bits;
> @@ -319,7 +322,7 @@ static int test_find_delalloc(u32 sectorsize, u32 nodesize)
>   	}
>   	if (process_folio_range(inode, start, end, PROCESS_TEST_LOCKED |
>   				PROCESS_UNLOCK)) {
> -		test_err("pages in range were not all locked");
> +		test_err("folios in range were not all locked");
>   		goto out_bits;
>   	}
>   	ret = 0;
> @@ -328,8 +331,8 @@ static int test_find_delalloc(u32 sectorsize, u32 nodesize)
>   		dump_extent_io_tree(tmp);
>   	btrfs_clear_extent_bit(tmp, 0, total_dirty - 1, (unsigned)-1, NULL);
>   out:
> -	if (locked_page)
> -		put_page(locked_page);
> +	if (locked_folio)
> +		folio_put(locked_folio);
>   	process_folio_range(inode, 0, total_dirty - 1,
>   			    PROCESS_UNLOCK | PROCESS_RELEASE);
>   	iput(inode);
> 


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v2 0/7] btrfs: convert some struct page users to folios
  2026-09-07 20:19 [PATCH v2 0/7] btrfs: convert some struct page users to folios Tal Zussman
                   ` (6 preceding siblings ...)
  2026-09-07 20:20 ` [PATCH v2 7/7] btrfs: use folios for reading super blocks from the block device Tal Zussman
@ 2026-09-09  6:10 ` Qu Wenruo
  2026-09-09 14:03   ` David Sterba
  7 siblings, 1 reply; 14+ messages in thread
From: Qu Wenruo @ 2026-09-09  6:10 UTC (permalink / raw)
  To: Tal Zussman, David Sterba, Chris Mason
  Cc: Matthew Wilcox (Oracle), linux-btrfs, linux-kernel



在 2026/9/8 05:49, Tal Zussman 写道:
> This series converts three areas of btrfs that still use struct page:
> 
> 1. The extent-io tests. test_find_delalloc() uses the page APIs, and the
>     extent buffer memory checks assume one page per folio.
> 
> 2. Compression. btrfs_compr_pool_scan() walks the folio pool as struct
>     page, the last use of page->lru in btrfs, and the heuristic sampler
>     is the last caller of find_get_page().
> 
> 3. Super block reads. btrfs_read_disk_super() and the zoned super block
>     log comparison are the last page cache lookups by page in btrfs.
> 
> Tested with KASAN, lockdep, DEBUG_VM and the btrfs selftests enabled.
> xfstests' compress group under compress=zstd and the btrfs group both
> pass.

Now pushed to for-next branch.

Thanks,
Qu

> 
> ---
> Changes in v2:
> - Add tags (Thanks Qu!)
> - Patch 2: Assert that test_find_delalloc()'s folios are order-0, per Qu
> - Drop the v1 free space cache patches (8-10), per Qu. The v1 space
>    cache will be removed instead
> - Link to v1: https://patch.msgid.link/20260906-btrfs-folio-conversions-v1-0-834b9d7b06f5@columbia.edu
> 
> ---
> Tal Zussman (7):
>        btrfs: tests: rename process_page_range() to process_folio_range()
>        btrfs: tests: convert test_find_delalloc() to use folios
>        btrfs: tests: use eb folio helpers in extent buffer memory checks
>        btrfs: convert btrfs_compr_pool_scan() to use folios
>        btrfs: convert heuristic_collect_sample() to use folios
>        btrfs: fix stale function references in compression comments
>        btrfs: use folios for reading super blocks from the block device
> 
>   fs/btrfs/compression.c           |  20 +++---
>   fs/btrfs/tests/extent-io-tests.c | 131 +++++++++++++++++++++------------------
>   fs/btrfs/volumes.c               |  16 +++--
>   fs/btrfs/zoned.c                 |  12 ++--
>   4 files changed, 93 insertions(+), 86 deletions(-)
> ---
> base-commit: 69b26c13e520480d1869171e2c2b8a59f0c857ec
> change-id: 20260905-btrfs-folio-conversions-47950cc1faca
> 
> Best regards,
> --
> Tal Zussman <tz2294@columbia.edu>


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v2 0/7] btrfs: convert some struct page users to folios
  2026-09-09  6:10 ` [PATCH v2 0/7] btrfs: convert some struct page users to folios Qu Wenruo
@ 2026-09-09 14:03   ` David Sterba
  2026-09-09 17:30     ` Tal Zussman
  0 siblings, 1 reply; 14+ messages in thread
From: David Sterba @ 2026-09-09 14:03 UTC (permalink / raw)
  To: Tal Zussman
  Cc: Qu Wenruo, David Sterba, Chris Mason, Matthew Wilcox (Oracle),
	linux-btrfs, linux-kernel

On Wed, Sep 09, 2026 at 03:40:47PM +0930, Qu Wenruo wrote:
> 
> 
> 在 2026/9/8 05:49, Tal Zussman 写道:
> > This series converts three areas of btrfs that still use struct page:
> > 
> > 1. The extent-io tests. test_find_delalloc() uses the page APIs, and the
> >     extent buffer memory checks assume one page per folio.
> > 
> > 2. Compression. btrfs_compr_pool_scan() walks the folio pool as struct
> >     page, the last use of page->lru in btrfs, and the heuristic sampler
> >     is the last caller of find_get_page().
> > 
> > 3. Super block reads. btrfs_read_disk_super() and the zoned super block
> >     log comparison are the last page cache lookups by page in btrfs.
> > 
> > Tested with KASAN, lockdep, DEBUG_VM and the btrfs selftests enabled.
> > xfstests' compress group under compress=zstd and the btrfs group both
> > pass.
> 
> Now pushed to for-next branch.

Tal, please send the cast removal I asked for in patch 5 separately. Thanks.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v2 0/7] btrfs: convert some struct page users to folios
  2026-09-09 14:03   ` David Sterba
@ 2026-09-09 17:30     ` Tal Zussman
  0 siblings, 0 replies; 14+ messages in thread
From: Tal Zussman @ 2026-09-09 17:30 UTC (permalink / raw)
  To: dsterba
  Cc: Qu Wenruo, David Sterba, Chris Mason, Matthew Wilcox (Oracle),
	linux-btrfs, linux-kernel

On 9/9/26 5:03 PM, David Sterba wrote:
> On Wed, Sep 09, 2026 at 03:40:47PM +0930, Qu Wenruo wrote:
>> 
>> 
>> 在 2026/9/8 05:49, Tal Zussman 写道:
>> > This series converts three areas of btrfs that still use struct page:
>> > 
>> > 1. The extent-io tests. test_find_delalloc() uses the page APIs, and the
>> >     extent buffer memory checks assume one page per folio.
>> > 
>> > 2. Compression. btrfs_compr_pool_scan() walks the folio pool as struct
>> >     page, the last use of page->lru in btrfs, and the heuristic sampler
>> >     is the last caller of find_get_page().
>> > 
>> > 3. Super block reads. btrfs_read_disk_super() and the zoned super block
>> >     log comparison are the last page cache lookups by page in btrfs.
>> > 
>> > Tested with KASAN, lockdep, DEBUG_VM and the btrfs selftests enabled.
>> > xfstests' compress group under compress=zstd and the btrfs group both
>> > pass.
>> 
>> Now pushed to for-next branch.
> 
> Tal, please send the cast removal I asked for in patch 5 separately. Thanks.
> 

Done: https://lore.kernel.org/linux-btrfs/20260909-btrfs-heuristic-u64-index-v1-1-8606b3c89807@columbia.edu/T/#u

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2026-09-09 17:31 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-07 20:19 [PATCH v2 0/7] btrfs: convert some struct page users to folios Tal Zussman
2026-09-07 20:19 ` [PATCH v2 1/7] btrfs: tests: rename process_page_range() to process_folio_range() Tal Zussman
2026-09-07 20:19 ` [PATCH v2 2/7] btrfs: tests: convert test_find_delalloc() to use folios Tal Zussman
2026-09-09  4:56   ` Qu Wenruo
2026-09-07 20:19 ` [PATCH v2 3/7] btrfs: tests: use eb folio helpers in extent buffer memory checks Tal Zussman
2026-09-07 20:19 ` [PATCH v2 4/7] btrfs: convert btrfs_compr_pool_scan() to use folios Tal Zussman
2026-09-07 20:19 ` [PATCH v2 5/7] btrfs: convert heuristic_collect_sample() " Tal Zussman
2026-09-09  1:26   ` David Sterba
2026-09-09  4:25     ` Tal Zussman
2026-09-07 20:20 ` [PATCH v2 6/7] btrfs: fix stale function references in compression comments Tal Zussman
2026-09-07 20:20 ` [PATCH v2 7/7] btrfs: use folios for reading super blocks from the block device Tal Zussman
2026-09-09  6:10 ` [PATCH v2 0/7] btrfs: convert some struct page users to folios Qu Wenruo
2026-09-09 14:03   ` David Sterba
2026-09-09 17:30     ` Tal Zussman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®