Hi Chao, thanks for your review.
On 4/17/19 11:21 AM, Chao Yu wrote:
> Hi Shin'ichiro,
>
> On 2019/4/10 16:56, Shin'ichiro Kawasaki wrote:
>> The mkfs.f2fs checks 'zoned' and 'chunk_sectors' sysfs attributes of
>> zoned block devices to place F2FS areas aligned to block zone
>> boundaries. However, mkfs.f2fs code assumes the given device name has
>> corresponding sysfs path under /sys/block directory. This is not the
>> case when partition devices or symbolic links are specified as the
>> command line argument of mkfs.f2fs. In such a case, mkfs.f2fs fails to
>> read sysfs attributes for zoned block devices, handles the device as a
>> regular block device, and do not align F2FS areas to the block zone
>> boundaries. This results in F2FS write failures because of zone write
>> pointer miss-alignment in sequential write required zones.
>>
>> Change mkfs.f2fs to handle sysfs path correctly. Read symbolic link
>> to get canonical sysfs path. If the device is a partition, cut the last
>> directory name in the sysfs path to refer the holder device attributes.
>>
>> Also introduce read_file() and read_sys_attr() helper functions for
>> code simplicity.
>>
>> Signed-off-by: Shin'ichiro Kawasaki <[email protected]>
>> ---
>> lib/libf2fs_zoned.c | 134 ++++++++++++++++++++++++++++++--------------
>> 1 file changed, 91 insertions(+), 43 deletions(-)
>>
>> diff --git a/lib/libf2fs_zoned.c b/lib/libf2fs_zoned.c
>> index 6e32f32..e645004 100644
>> --- a/lib/libf2fs_zoned.c
>> +++ b/lib/libf2fs_zoned.c
>> @@ -8,6 +8,7 @@
>> */
>> #define _LARGEFILE64_SOURCE
>>
>> +#define _GNU_SOURCE
>> #include <stdio.h>
>> #include <stdlib.h>
>> #include <string.h>
>> @@ -15,6 +16,8 @@
>> #include <unistd.h>
>> #include <fcntl.h>
>> #include <sys/stat.h>
>> +#include <sys/sysmacros.h>
>> +#include <linux/limits.h>
>> #ifndef ANDROID_WINDOWS_HOST
>> #include <sys/ioctl.h>
>> #endif
>> @@ -24,67 +27,112 @@
>>
>> #ifdef HAVE_LINUX_BLKZONED_H
>>
>> +/*
>> + * Read up to 255 characters from the first line of a file. Strip the
>> trailing
>> + * newline.
>> + */
>> +static char *read_file(const char *path)
>> +{
>> + char line[256], *p = line;
>> + FILE *f;
>> +
>> + f = fopen(path, "rb");
>> + if (!f)
>> + return NULL;
>> + if (!fgets(line, sizeof(line), f))
>> + line[0] = '\0';
>> + strsep(&p, "\n");
>> + fclose(f);
>> +
>> + return strdup(line);
>> +}
>> +
>> +static char *read_sys_attr(const char *dev_path, const char *attr)
>> +{
>> + struct stat statbuf;
>> + char *sys_devno_path = NULL;
>> + char sys_path[PATH_MAX];
>> + ssize_t sz;
>> + char *part_attr_path = NULL;
>> + char *part_str = NULL;
>> + char *delim = NULL;
>> + char *attr_path = NULL;
>> + char *attr_str = NULL;
>> +
>> + if (stat(dev_path, &statbuf) < 0)
>> + goto out;
>> +
>> + if (asprintf(&sys_devno_path, "/sys/dev/block/%d:%d",
>> + major(statbuf.st_rdev), minor(statbuf.st_rdev)) < 0)
>> + goto out;
>> +
>> + sz = readlink(sys_devno_path, sys_path, sizeof(sys_path) - 1);
>> + if (sz < 0)
>> + goto out;
>> + sys_path[sz] = '\0';
>> +
>> + /*
>> + * If the device is a partition device, cut the device name in the
>> + * canonical sysfs path to obtain the sysfs path of the holder device.
>> + * e.g.: /sys/devices/.../sda/sda1 -> /sys/devices/.../sda
>> + */
>> + if (asprintf(&part_attr_path, "/sys/dev/block/%s/partition",
>> + sys_path) < 0)
>> + goto out;
>> + part_str = read_file(part_attr_path);
>
> It needs to handle the error of read_file() here?
I don't think so. The major scenario that read_file() returns NULL is fopen
fails to read /sys/dev/block/%s/partition. It indicates that the target device
is not a partition device. The sys_path and following code is still valid for
the non-partition device.
The other minor read_file() NULL return scenario is strdup() failure because of
memory shortage. Do you think f2fs-tools need strdup() return value check? If
you suggest it, I will update the patch.
Thanks!
>> + if (part_str && *part_str == '1') {
>> + delim = strrchr(sys_path, '/');
>> + if (!delim)
>> + goto out;
>> + *delim = '\0';
>> + }
>> +
>> + if (asprintf(&attr_path, "/sys/dev/block/%s/%s", sys_path, attr) < 0)
>> + goto out;
>> +
>> + attr_str = read_file(attr_path);
>> +out:
>> + free(attr_path);
>> + free(part_str);
>> + free(part_attr_path);
>> + free(sys_devno_path);
>> + return attr_str;
>> +}
>> +
>> void f2fs_get_zoned_model(int i)
>> {
>> struct device_info *dev = c.devices + i;
>> - char str[128];
>> - FILE *file;
>> - int res;
>> -
>> - /* Check that this is a zoned block device */
>> - snprintf(str, sizeof(str),
>> - "/sys/block/%s/queue/zoned",
>> - basename(dev->path));
>> - file = fopen(str, "r");
>> - if (!file)
>> - goto not_zoned;
>> -
>> - memset(str, 0, sizeof(str));
>> - res = fscanf(file, "%s", str);
>> - fclose(file);
>> -
>> - if (res != 1)
>> - goto not_zoned;
>> -
>> - if (strcmp(str, "host-aware") == 0) {
>> - dev->zoned_model = F2FS_ZONED_HA;
>> + char *model_str;
>> +
>> + dev->zoned_model = F2FS_ZONED_NONE;
>> +
>> + model_str = read_sys_attr(dev->path, "queue/zoned");
>> + if (!model_str)
>> return;
>> - }
>> - if (strcmp(str, "host-managed") == 0) {
>> +
>> + if (strcmp(model_str, "host-aware") == 0)
>> + dev->zoned_model = F2FS_ZONED_HA;
>> + else if (strcmp(model_str, "host-managed") == 0)
>> dev->zoned_model = F2FS_ZONED_HM;
>> - return;
>> - }
>>
>> -not_zoned:
>> - dev->zoned_model = F2FS_ZONED_NONE;
>> + free(model_str);
>> }
>>
>> int f2fs_get_zone_blocks(int i)
>> {
>> struct device_info *dev = c.devices + i;
>> uint64_t sectors;
>> - char str[128];
>> - FILE *file;
>> - int res;
>> + char * cs_str;
>>
>> /* Get zone size */
>> dev->zone_blocks = 0;
>>
>> - snprintf(str, sizeof(str),
>> - "/sys/block/%s/queue/chunk_sectors",
>> - basename(dev->path));
>> - file = fopen(str, "r");
>> - if (!file)
>> - return -1;
>> -
>> - memset(str, 0, sizeof(str));
>> - res = fscanf(file, "%s", str);
>> - fclose(file);
>> -
>> - if (res != 1)
>> + cs_str = read_sys_attr(dev->path, "queue/chunk_sectors");
>> + if (!cs_str)
>> return -1;
>>
>> - sectors = atol(str);
>> + sectors = atol(cs_str);
>> + free(cs_str);
>> if (!sectors)
>> return -1;
>>
>>
>
--
Best Regards,
Shin'ichiro Kawasaki
_______________________________________________
Linux-f2fs-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel