On Fri, Aug 05, 2022 at 03:57:46PM +0800, Sam Li wrote: > Use sysfs attribute files to get the string value of device > zoned model. Then get_sysfs_zoned_model can convert it to > BlockZoneModel type in QEMU. > > Signed-off-by: Sam Li <[email protected]> > Reviewed-by: Hannes Reinecke <[email protected]> > --- > block/file-posix.c | 70 ++++++++++++++++++++++++++++++++ > include/block/block_int-common.h | 3 ++ > 2 files changed, 73 insertions(+) > > diff --git a/block/file-posix.c b/block/file-posix.c > index a40eab64a2..4785203eea 100644 > --- a/block/file-posix.c > +++ b/block/file-posix.c > @@ -1264,6 +1264,68 @@ out: > #endif > } > > +/* > + * Convert the zoned attribute file in sysfs to internal value. > + */ > +static int get_sysfs_str_val(int fd, struct stat *st, > + const char *attribute, > + char **val) {
The fd argument is unused and can be dropped.
> +#ifdef CONFIG_LINUX
> + char *buf = NULL;
> + g_autofree char *sysfspath = NULL;
> + int ret;
> + size_t len;
> +
> + if (!S_ISBLK(st->st_mode)) {
> + return -ENOTSUP;
> + }
> +
> + sysfspath = g_strdup_printf("/sys/dev/block/%u:%u/queue/%s",
> + major(st->st_rdev), minor(st->st_rdev),
> + attribute);
> + ret = g_file_get_contents(sysfspath, &buf, &len, NULL);
> + if (ret == -1) {
> + ret = -errno;
g_file_get_contents() does not set errno. You can either pass in a
GError and report the message string by converting it into a QEMU Error
object (grep for g_file_get_contents() to see example), or you can
return a fixed error code like -ENOENT.
> + return ret;
> + }
> +
> + /* The file is ended with '\n' */
> + if (buf[len - 1] == '\n') {
> + buf[len - 1] = '\0';
> + }
> +
> + if (!strncpy(*val, buf, len)) {
> + ret = -errno;
> + return ret;
> + }
> + g_free(buf);
buf is not necessary. val can be passed directly to g_file_get_contents().
> + return 0;
> +#else
> + return -ENOTSUP;
> +#endif
> +}
Now get_sysfs_long_val() can be written using get_sysfs_str_val():
static long get_sysfs_long_val(struct stat *st, const char *attribute)
{
g_autofree char *str = NULL;
const char *end;
long val;
int ret;
ret = get_sysfs_str_val(st, attribute, &str);
if (ret < 0) {
return ret;
}
ret = qemu_strtol(str, &end, 10, &val);
if (ret == 0 && end && *end == '\0') {
ret = val;
}
return ret;
}
The get_sysfs_long_val() patch can be moved after the
get_sysfs_str_val() patch.
> +
> +static int get_sysfs_zoned_model(int fd, struct stat *st,
> + BlockZoneModel *zoned) {
> + g_autofree char *val = NULL;
> + val = g_malloc(32);
> + get_sysfs_str_val(fd, st, "zoned", &val);
Once get_sysfs_str_val() passes val through to g_get_file_contents() the
caller will no longer have to g_malloc() val themselves.
signature.asc
Description: PGP signature
