btrfs: use folios for reading super blocks from the block device

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>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
Tal Zussman 2026-09-07 16:20:01 -04:00 committed by David Sterba
parent dcfc00dc02
commit cf7ded644e
2 changed files with 13 additions and 15 deletions

View File

@ -1358,16 +1358,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;
@ -1388,7 +1386,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,
@ -1396,12 +1394,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);

View File

@ -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]) >