Re: [PATCH v4 07/13] btrfs: zoned: use generic btrfs zone helpers to support npo2 zoned devices
From: Naohiro Aota <Naohiro.Aota@wdc.com>
Date: 2022-05-19 04:13:35
Also in:
dm-devel, linux-btrfs, linux-fsdevel, linux-nvme, lkml
On Mon, May 16, 2022 at 06:54:10PM +0200, Pankaj Raghav wrote:
quoted hunk ↗ jump to hunk
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. Reviewed-by: Luis Chamberlain <mcgrof@kernel.org> Signed-off-by: Pankaj Raghav <redacted> --- fs/btrfs/volumes.c | 24 +++++++++------- fs/btrfs/zoned.c | 72 ++++++++++++++++++++++------------------------ fs/btrfs/zoned.h | 43 +++++++++++++++++++++++---- 3 files changed, 85 insertions(+), 54 deletions(-) <snip>diff --git a/fs/btrfs/zoned.h b/fs/btrfs/zoned.h index 694ab6d1e..b94ce4d1f 100644 --- a/fs/btrfs/zoned.h +++ b/fs/btrfs/zoned.h@@ -9,6 +9,7 @@ #include "disk-io.h" #include "block-group.h" #include "btrfs_inode.h" +#include "misc.h" #define BTRFS_DEFAULT_RECLAIM_THRESH (75)@@ -18,7 +19,6 @@ struct btrfs_zoned_device_info { * zoned block device. */ u64 zone_size; - u8 zone_size_shift; u32 nr_zones; unsigned int max_active_zones; atomic_t active_zones_left;@@ -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); + + 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; +} +
This is just a preference, but how about naming these helpers not related
to "zoned"? While they take "zone_size" as an argument, it does not do
anything special on zoned things. For my preference, I would take
btrfs_device or btrfs_zoned_device_info for "btrfs_zoned_*" function.
Actually, I was a bit confused seeing the part
below. btrfs_zoned_is_aligned() takes "sector_t" values while the arguments
are often byte granularity address. Yeah, actually sector_t == u64 and the
code does not relies on the unit ... so, it is OK as long as the values are
in the same unit.
@@ -409,9 +409,8 @@ int btrfs_get_dev_zone_info(struct btrfs_device *device, bool populate_cache)
}
nr_sectors = bdev_nr_sectors(bdev);
- zone_info->zone_size_shift = ilog2(zone_info->zone_size);
- zone_info->nr_zones = nr_sectors >> ilog2(zone_sectors);
- if (!IS_ALIGNED(nr_sectors, zone_sectors))
+ zone_info->nr_zones = bdev_zone_no(bdev, nr_sectors);
+ if (!btrfs_zoned_is_aligned(nr_sectors, zone_sectors))
zone_info->nr_zones++;
max_active_zones = bdev_max_active_zones(bdev);
BTW, aren't these helpers used in other subsystems? Maybe adding these in
include/linux/math64.h or so?