* [Qemu-devel] [PATCH v4 1/4] block: Add zoned device model property
@ 2019-08-23 19:20 Dmitry Fomichev
2019-08-23 19:20 ` [Qemu-devel] [PATCH v4 2/4] raw: Recognize zoned backing devices Dmitry Fomichev
0 siblings, 1 reply; 3+ messages in thread
From: Dmitry Fomichev @ 2019-08-23 19:20 UTC (permalink / raw)
To: Paolo Bonzini, Kevin Wolf, Max Reitz, Michael S . Tsirkin,
Stefan Hajnoczi, John Snow
Cc: Dmitry Fomichev, Alistair Francis, qemu-devel, qemu-block
This commit adds Zoned Device Model (as defined in T10 ZBC and
T13 ZAC standards) as a block driver property, along with some
useful access functions.
A new backend driver permission, BLK_PERM_SUPPORT_ZONED, is also
introduced. Only the drivers having this permission will be allowed
to open zoned block devices.
No code is added yet to initialize or check the value of this new
property, therefore this commit doesn't change any functionality.
Signed-off-by: Dmitry Fomichev <dmitry.fomichev@wdc.com>
---
block.c | 19 +++++++++++++++++++
include/block/block.h | 21 ++++++++++++++++++++-
include/block/block_int.h | 4 ++++
3 files changed, 43 insertions(+), 1 deletion(-)
diff --git a/block.c b/block.c
index 874a29a983..6dd4cecded 100644
--- a/block.c
+++ b/block.c
@@ -4679,6 +4679,25 @@ void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr)
*nb_sectors_ptr = nb_sectors < 0 ? 0 : nb_sectors;
}
+uint8_t bdrv_get_zoned_model(BlockDriverState *bs)
+{
+ if (bs->drv->bdrv_get_zoned_info) {
+ bs->drv->bdrv_get_zoned_info(bs);
+ }
+
+ return bs->bl.zoned_model;
+}
+
+uint8_t bdrv_is_zoned(BlockDriverState *bs)
+{
+ /*
+ * Host Aware zone devices are supposed to be able to work
+ * just like regular block devices. Thus, we only consider
+ * Host Managed devices to be zoned here.
+ */
+ return bdrv_get_zoned_model(bs) == BLK_ZONED_MODEL_HM;
+}
+
bool bdrv_is_sg(BlockDriverState *bs)
{
return bs->sg;
diff --git a/include/block/block.h b/include/block/block.h
index 124ad40809..238c0f5ed7 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -271,18 +271,35 @@ enum {
*/
BLK_PERM_GRAPH_MOD = 0x10,
+ /** This permission is required to open zoned block devices. */
+ BLK_PERM_SUPPORT_ZONED = 0x20,
+
BLK_PERM_ALL = 0x1f,
DEFAULT_PERM_PASSTHROUGH = BLK_PERM_CONSISTENT_READ
| BLK_PERM_WRITE
| BLK_PERM_WRITE_UNCHANGED
- | BLK_PERM_RESIZE,
+ | BLK_PERM_RESIZE
+ | BLK_PERM_SUPPORT_ZONED,
DEFAULT_PERM_UNCHANGED = BLK_PERM_ALL & ~DEFAULT_PERM_PASSTHROUGH,
};
char *bdrv_perm_names(uint64_t perm);
+/*
+ * Known zoned device models.
+ *
+ * TODO For a Linux host, it could be preferrable to include
+ * /usr/include/linux/blkzoned.h instead of defining ZBD-specific
+ * values here.
+ */
+enum blk_zoned_model {
+ BLK_ZONED_MODEL_NONE, /* Regular block device */
+ BLK_ZONED_MODEL_HA, /* Host-aware zoned block device */
+ BLK_ZONED_MODEL_HM, /* Host-managed zoned block device */
+};
+
/* disk I/O throttling */
void bdrv_init(void);
void bdrv_init_with_whitelist(void);
@@ -359,6 +376,8 @@ int64_t bdrv_get_allocated_file_size(BlockDriverState *bs);
BlockMeasureInfo *bdrv_measure(BlockDriver *drv, QemuOpts *opts,
BlockDriverState *in_bs, Error **errp);
void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr);
+uint8_t bdrv_get_zoned_model(BlockDriverState *bs);
+uint8_t bdrv_is_zoned(BlockDriverState *bs);
void bdrv_refresh_limits(BlockDriverState *bs, Error **errp);
int bdrv_commit(BlockDriverState *bs);
int bdrv_change_backing_file(BlockDriverState *bs,
diff --git a/include/block/block_int.h b/include/block/block_int.h
index ceec8c2f56..91496e8149 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -415,6 +415,7 @@ struct BlockDriver {
bool (*bdrv_debug_is_suspended)(BlockDriverState *bs, const char *tag);
void (*bdrv_refresh_limits)(BlockDriverState *bs, Error **errp);
+ void (*bdrv_get_zoned_info)(BlockDriverState *bs);
/*
* Returns 1 if newly created images are guaranteed to contain only
@@ -620,6 +621,9 @@ typedef struct BlockLimits {
/* maximum number of iovec elements */
int max_iov;
+
+ /* Zoned device model. Zero value indicates a regular block device */
+ uint8_t zoned_model;
} BlockLimits;
typedef struct BdrvOpBlocker BdrvOpBlocker;
--
2.21.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [Qemu-devel] [PATCH v4 2/4] raw: Recognize zoned backing devices
2019-08-23 19:20 [Qemu-devel] [PATCH v4 1/4] block: Add zoned device model property Dmitry Fomichev
@ 2019-08-23 19:20 ` Dmitry Fomichev
0 siblings, 0 replies; 3+ messages in thread
From: Dmitry Fomichev @ 2019-08-23 19:20 UTC (permalink / raw)
To: Paolo Bonzini, Kevin Wolf, Max Reitz, Michael S . Tsirkin,
Stefan Hajnoczi, John Snow
Cc: Dmitry Fomichev, Alistair Francis, qemu-devel, qemu-block
The purpose of this patch is to recognize a zoned block device (ZBD)
when it is opened as a raw file. The new code initializes the zoned
model propery introduced by the previous commit.
This commit is Linux-specific as it gets the Zoned Block Device Model
value (none/host-managed/host-aware) from sysfs on the host.
In order to avoid code duplication in file-posix.c, a common helper
function is added to read values of sysfs entries under
/sys/block/<dev>/queue. This way, the existing function that reads
the value of "max_segments" entry and the the new function that reads
"zoned" value both share the same helper code.
Signed-off-by: Dmitry Fomichev <dmitry.fomichev@wdc.com>
---
block/file-posix.c | 74 ++++++++++++++++++++++++++++++++++++++--------
block/raw-format.c | 8 +++++
2 files changed, 70 insertions(+), 12 deletions(-)
diff --git a/block/file-posix.c b/block/file-posix.c
index fbeb0068db..d9f2fc5e46 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -1067,15 +1067,13 @@ static int sg_get_max_transfer_length(int fd)
#endif
}
-static int sg_get_max_segments(int fd)
+static int hdev_read_blk_queue_entry(int fd, const char *key,
+ char *buf, int buf_len)
{
#ifdef CONFIG_LINUX
- char buf[32];
- const char *end;
char *sysfspath = NULL;
int ret;
int sysfd = -1;
- long max_segments;
struct stat st;
if (fstat(fd, &st)) {
@@ -1083,23 +1081,45 @@ static int sg_get_max_segments(int fd)
goto out;
}
- sysfspath = g_strdup_printf("/sys/dev/block/%u:%u/queue/max_segments",
- major(st.st_rdev), minor(st.st_rdev));
+ sysfspath = g_strdup_printf("/sys/dev/block/%u:%u/queue/%s",
+ major(st.st_rdev), minor(st.st_rdev), key);
sysfd = open(sysfspath, O_RDONLY);
if (sysfd == -1) {
ret = -errno;
goto out;
}
do {
- ret = read(sysfd, buf, sizeof(buf) - 1);
+ ret = read(sysfd, buf, buf_len - 1);
} while (ret == -1 && errno == EINTR);
if (ret < 0) {
ret = -errno;
- goto out;
} else if (ret == 0) {
ret = -EIO;
+ }
+out:
+ if (sysfd != -1) {
+ close(sysfd);
+ }
+ g_free(sysfspath);
+ return ret;
+#else
+ return -ENOTSUP;
+#endif
+}
+
+static int sg_get_max_segments(int fd)
+{
+#ifdef CONFIG_LINUX
+ char buf[32];
+ const char *end;
+ int ret;
+ long max_segments;
+
+ ret = hdev_read_blk_queue_entry(fd, "max_segments", buf, sizeof(buf));
+ if (ret < 0) {
goto out;
}
+
buf[ret] = 0;
/* The file is ended with '\n', pass 'end' to accept that. */
ret = qemu_strtol(buf, &end, 10, &max_segments);
@@ -1108,10 +1128,33 @@ static int sg_get_max_segments(int fd)
}
out:
- if (sysfd != -1) {
- close(sysfd);
+ return ret;
+#else
+ return -ENOTSUP;
+#endif
+}
+
+static int hdev_get_zoned_model(int fd)
+{
+#ifdef CONFIG_LINUX
+ char buf[32];
+ int ret;
+
+ ret = hdev_read_blk_queue_entry(fd, "zoned", buf, sizeof(buf));
+ if (ret < 0) {
+ ret = BLK_ZONED_MODEL_NONE;
+ goto out;
}
- g_free(sysfspath);
+
+ buf[ret - 1] = 0;
+ ret = BLK_ZONED_MODEL_NONE;
+ if (strcmp(buf, "host-managed") == 0) {
+ ret = BLK_ZONED_MODEL_HM;
+ } else if (strcmp(buf, "host-aware") == 0) {
+ ret = BLK_ZONED_MODEL_HA;
+ }
+
+out:
return ret;
#else
return -ENOTSUP;
@@ -1121,9 +1164,10 @@ out:
static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
{
BDRVRawState *s = bs->opaque;
+ int ret;
if (bs->sg) {
- int ret = sg_get_max_transfer_length(s->fd);
+ ret = sg_get_max_transfer_length(s->fd);
if (ret > 0 && ret <= BDRV_REQUEST_MAX_BYTES) {
bs->bl.max_transfer = pow2floor(ret);
@@ -1133,6 +1177,12 @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
if (ret > 0) {
bs->bl.max_transfer = MIN(bs->bl.max_transfer, ret * getpagesize());
}
+
+ }
+
+ ret = hdev_get_zoned_model(s->fd);
+ if (ret >= 0) {
+ bs->bl.zoned_model = ret;
}
raw_probe_alignment(bs, s->fd, errp);
diff --git a/block/raw-format.c b/block/raw-format.c
index 42c28cc29a..a606e4a7fe 100644
--- a/block/raw-format.c
+++ b/block/raw-format.c
@@ -369,6 +369,13 @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
}
}
+static void raw_get_zoned_info(BlockDriverState *bs)
+{
+ if (!bs->probed) {
+ bs->bl.zoned_model = bs->file->bs->bl.zoned_model;
+ }
+}
+
static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
PreallocMode prealloc, Error **errp)
{
@@ -578,6 +585,7 @@ BlockDriver bdrv_raw = {
.create_opts = &raw_create_opts,
.bdrv_has_zero_init = &raw_has_zero_init,
.bdrv_has_zero_init_truncate = &raw_has_zero_init_truncate,
+ .bdrv_get_zoned_info = &raw_get_zoned_info,
.strong_runtime_opts = raw_strong_runtime_opts,
.mutable_opts = mutable_opts,
};
--
2.21.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [Qemu-devel] [PATCH v4 0/4] virtio/block: handle zoned backing devices
@ 2019-08-23 19:22 Dmitry Fomichev
2019-08-23 19:22 ` [Qemu-devel] [PATCH v4 2/4] raw: Recognize " Dmitry Fomichev
0 siblings, 1 reply; 3+ messages in thread
From: Dmitry Fomichev @ 2019-08-23 19:22 UTC (permalink / raw)
To: Paolo Bonzini, Kevin Wolf, Max Reitz, Michael S . Tsirkin,
Stefan Hajnoczi, John Snow
Cc: Dmitry Fomichev, Alistair Francis, qemu-devel, qemu-block
Ping... Any objections to merging this patchset? Ask me if you are not
sure how to validate these patches without having the hardware :)
Currently, attaching zoned block devices (i.e., storage devices
compliant to ZAC/ZBC standards) using several virtio methods doesn't
work properly as zoned devices appear as regular block devices at the
guest. This may cause unexpected i/o errors and, potentially, some
data corruption.
To be more precise, attaching a zoned device via virtio-pci-blk,
virtio-scsi-pci/scsi-disk or virtio-scsi-pci/scsi-hd demonstrates the
above behavior. The virtio-scsi-pci/scsi-block method works with a
recent patch. The virtio-scsi-pci/scsi-generic method also appears to
handle zoned devices without problems.
This patch set adds code to check if the backing device that is being
opened is a zoned Host Managed device. If this is the case, the patch
prohibits attaching such device for all use cases lacking proper
zoned support.
Host Aware zoned block devices are designed to work as regular block
devices at a guest system that does not support ZBD. Therefore, this
patch set doesn't prohibit attachment of Host Aware devices.
Considering that there is still a couple of different working ways
to attach a ZBD, this patch set provides a reasonable short-term
solution for this problem.
ZBD support for virtio-scsi-pci/scsi-disk and virtio-scsi-pci/scsi-hd
does not seem as necessary. Users will be expected to attach zoned
block devices via virtio-scsi-pci/scsi-block instead.
This patch set contains some Linux-specific code. This code is
necessary to obtain Zoned Block Device model value from Linux sysfs.
History:
v1 -> v2:
- rework code to be permission-based
- always allow Host Aware devices to be attached
- add fix for Host Aware attachments aka RCAP output snoop
v2 -> v3:
- drop the patch for RCAP output snoop - merged separately
v3 -> v4:
- rebase to the current code
Dmitry Fomichev (4):
block: Add zoned device model property
raw: Recognize zoned backing devices
block/ide/scsi: Set BLK_PERM_SUPPORT_ZONED
raw: Don't open ZBDs if backend can't handle them
block.c | 19 +++++++++
block/file-posix.c | 88 +++++++++++++++++++++++++++++++++------
block/raw-format.c | 8 ++++
hw/block/block.c | 8 +++-
hw/block/fdc.c | 5 ++-
hw/block/nvme.c | 2 +-
hw/block/virtio-blk.c | 2 +-
hw/block/xen-block.c | 2 +-
hw/ide/qdev.c | 2 +-
hw/scsi/scsi-disk.c | 13 +++---
hw/scsi/scsi-generic.c | 2 +-
hw/usb/dev-storage.c | 2 +-
include/block/block.h | 21 +++++++++-
include/block/block_int.h | 4 ++
include/hw/block/block.h | 3 +-
15 files changed, 151 insertions(+), 30 deletions(-)
--
2.21.0
^ permalink raw reply [flat|nested] 3+ messages in thread
* [Qemu-devel] [PATCH v4 2/4] raw: Recognize zoned backing devices
2019-08-23 19:22 [Qemu-devel] [PATCH v4 0/4] virtio/block: handle " Dmitry Fomichev
@ 2019-08-23 19:22 ` Dmitry Fomichev
0 siblings, 0 replies; 3+ messages in thread
From: Dmitry Fomichev @ 2019-08-23 19:22 UTC (permalink / raw)
To: Paolo Bonzini, Kevin Wolf, Max Reitz, Michael S . Tsirkin,
Stefan Hajnoczi, John Snow
Cc: Dmitry Fomichev, Alistair Francis, qemu-devel, qemu-block
The purpose of this patch is to recognize a zoned block device (ZBD)
when it is opened as a raw file. The new code initializes the zoned
model propery introduced by the previous commit.
This commit is Linux-specific as it gets the Zoned Block Device Model
value (none/host-managed/host-aware) from sysfs on the host.
In order to avoid code duplication in file-posix.c, a common helper
function is added to read values of sysfs entries under
/sys/block/<dev>/queue. This way, the existing function that reads
the value of "max_segments" entry and the the new function that reads
"zoned" value both share the same helper code.
Signed-off-by: Dmitry Fomichev <dmitry.fomichev@wdc.com>
---
block/file-posix.c | 74 ++++++++++++++++++++++++++++++++++++++--------
block/raw-format.c | 8 +++++
2 files changed, 70 insertions(+), 12 deletions(-)
diff --git a/block/file-posix.c b/block/file-posix.c
index fbeb0068db..d9f2fc5e46 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -1067,15 +1067,13 @@ static int sg_get_max_transfer_length(int fd)
#endif
}
-static int sg_get_max_segments(int fd)
+static int hdev_read_blk_queue_entry(int fd, const char *key,
+ char *buf, int buf_len)
{
#ifdef CONFIG_LINUX
- char buf[32];
- const char *end;
char *sysfspath = NULL;
int ret;
int sysfd = -1;
- long max_segments;
struct stat st;
if (fstat(fd, &st)) {
@@ -1083,23 +1081,45 @@ static int sg_get_max_segments(int fd)
goto out;
}
- sysfspath = g_strdup_printf("/sys/dev/block/%u:%u/queue/max_segments",
- major(st.st_rdev), minor(st.st_rdev));
+ sysfspath = g_strdup_printf("/sys/dev/block/%u:%u/queue/%s",
+ major(st.st_rdev), minor(st.st_rdev), key);
sysfd = open(sysfspath, O_RDONLY);
if (sysfd == -1) {
ret = -errno;
goto out;
}
do {
- ret = read(sysfd, buf, sizeof(buf) - 1);
+ ret = read(sysfd, buf, buf_len - 1);
} while (ret == -1 && errno == EINTR);
if (ret < 0) {
ret = -errno;
- goto out;
} else if (ret == 0) {
ret = -EIO;
+ }
+out:
+ if (sysfd != -1) {
+ close(sysfd);
+ }
+ g_free(sysfspath);
+ return ret;
+#else
+ return -ENOTSUP;
+#endif
+}
+
+static int sg_get_max_segments(int fd)
+{
+#ifdef CONFIG_LINUX
+ char buf[32];
+ const char *end;
+ int ret;
+ long max_segments;
+
+ ret = hdev_read_blk_queue_entry(fd, "max_segments", buf, sizeof(buf));
+ if (ret < 0) {
goto out;
}
+
buf[ret] = 0;
/* The file is ended with '\n', pass 'end' to accept that. */
ret = qemu_strtol(buf, &end, 10, &max_segments);
@@ -1108,10 +1128,33 @@ static int sg_get_max_segments(int fd)
}
out:
- if (sysfd != -1) {
- close(sysfd);
+ return ret;
+#else
+ return -ENOTSUP;
+#endif
+}
+
+static int hdev_get_zoned_model(int fd)
+{
+#ifdef CONFIG_LINUX
+ char buf[32];
+ int ret;
+
+ ret = hdev_read_blk_queue_entry(fd, "zoned", buf, sizeof(buf));
+ if (ret < 0) {
+ ret = BLK_ZONED_MODEL_NONE;
+ goto out;
}
- g_free(sysfspath);
+
+ buf[ret - 1] = 0;
+ ret = BLK_ZONED_MODEL_NONE;
+ if (strcmp(buf, "host-managed") == 0) {
+ ret = BLK_ZONED_MODEL_HM;
+ } else if (strcmp(buf, "host-aware") == 0) {
+ ret = BLK_ZONED_MODEL_HA;
+ }
+
+out:
return ret;
#else
return -ENOTSUP;
@@ -1121,9 +1164,10 @@ out:
static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
{
BDRVRawState *s = bs->opaque;
+ int ret;
if (bs->sg) {
- int ret = sg_get_max_transfer_length(s->fd);
+ ret = sg_get_max_transfer_length(s->fd);
if (ret > 0 && ret <= BDRV_REQUEST_MAX_BYTES) {
bs->bl.max_transfer = pow2floor(ret);
@@ -1133,6 +1177,12 @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
if (ret > 0) {
bs->bl.max_transfer = MIN(bs->bl.max_transfer, ret * getpagesize());
}
+
+ }
+
+ ret = hdev_get_zoned_model(s->fd);
+ if (ret >= 0) {
+ bs->bl.zoned_model = ret;
}
raw_probe_alignment(bs, s->fd, errp);
diff --git a/block/raw-format.c b/block/raw-format.c
index 42c28cc29a..a606e4a7fe 100644
--- a/block/raw-format.c
+++ b/block/raw-format.c
@@ -369,6 +369,13 @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
}
}
+static void raw_get_zoned_info(BlockDriverState *bs)
+{
+ if (!bs->probed) {
+ bs->bl.zoned_model = bs->file->bs->bl.zoned_model;
+ }
+}
+
static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
PreallocMode prealloc, Error **errp)
{
@@ -578,6 +585,7 @@ BlockDriver bdrv_raw = {
.create_opts = &raw_create_opts,
.bdrv_has_zero_init = &raw_has_zero_init,
.bdrv_has_zero_init_truncate = &raw_has_zero_init_truncate,
+ .bdrv_get_zoned_info = &raw_get_zoned_info,
.strong_runtime_opts = raw_strong_runtime_opts,
.mutable_opts = mutable_opts,
};
--
2.21.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2019-08-23 19:37 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-23 19:20 [Qemu-devel] [PATCH v4 1/4] block: Add zoned device model property Dmitry Fomichev
2019-08-23 19:20 ` [Qemu-devel] [PATCH v4 2/4] raw: Recognize zoned backing devices Dmitry Fomichev
2019-08-23 19:22 [Qemu-devel] [PATCH v4 0/4] virtio/block: handle " Dmitry Fomichev
2019-08-23 19:22 ` [Qemu-devel] [PATCH v4 2/4] raw: Recognize " Dmitry Fomichev
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).