On 2022-05-17 14:30, David Sterba wrote: > On Mon, May 16, 2022 at 06:54:10PM +0200, Pankaj Raghav wrote: >> Add helpers to calculate alignment, round up and round down >> for zoned devices. These helpers encapsulates the necessary handling for >> power_of_2 and non-power_of_2 zone sizes. Optimized calculations are >> performed for zone sizes that are power_of_2 with log and shifts. >> >> btrfs_zoned_is_aligned() is added instead of reusing bdev_zone_aligned() >> helper due to some use cases in btrfs where zone alignment is checked >> before having access to the underlying block device such as in this >> function: btrfs_load_block_group_zone_info(). >> >> Use the generic btrfs zone helpers to calculate zone index, check zone >> alignment, round up and round down operations. >> >> The zone_size_shift field is not needed anymore as generic helpers are >> used for calculation. > > Overall this looks reasonable to me. > >> Reviewed-by: Luis Chamberlain <mcgrof@xxxxxxxxxx> >> Signed-off-by: Pankaj Raghav <p.raghav@xxxxxxxxxxx> >> --- >> fs/btrfs/volumes.c | 24 +++++++++------- >> fs/btrfs/zoned.c | 72 ++++++++++++++++++++++------------------------ >> fs/btrfs/zoned.h | 43 +++++++++++++++++++++++---- >> 3 files changed, 85 insertions(+), 54 deletions(-) >> >> --- a/fs/btrfs/zoned.c >> +++ b/fs/btrfs/zoned.c >> @@ -1108,14 +1101,14 @@ int btrfs_reset_device_zone(struct btrfs_device *device, u64 physical, >> int btrfs_ensure_empty_zones(struct btrfs_device *device, u64 start, u64 size) >> { >> struct btrfs_zoned_device_info *zinfo = device->zone_info; >> - const u8 shift = zinfo->zone_size_shift; >> - unsigned long begin = start >> shift; >> - unsigned long end = (start + size) >> shift; >> + unsigned long begin = bdev_zone_no(device->bdev, start >> SECTOR_SHIFT); >> + unsigned long end = >> + bdev_zone_no(device->bdev, (start + size) >> SECTOR_SHIFT); > > There are unsinged long types here though I'd rather see u64, better for > a separate patch. Fixed width types are cleaner here and in the zoned > code as there's always some conversion to/from sectors. > Ok. I will probably send a separate patch to convert them to fix width types. Is it ok if I do it as a separate patch instead of including it in this series? >> u64 pos; >> int ret; >> >> - ASSERT(IS_ALIGNED(start, zinfo->zone_size)); >> - ASSERT(IS_ALIGNED(size, zinfo->zone_size)); >> + ASSERT(btrfs_zoned_is_aligned(start, zinfo->zone_size)); >> + ASSERT(btrfs_zoned_is_aligned(size, zinfo->zone_size)); >> >> if (end > zinfo->nr_zones) >> return -ERANGE; >> --- a/fs/btrfs/zoned.h >> +++ b/fs/btrfs/zoned.h >> @@ -30,6 +30,36 @@ struct btrfs_zoned_device_info { >> u32 sb_zone_location[BTRFS_SUPER_MIRROR_MAX]; >> }; >> >> +static inline bool btrfs_zoned_is_aligned(u64 pos, u64 zone_size) >> +{ >> + u64 remainder = 0; >> + >> + if (is_power_of_two_u64(zone_size)) >> + return IS_ALIGNED(pos, zone_size); >> + >> + div64_u64_rem(pos, zone_size, &remainder); >> + return remainder == 0; >> +} >> + >> +static inline u64 btrfs_zoned_roundup(u64 pos, u64 zone_size) >> +{ >> + if (is_power_of_two_u64(zone_size)) >> + return ALIGN(pos, zone_size); > > Please use round_up as the rounddown helper uses round_down > Ah, good catch. I will use it instead. Thanks. >> + >> + return div64_u64(pos + zone_size - 1, zone_size) * zone_size; >> +} >> + >> +static inline u64 btrfs_zoned_rounddown(u64 pos, u64 zone_size) >> +{ >> + u64 remainder = 0; >> + if (is_power_of_two_u64(zone_size)) >> + return round_down(pos, zone_size); >> + >> + div64_u64_rem(pos, zone_size, &remainder); >> + pos -= remainder; >> + return pos; >> +} >> + >> #ifdef CONFIG_BLK_DEV_ZONED >> int btrfs_get_dev_zone(struct btrfs_device *device, u64 pos, >> struct blk_zone *zone);