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

Reply via email to