From: Luis Chamberlain <[email protected]> f2fs currently only work with zoned storage devices with a zone size which is a power of 2 (PO2). So check if a non-power of 2 zoned device is found, and if so disallow its use. This prevents users from incorrectly using these devices.
This is a non-issue today given today's kernel does not allow NPO2 zoned devices to exist as a block device. But NPO2 zoned devices do exist so proactively put a stop-gap measure in place to prevent it from being incorrectly used. Signed-off-by: Luis Chamberlain <[email protected]> Signed-off-by: Pankaj Raghav <[email protected]> --- Changes since v1: - Squash the commits for clarity (Damien) - f2fs_get_zone_chunk_sectors can return uint32_t (Damien) - Include the units for zone size in msg info (Damien) - Sections can be npo2 but it should only be a multiple of 2MB (Jaegeuk) include/f2fs_fs.h | 1 + lib/libf2fs.c | 17 +++++++++++++++-- lib/libf2fs_zoned.c | 34 ++++++++++++++++++++++------------ 3 files changed, 38 insertions(+), 14 deletions(-) diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h index d236437..83c5b33 100644 --- a/include/f2fs_fs.h +++ b/include/f2fs_fs.h @@ -386,6 +386,7 @@ struct device_info { u_int32_t nr_zones; u_int32_t nr_rnd_zones; size_t zone_blocks; + uint64_t zone_size; size_t *zone_cap_blocks; }; diff --git a/lib/libf2fs.c b/lib/libf2fs.c index 420dfda..8104667 100644 --- a/lib/libf2fs.c +++ b/lib/libf2fs.c @@ -882,6 +882,11 @@ static int open_check_fs(char *path, int flag) return open(path, O_RDONLY | flag); } +static int is_power_of_2(unsigned long n) +{ + return (n != 0 && ((n & (n - 1)) == 0)); +} + int get_device_info(int i) { int32_t fd = 0; @@ -1043,6 +1048,13 @@ int get_device_info(int i) return -1; } + if (!is_power_of_2(dev->zone_size)) { + MSG(0, "\tError: zoned: illegal zone size %lu (not a power of 2)\n", + dev->zone_size); + free(stat_buf); + return -1; + } + /* * Check zone configuration: for the first disk of a * multi-device volume, conventional zones are needed. @@ -1055,8 +1067,9 @@ int get_device_info(int i) MSG(0, "Info: Host-%s zoned block device:\n", (dev->zoned_model == F2FS_ZONED_HA) ? "aware" : "managed"); - MSG(0, " %u zones, %u randomly writeable zones\n", - dev->nr_zones, dev->nr_rnd_zones); + MSG(0, " %u zones, %lu zone size(bytes), %u randomly writeable zones\n", + dev->nr_zones, dev->zone_size, + dev->nr_rnd_zones); MSG(0, " %lu blocks per zone\n", dev->zone_blocks); } diff --git a/lib/libf2fs_zoned.c b/lib/libf2fs_zoned.c index ce73b9a..48a23c0 100644 --- a/lib/libf2fs_zoned.c +++ b/lib/libf2fs_zoned.c @@ -146,40 +146,50 @@ int f2fs_get_zoned_model(int i) return 0; } -int f2fs_get_zone_blocks(int i) +uint32_t f2fs_get_zone_chunk_sectors(struct device_info *dev) { - struct device_info *dev = c.devices + i; - uint64_t sectors; + uint32_t sectors; char str[PATH_MAX]; FILE *file; int res; - /* Get zone size */ - dev->zone_blocks = 0; - res = get_sysfs_path(dev, "queue/chunk_sectors", str, sizeof(str)); if (res != 0) { MSG(0, "\tError: Failed to get device sysfs attribute path\n"); - return -1; + return 0; } file = fopen(str, "r"); if (!file) - return -1; + return 0; memset(str, 0, sizeof(str)); res = fscanf(file, "%s", str); fclose(file); if (res != 1) - return -1; + return 0; - sectors = atol(str); + sectors = atoi(str); + + return sectors; +} + +int f2fs_get_zone_blocks(int i) +{ + struct device_info *dev = c.devices + i; + uint64_t sectors; + + /* Get zone size */ + dev->zone_blocks = 0; + + sectors = f2fs_get_zone_chunk_sectors(dev); if (!sectors) return -1; - dev->zone_blocks = sectors >> (F2FS_BLKSIZE_BITS - 9); - sectors = (sectors << 9) / c.sector_size; + dev->zone_size = sectors << SECTOR_SHIFT; + dev->zone_blocks = sectors >> (F2FS_BLKSIZE_BITS - SECTOR_SHIFT); + sectors = dev->zone_size / c.sector_size; /* * Total number of zones: there may -- 2.25.1 _______________________________________________ Linux-f2fs-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
