@@ -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);