Skip to content

Commit 5b434df

Browse files
naotakdave
authored andcommitted
btrfs: zoned: fix zone number to sector/physical calculation
In btrfs_get_dev_zone_info(), we have "u32 sb_zone" and calculate "sector_t sector" by shifting it. But, this "sector" is calculated in 32bit, leading it to be 0 for the 2nd superblock copy. Since zone number is u32, shifting it to sector (sector_t) or physical address (u64) can easily trigger a missing cast bug like this. This commit introduces helpers to convert zone number to sector/LBA, so we won't fall into the same pitfall again. Reported-by: Dmitry Fomichev <[email protected]> Fixes: 1265925 ("btrfs: implement log-structured superblock for ZONED mode") CC: [email protected] # 5.11+ Reviewed-by: Johannes Thumshirn <[email protected]> Signed-off-by: Naohiro Aota <[email protected]> Reviewed-by: David Sterba <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent 165ea85 commit 5b434df

File tree

1 file changed

+18
-5
lines changed

1 file changed

+18
-5
lines changed

fs/btrfs/zoned.c

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,18 @@ static inline u32 sb_zone_number(int shift, int mirror)
150150
return (u32)zone;
151151
}
152152

153+
static inline sector_t zone_start_sector(u32 zone_number,
154+
struct block_device *bdev)
155+
{
156+
return (sector_t)zone_number << ilog2(bdev_zone_sectors(bdev));
157+
}
158+
159+
static inline u64 zone_start_physical(u32 zone_number,
160+
struct btrfs_zoned_device_info *zone_info)
161+
{
162+
return (u64)zone_number << zone_info->zone_size_shift;
163+
}
164+
153165
/*
154166
* Emulate blkdev_report_zones() for a non-zoned device. It slices up the block
155167
* device into static sized chunks and fake a conventional zone on each of
@@ -405,8 +417,8 @@ int btrfs_get_dev_zone_info(struct btrfs_device *device)
405417
if (sb_zone + 1 >= zone_info->nr_zones)
406418
continue;
407419

408-
sector = sb_zone << (zone_info->zone_size_shift - SECTOR_SHIFT);
409-
ret = btrfs_get_dev_zones(device, sector << SECTOR_SHIFT,
420+
ret = btrfs_get_dev_zones(device,
421+
zone_start_physical(sb_zone, zone_info),
410422
&zone_info->sb_zones[sb_pos],
411423
&nr_zones);
412424
if (ret)
@@ -721,7 +733,7 @@ int btrfs_sb_log_location_bdev(struct block_device *bdev, int mirror, int rw,
721733
if (sb_zone + 1 >= nr_zones)
722734
return -ENOENT;
723735

724-
ret = blkdev_report_zones(bdev, sb_zone << zone_sectors_shift,
736+
ret = blkdev_report_zones(bdev, zone_start_sector(sb_zone, bdev),
725737
BTRFS_NR_SB_LOG_ZONES, copy_zone_info_cb,
726738
zones);
727739
if (ret < 0)
@@ -826,7 +838,7 @@ int btrfs_reset_sb_log_zones(struct block_device *bdev, int mirror)
826838
return -ENOENT;
827839

828840
return blkdev_zone_mgmt(bdev, REQ_OP_ZONE_RESET,
829-
sb_zone << zone_sectors_shift,
841+
zone_start_sector(sb_zone, bdev),
830842
zone_sectors * BTRFS_NR_SB_LOG_ZONES, GFP_NOFS);
831843
}
832844

@@ -878,7 +890,8 @@ u64 btrfs_find_allocatable_zones(struct btrfs_device *device, u64 hole_start,
878890
if (!(end <= sb_zone ||
879891
sb_zone + BTRFS_NR_SB_LOG_ZONES <= begin)) {
880892
have_sb = true;
881-
pos = ((u64)sb_zone + BTRFS_NR_SB_LOG_ZONES) << shift;
893+
pos = zone_start_physical(
894+
sb_zone + BTRFS_NR_SB_LOG_ZONES, zinfo);
882895
break;
883896
}
884897

0 commit comments

Comments
 (0)