[PATCH v3 08/11] btrfs: zoned: relax the alignment constraint for zoned devices

From: Pankaj Raghav
Date: Fri May 06 2022 - 04:12:35 EST


Checks were in place to return error when a non power-of-2 zoned devices
is detected. Remove those checks as non power-of-2 zoned devices are
now supported.

Relax the zone size constraint to align with a sane default of 1MB.
This 1M default has been chosen as the minimum alignment requirement
for zone sizes to make sure zones align with sectorsize in different
architectures.

Reviewed-by: Luis Chamberlain <mcgrof@xxxxxxxxxx>
Signed-off-by: Pankaj Raghav <p.raghav@xxxxxxxxxxx>
---
fs/btrfs/zoned.c | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c
index 3023c871e..a6b15fbe1 100644
--- a/fs/btrfs/zoned.c
+++ b/fs/btrfs/zoned.c
@@ -54,6 +54,13 @@
*/
#define BTRFS_MAX_ZONE_SIZE SZ_8G

+/*
+ * A minimum alignment of 1MB is chosen for zoned devices as their zone sizes
+ * can be non power of 2. This is to make sure the zones correctly align to the
+ * sectorsize.
+ */
+#define BTRFS_ZONED_MIN_ALIGN_SECTORS ((u64)SZ_1M >> SECTOR_SHIFT)
+
#define SUPER_INFO_SECTORS ((u64)BTRFS_SUPER_INFO_SIZE >> SECTOR_SHIFT)

static inline bool sb_zone_is_full(const struct blk_zone *zone)
@@ -394,8 +401,8 @@ int btrfs_get_dev_zone_info(struct btrfs_device *device, bool populate_cache)
zone_sectors = bdev_zone_sectors(bdev);
}

- /* Check if it's power of 2 (see is_power_of_2) */
- ASSERT(zone_sectors != 0 && (zone_sectors & (zone_sectors - 1)) == 0);
+ ASSERT(zone_sectors != 0 &&
+ IS_ALIGNED(zone_sectors, BTRFS_ZONED_MIN_ALIGN_SECTORS));
zone_info->zone_size = zone_sectors << SECTOR_SHIFT;

/* We reject devices with a zone size larger than 8GB */
@@ -834,9 +841,11 @@ int btrfs_sb_log_location_bdev(struct block_device *bdev, int mirror, int rw,

ASSERT(rw == READ || rw == WRITE);

- if (!is_power_of_2(bdev_zone_sectors(bdev)))
- return -EINVAL;
nr_sectors = bdev_nr_sectors(bdev);
+
+ if (!IS_ALIGNED(nr_sectors, BTRFS_ZONED_MIN_ALIGN_SECTORS))
+ return -EINVAL;
+
nr_zones = bdev_zone_no(bdev, nr_sectors);

sb_zone = sb_zone_number(bdev, mirror);
--
2.25.1