aboutsummaryrefslogtreecommitdiff
path: root/qemu-io-cmds.c
diff options
context:
space:
mode:
authorSam Li <faithilikerun@gmail.com>2023-05-08 12:55:28 +0800
committerStefan Hajnoczi <stefanha@redhat.com>2023-05-15 08:17:03 -0400
commit6d43eaa39647507563017590b090b2e2b10aed2d (patch)
tree5d59c499aaeecaa226010c25d84be010f1103661 /qemu-io-cmds.c
parenta735b56e49be6f227f3f33be837a74c069441a48 (diff)
block/block-backend: add block layer APIs resembling Linux ZonedBlockDevice ioctls
Add zoned device option to host_device BlockDriver. It will be presented only for zoned host block devices. By adding zone management operations to the host_block_device BlockDriver, users can use the new block layer APIs including Report Zone and four zone management operations (open, close, finish, reset, reset_all). Qemu-io uses the new APIs to perform zoned storage commands of the device: zone_report(zrp), zone_open(zo), zone_close(zc), zone_reset(zrs), zone_finish(zf). For example, to test zone_report, use following command: $ ./build/qemu-io --image-opts -n driver=host_device, filename=/dev/nullb0 -c "zrp offset nr_zones" Signed-off-by: Sam Li <faithilikerun@gmail.com> Reviewed-by: Hannes Reinecke <hare@suse.de> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Reviewed-by: Dmitry Fomichev <dmitry.fomichev@wdc.com> Acked-by: Kevin Wolf <kwolf@redhat.com> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> Message-id: 20230508045533.175575-4-faithilikerun@gmail.com Message-id: 20230324090605.28361-4-faithilikerun@gmail.com [Adjust commit message prefix as suggested by Philippe Mathieu-Daudé <philmd@linaro.org> and remove spurious ret = -errno in raw_co_zone_mgmt(). --Stefan] Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'qemu-io-cmds.c')
-rw-r--r--qemu-io-cmds.c149
1 files changed, 149 insertions, 0 deletions
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
index e7a02f5b99..f35ea627d7 100644
--- a/qemu-io-cmds.c
+++ b/qemu-io-cmds.c
@@ -1730,6 +1730,150 @@ static const cmdinfo_t flush_cmd = {
.oneline = "flush all in-core file state to disk",
};
+static inline int64_t tosector(int64_t bytes)
+{
+ return bytes >> BDRV_SECTOR_BITS;
+}
+
+static int zone_report_f(BlockBackend *blk, int argc, char **argv)
+{
+ int ret;
+ int64_t offset;
+ unsigned int nr_zones;
+
+ ++optind;
+ offset = cvtnum(argv[optind]);
+ ++optind;
+ nr_zones = cvtnum(argv[optind]);
+
+ g_autofree BlockZoneDescriptor *zones = NULL;
+ zones = g_new(BlockZoneDescriptor, nr_zones);
+ ret = blk_zone_report(blk, offset, &nr_zones, zones);
+ if (ret < 0) {
+ printf("zone report failed: %s\n", strerror(-ret));
+ } else {
+ for (int i = 0; i < nr_zones; ++i) {
+ printf("start: 0x%" PRIx64 ", len 0x%" PRIx64 ", "
+ "cap"" 0x%" PRIx64 ", wptr 0x%" PRIx64 ", "
+ "zcond:%u, [type: %u]\n",
+ tosector(zones[i].start), tosector(zones[i].length),
+ tosector(zones[i].cap), tosector(zones[i].wp),
+ zones[i].state, zones[i].type);
+ }
+ }
+ return ret;
+}
+
+static const cmdinfo_t zone_report_cmd = {
+ .name = "zone_report",
+ .altname = "zrp",
+ .cfunc = zone_report_f,
+ .argmin = 2,
+ .argmax = 2,
+ .args = "offset number",
+ .oneline = "report zone information",
+};
+
+static int zone_open_f(BlockBackend *blk, int argc, char **argv)
+{
+ int ret;
+ int64_t offset, len;
+ ++optind;
+ offset = cvtnum(argv[optind]);
+ ++optind;
+ len = cvtnum(argv[optind]);
+ ret = blk_zone_mgmt(blk, BLK_ZO_OPEN, offset, len);
+ if (ret < 0) {
+ printf("zone open failed: %s\n", strerror(-ret));
+ }
+ return ret;
+}
+
+static const cmdinfo_t zone_open_cmd = {
+ .name = "zone_open",
+ .altname = "zo",
+ .cfunc = zone_open_f,
+ .argmin = 2,
+ .argmax = 2,
+ .args = "offset len",
+ .oneline = "explicit open a range of zones in zone block device",
+};
+
+static int zone_close_f(BlockBackend *blk, int argc, char **argv)
+{
+ int ret;
+ int64_t offset, len;
+ ++optind;
+ offset = cvtnum(argv[optind]);
+ ++optind;
+ len = cvtnum(argv[optind]);
+ ret = blk_zone_mgmt(blk, BLK_ZO_CLOSE, offset, len);
+ if (ret < 0) {
+ printf("zone close failed: %s\n", strerror(-ret));
+ }
+ return ret;
+}
+
+static const cmdinfo_t zone_close_cmd = {
+ .name = "zone_close",
+ .altname = "zc",
+ .cfunc = zone_close_f,
+ .argmin = 2,
+ .argmax = 2,
+ .args = "offset len",
+ .oneline = "close a range of zones in zone block device",
+};
+
+static int zone_finish_f(BlockBackend *blk, int argc, char **argv)
+{
+ int ret;
+ int64_t offset, len;
+ ++optind;
+ offset = cvtnum(argv[optind]);
+ ++optind;
+ len = cvtnum(argv[optind]);
+ ret = blk_zone_mgmt(blk, BLK_ZO_FINISH, offset, len);
+ if (ret < 0) {
+ printf("zone finish failed: %s\n", strerror(-ret));
+ }
+ return ret;
+}
+
+static const cmdinfo_t zone_finish_cmd = {
+ .name = "zone_finish",
+ .altname = "zf",
+ .cfunc = zone_finish_f,
+ .argmin = 2,
+ .argmax = 2,
+ .args = "offset len",
+ .oneline = "finish a range of zones in zone block device",
+};
+
+static int zone_reset_f(BlockBackend *blk, int argc, char **argv)
+{
+ int ret;
+ int64_t offset, len;
+ ++optind;
+ offset = cvtnum(argv[optind]);
+ ++optind;
+ len = cvtnum(argv[optind]);
+ ret = blk_zone_mgmt(blk, BLK_ZO_RESET, offset, len);
+ if (ret < 0) {
+ printf("zone reset failed: %s\n", strerror(-ret));
+ }
+ return ret;
+}
+
+static const cmdinfo_t zone_reset_cmd = {
+ .name = "zone_reset",
+ .altname = "zrs",
+ .cfunc = zone_reset_f,
+ .argmin = 2,
+ .argmax = 2,
+ .args = "offset len",
+ .oneline = "reset a zone write pointer in zone block device",
+};
+
static int truncate_f(BlockBackend *blk, int argc, char **argv);
static const cmdinfo_t truncate_cmd = {
.name = "truncate",
@@ -2523,6 +2667,11 @@ static void __attribute((constructor)) init_qemuio_commands(void)
qemuio_add_command(&aio_write_cmd);
qemuio_add_command(&aio_flush_cmd);
qemuio_add_command(&flush_cmd);
+ qemuio_add_command(&zone_report_cmd);
+ qemuio_add_command(&zone_open_cmd);
+ qemuio_add_command(&zone_close_cmd);
+ qemuio_add_command(&zone_finish_cmd);
+ qemuio_add_command(&zone_reset_cmd);
qemuio_add_command(&truncate_cmd);
qemuio_add_command(&length_cmd);
qemuio_add_command(&info_cmd);