Instead of calculating the superblock location every time, cache the superblock zone location in btrfs_zoned_device_info struct and use it to locate the zone index. The functions such as btrfs_sb_log_location_bdev() and btrfs_reset_sb_log_zones() which work directly on block_device shall continue to use the sb_zone_number because btrfs_zoned_device_info struct might not have been initialized at that point. This patch will enable non power-of-2 zoned devices to not perform division to lookup superblock and its mirror location. Reviewed-by: Luis Chamberlain <mcgrof@xxxxxxxxxx> Signed-off-by: Pankaj Raghav <p.raghav@xxxxxxxxxxx> --- fs/btrfs/zoned.c | 13 +++++++++---- fs/btrfs/zoned.h | 1 + 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c index 06f22c021..e8c7cebb2 100644 --- a/fs/btrfs/zoned.c +++ b/fs/btrfs/zoned.c @@ -511,6 +511,11 @@ int btrfs_get_dev_zone_info(struct btrfs_device *device, bool populate_cache) max_active_zones - nactive); } + /* Cache the sb zone number */ + for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; ++i) { + zone_info->sb_zone_location[i] = + sb_zone_number(zone_info->zone_size_shift, i); + } /* Validate superblock log */ nr_zones = BTRFS_NR_SB_LOG_ZONES; for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) { @@ -518,7 +523,7 @@ int btrfs_get_dev_zone_info(struct btrfs_device *device, bool populate_cache) u64 sb_wp; int sb_pos = BTRFS_NR_SB_LOG_ZONES * i; - sb_zone = sb_zone_number(zone_info->zone_size_shift, i); + sb_zone = zone_info->sb_zone_location[i]; if (sb_zone + 1 >= zone_info->nr_zones) continue; @@ -866,7 +871,7 @@ int btrfs_sb_log_location(struct btrfs_device *device, int mirror, int rw, return 0; } - zone_num = sb_zone_number(zinfo->zone_size_shift, mirror); + zone_num = zinfo->sb_zone_location[mirror]; if (zone_num + 1 >= zinfo->nr_zones) return -ENOENT; @@ -883,7 +888,7 @@ static inline bool is_sb_log_zone(struct btrfs_zoned_device_info *zinfo, if (!zinfo) return false; - zone_num = sb_zone_number(zinfo->zone_size_shift, mirror); + zone_num = zinfo->sb_zone_location[mirror]; if (zone_num + 1 >= zinfo->nr_zones) return false; @@ -1011,7 +1016,7 @@ u64 btrfs_find_allocatable_zones(struct btrfs_device *device, u64 hole_start, u32 sb_zone; u64 sb_pos; - sb_zone = sb_zone_number(shift, i); + sb_zone = zinfo->sb_zone_location[i]; if (!(end <= sb_zone || sb_zone + BTRFS_NR_SB_LOG_ZONES <= begin)) { have_sb = true; diff --git a/fs/btrfs/zoned.h b/fs/btrfs/zoned.h index 10f31d1c8..694ab6d1e 100644 --- a/fs/btrfs/zoned.h +++ b/fs/btrfs/zoned.h @@ -27,6 +27,7 @@ struct btrfs_zoned_device_info { unsigned long *active_zones; struct blk_zone *zone_cache; struct blk_zone sb_zones[2 * BTRFS_SUPER_MIRROR_MAX]; + u32 sb_zone_location[BTRFS_SUPER_MIRROR_MAX]; }; #ifdef CONFIG_BLK_DEV_ZONED -- 2.25.1