Re: [PATCH 07/10] btrfs: use folios for reading super blocks from the block device
From: Qu Wenruo
Date: Mon Sep 07 2026 - 02:56:45 EST
在 2026/9/7 07:59, 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
Signed-off-by: Tal Zussman <tz2294@xxxxxxxxxxxx>
Reviewed-by: Qu Wenruo <wqu@xxxxxxxx>
Thanks,
Qu
---
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]) >