qemu-block
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [RFC v5 04/11] file-posix: introduce get_sysfs_str_val for device zo


From: Stefan Hajnoczi
Subject: Re: [RFC v5 04/11] file-posix: introduce get_sysfs_str_val for device zoned model
Date: Mon, 1 Aug 2022 10:42:00 -0400

On Sun, 31 Jul 2022 at 21:34, Sam Li <faithilikerun@gmail.com> 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 <faithilikerun@gmail.com>
> ---
>  block/file-posix.c               | 86 ++++++++++++++++++++++++++++++++
>  include/block/block_int-common.h |  3 ++
>  2 files changed, 89 insertions(+)
>
> diff --git a/block/file-posix.c b/block/file-posix.c
> index bcf898f0cb..0d8b4acdc7 100644
> --- a/block/file-posix.c
> +++ b/block/file-posix.c
> @@ -1271,6 +1271,85 @@ 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) {
> +#ifdef CONFIG_LINUX
> +    char buf[32];
> +    char *sysfspath = NULL;

This can be g_autofree and then the explicit g_free(sysfspath) call is
no longer necessary.

> +    int ret, offset;
> +    int sysfd = -1;
> +
> +    if (S_ISCHR(st->st_mode)) {
> +        if (ioctl(fd, SG_GET_SG_TABLESIZE, &ret) == 0) {
> +            return ret;
> +        }
> +        return -ENOTSUP;
> +    }

This is for max_segments only. See my comment on the previous patch.

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

The code that follows can be replaced by a call to g_file_get_contents():
https://docs.gtk.org/glib/func.file_get_contents.html

Then the caller doesn't need to pre-allocate a 32-byte buffer. Instead
this function returns a string on the heap. The caller can free it
with g_free().

> +    sysfd = open(sysfspath, O_RDONLY);
> +    if (sysfd == -1) {
> +        ret = -errno;
> +        goto out;
> +    }
> +    offset = 0;
> +    do {
> +        ret = read(sysfd, buf + offset, sizeof(buf) - 1 + offset);
> +        if (ret > 0) {
> +            offset += ret;
> +        }
> +    } while (ret == -1);

I think this should be:

  } while (ret == -1 && errno == EINTR);

  if (ret < 0) {
      ret = -errno;
      goto out;
  }

Otherwise there is an infinite loop when an unrecoverable error occurs.

> +    /* The file is ended with '\n' */
> +    if (buf[ret - 1] == '\n') {
> +        buf[ret - 1] = '\0';
> +    }
> +
> +    if (!strncpy(*val, buf, ret)) {
> +        goto out;
> +    }
> +
> +out:
> +    if (sysfd != -1) {
> +        close(sysfd);
> +    }
> +    g_free(sysfspath);
> +    return ret;
> +#else
> +    return -ENOTSUP;
> +#endif
> +}
> +
> +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);
> +    if (!val) {
> +        return -ENOTSUP;
> +    }
> +
> +    if (strcmp(val, "host-managed") == 0) {
> +        *zoned = BLK_Z_HM;
> +    } else if (strcmp(val, "host-aware") == 0) {
> +        *zoned = BLK_Z_HA;
> +    } else if (strcmp(val, "none") == 0) {
> +        *zoned = BLK_Z_NONE;
> +    } else {
> +        return -ENOTSUP;
> +    }
> +    return 0;
> +}
> +
>  static int hdev_get_max_segments(int fd, struct stat *st) {
>      return get_sysfs_long_val(fd, st, "max_segments");
>  }
> @@ -1279,6 +1358,8 @@ static void raw_refresh_limits(BlockDriverState *bs, 
> Error **errp)
>  {
>      BDRVRawState *s = bs->opaque;
>      struct stat st;
> +    int ret;
> +    BlockZoneModel zoned;
>
>      s->needs_alignment = raw_needs_alignment(bs);
>      raw_probe_alignment(bs, s->fd, errp);
> @@ -1316,6 +1397,11 @@ static void raw_refresh_limits(BlockDriverState *bs, 
> Error **errp)
>              bs->bl.max_hw_iov = ret;
>          }
>      }
> +
> +    ret = get_sysfs_zoned_model(s->fd, &st, &zoned);
> +    if (ret < 0)
> +        zoned = BLK_Z_NONE;

QEMU coding style always uses {}:

  if (ret < 0) {
      zoned = BLK_Z_NONE;
  }

> +    bs->bl.zoned = zoned;
>  }
>
>  static int check_for_dasd(int fd)
> diff --git a/include/block/block_int-common.h 
> b/include/block/block_int-common.h
> index 8947abab76..7f7863cc9e 100644
> --- a/include/block/block_int-common.h
> +++ b/include/block/block_int-common.h
> @@ -825,6 +825,9 @@ typedef struct BlockLimits {
>
>      /* maximum number of iovec elements */
>      int max_iov;
> +
> +    /* device zone model */
> +    BlockZoneModel zoned;
>  } BlockLimits;
>
>  typedef struct BdrvOpBlocker BdrvOpBlocker;
> --
> 2.37.1
>
>



reply via email to

[Prev in Thread] Current Thread [Next in Thread]