From: Kevin Wolf <kwolf@redhat.com>
To: qemu-block@nongnu.org
Cc: kwolf@redhat.com, qemu-devel@nongnu.org
Subject: [PULL 16/18] block: Expose block limits for images in QMP
Date: Wed, 29 Oct 2025 13:06:32 +0100 [thread overview]
Message-ID: <20251029120634.288467-17-kwolf@redhat.com> (raw)
In-Reply-To: <20251029120634.288467-1-kwolf@redhat.com>
This information can be useful both for debugging and for management
tools trying to configure guest devices with the optimal limits
(possibly across multiple hosts). There is no reason not to make it
available, so just add it to BlockNodeInfo.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Hanna Czenczek <hreitz@redhat.com>
Message-ID: <20251024123041.51254-3-kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
qapi/block-core.json | 66 ++++++++++++++++++++++++++++++++
block/qapi.c | 34 ++++++++++++++--
tests/qemu-iotests/184 | 5 ++-
tests/qemu-iotests/184.out | 8 ----
tests/qemu-iotests/common.filter | 3 +-
5 files changed, 102 insertions(+), 14 deletions(-)
diff --git a/qapi/block-core.json b/qapi/block-core.json
index dc6eb4ae23..2c037183f0 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -275,6 +275,69 @@
'file': 'ImageInfoSpecificFileWrapper'
} }
+##
+# @BlockLimitsInfo:
+#
+# @request-alignment: Alignment requirement, in bytes, for
+# offset/length of I/O requests.
+#
+# @max-discard: Maximum number of bytes that can be discarded at once.
+# If not present, there is no specific maximum.
+#
+# @discard-alignment: Optimal alignment for discard requests in bytes.
+# Note that this doesn't have to be a power of two. If not
+# present, discards don't have a alignment requirement different
+# from @request-alignment.
+#
+# @max-write-zeroes: Maximum number of bytes that can be zeroed out at
+# once. If not present, there is no specific maximum.
+#
+# @write-zeroes-alignment: Optimal alignment for write zeroes requests
+# in bytes. Note that this doesn't have to be a power of two. If
+# not present, write_zeroes doesn't have a alignment requirement
+# different from @request-alignment.
+#
+# @opt-transfer: Optimal transfer length in bytes. If not present,
+# there is no preferred size.
+#
+# @max-transfer: Maximal transfer length in bytes. If not present,
+# there is no specific maximum.
+#
+# @max-hw-transfer: Maximal hardware transfer length in bytes.
+# Applies whenever transfers to the device bypass the kernel I/O
+# scheduler, for example with SG_IO. If not present, there is no
+# specific maximum.
+#
+# @max-iov: Maximum number of scatter/gather elements
+#
+# @max-hw-iov: Maximum number of scatter/gather elements allowed by
+# the hardware. Applies whenever transfers to the device bypass
+# the kernel I/O scheduler, for example with SG_IO. If not
+# present, the hardware limits is unknown and @max-iov is always
+# used.
+#
+# @min-mem-alignment: Minimal required memory alignment in bytes for
+# zero-copy I/O to succeed. For unaligned requests, a bounce
+# buffer will be used.
+#
+# @opt-mem-alignment: Optimal memory alignment in bytes. This is the
+# alignment used for any buffer allocations QEMU performs
+# internally.
+##
+{ 'struct': 'BlockLimitsInfo',
+ 'data': { 'request-alignment': 'uint32',
+ '*max-discard': 'uint64',
+ '*discard-alignment': 'uint32',
+ '*max-write-zeroes': 'uint64',
+ '*write-zeroes-alignment': 'uint32',
+ '*opt-transfer': 'uint32',
+ '*max-transfer': 'uint32',
+ '*max-hw-transfer': 'uint32',
+ 'max-iov': 'int',
+ '*max-hw-iov': 'int',
+ 'min-mem-alignment': 'size',
+ 'opt-mem-alignment': 'size' } }
+
##
# @BlockNodeInfo:
#
@@ -304,6 +367,8 @@
#
# @snapshots: list of VM snapshots
#
+# @limits: block limits that are used for I/O on the node (Since 10.2)
+#
# @format-specific: structure supplying additional format-specific
# information (since 1.7)
#
@@ -315,6 +380,7 @@
'*cluster-size': 'int', '*encrypted': 'bool', '*compressed': 'bool',
'*backing-filename': 'str', '*full-backing-filename': 'str',
'*backing-filename-format': 'str', '*snapshots': ['SnapshotInfo'],
+ '*limits': 'BlockLimitsInfo',
'*format-specific': 'ImageInfoSpecific' } }
##
diff --git a/block/qapi.c b/block/qapi.c
index 12fbf8d1b7..54521d0a68 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -235,7 +235,8 @@ int bdrv_query_snapshot_info_list(BlockDriverState *bs,
* in @info, setting @errp on error.
*/
static void GRAPH_RDLOCK
-bdrv_do_query_node_info(BlockDriverState *bs, BlockNodeInfo *info, Error **errp)
+bdrv_do_query_node_info(BlockDriverState *bs, BlockNodeInfo *info, bool limits,
+ Error **errp)
{
int64_t size;
const char *backing_filename;
@@ -269,6 +270,33 @@ bdrv_do_query_node_info(BlockDriverState *bs, BlockNodeInfo *info, Error **errp)
info->dirty_flag = bdi.is_dirty;
info->has_dirty_flag = true;
}
+
+ if (limits) {
+ info->limits = g_new(BlockLimitsInfo, 1);
+ *info->limits = (BlockLimitsInfo) {
+ .request_alignment = bs->bl.request_alignment,
+ .has_max_discard = bs->bl.max_pdiscard != 0,
+ .max_discard = bs->bl.max_pdiscard,
+ .has_discard_alignment = bs->bl.pdiscard_alignment != 0,
+ .discard_alignment = bs->bl.pdiscard_alignment,
+ .has_max_write_zeroes = bs->bl.max_pwrite_zeroes != 0,
+ .max_write_zeroes = bs->bl.max_pwrite_zeroes,
+ .has_write_zeroes_alignment = bs->bl.pwrite_zeroes_alignment != 0,
+ .write_zeroes_alignment = bs->bl.pwrite_zeroes_alignment,
+ .has_opt_transfer = bs->bl.opt_transfer != 0,
+ .opt_transfer = bs->bl.opt_transfer,
+ .has_max_transfer = bs->bl.max_transfer != 0,
+ .max_transfer = bs->bl.max_transfer,
+ .has_max_hw_transfer = bs->bl.max_hw_transfer != 0,
+ .max_hw_transfer = bs->bl.max_hw_transfer,
+ .max_iov = bs->bl.max_iov,
+ .has_max_hw_iov = bs->bl.max_hw_iov != 0,
+ .max_hw_iov = bs->bl.max_hw_iov,
+ .min_mem_alignment = bs->bl.min_mem_alignment,
+ .opt_mem_alignment = bs->bl.opt_mem_alignment,
+ };
+ }
+
info->format_specific = bdrv_get_specific_info(bs, &err);
if (err) {
error_propagate(errp, err);
@@ -343,7 +371,7 @@ void bdrv_query_image_info(BlockDriverState *bs,
ImageInfo *info;
info = g_new0(ImageInfo, 1);
- bdrv_do_query_node_info(bs, qapi_ImageInfo_base(info), errp);
+ bdrv_do_query_node_info(bs, qapi_ImageInfo_base(info), true, errp);
if (*errp) {
goto fail;
}
@@ -397,7 +425,7 @@ void bdrv_query_block_graph_info(BlockDriverState *bs,
BdrvChild *c;
info = g_new0(BlockGraphInfo, 1);
- bdrv_do_query_node_info(bs, qapi_BlockGraphInfo_base(info), errp);
+ bdrv_do_query_node_info(bs, qapi_BlockGraphInfo_base(info), false, errp);
if (*errp) {
goto fail;
}
diff --git a/tests/qemu-iotests/184 b/tests/qemu-iotests/184
index e4cbcd8634..6d0afe9d38 100755
--- a/tests/qemu-iotests/184
+++ b/tests/qemu-iotests/184
@@ -45,8 +45,9 @@ do_run_qemu()
run_qemu()
{
- do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu | _filter_qmp\
- | _filter_qemu_io | _filter_generated_node_ids
+ do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu | _filter_qmp \
+ | _filter_qemu_io | _filter_generated_node_ids \
+ | _filter_img_info
}
test_throttle=$($QEMU_IMG --help|grep throttle)
diff --git a/tests/qemu-iotests/184.out b/tests/qemu-iotests/184.out
index ef99bb2e9a..52692b6b3b 100644
--- a/tests/qemu-iotests/184.out
+++ b/tests/qemu-iotests/184.out
@@ -41,12 +41,6 @@ Testing:
},
"iops_wr": 0,
"ro": false,
- "children": [
- {
- "node-name": "disk0",
- "child": "file"
- }
- ],
"node-name": "throttle0",
"backing_file_depth": 1,
"drv": "throttle",
@@ -75,8 +69,6 @@ Testing:
},
"iops_wr": 0,
"ro": false,
- "children": [
- ],
"node-name": "disk0",
"backing_file_depth": 0,
"drv": "null-co",
diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter
index 511a55b1e8..26e6b45b04 100644
--- a/tests/qemu-iotests/common.filter
+++ b/tests/qemu-iotests/common.filter
@@ -229,6 +229,7 @@ _filter_img_info()
discard=0
regex_json_spec_start='^ *"format-specific": \{'
regex_json_child_start='^ *"children": \['
+ regex_json_limit_start='^ *"limits": \{'
gsed -e "s#$REMOTE_TEST_DIR#TEST_DIR#g" \
-e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \
-e "s#$TEST_DIR#TEST_DIR#g" \
@@ -261,7 +262,7 @@ _filter_img_info()
discard=1
elif [[ $line =~ "Child node '/" ]]; then
discard=1
- elif [[ $line =~ $regex_json_spec_start ]]; then
+ elif [[ $line =~ $regex_json_spec_start || $line =~ $regex_json_limit_start ]]; then
discard=2
regex_json_end="^${line%%[^ ]*}\\},? *$"
elif [[ $line =~ $regex_json_child_start ]]; then
--
2.51.0
next prev parent reply other threads:[~2025-10-29 12:08 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-10-29 12:06 [PULL 00/18] Block layer patches Kevin Wolf
2025-10-29 12:06 ` [PULL 01/18] tests/qemu-iotests: Mark the 'inactive-node-nbd' as unsupported with -luks Kevin Wolf
2025-10-29 12:06 ` [PULL 02/18] block: remove 'detached-header' option from opts after use Kevin Wolf
2025-10-29 12:06 ` [PULL 03/18] block: fix luks 'amend' when run in coroutine Kevin Wolf
2025-10-31 10:18 ` Michael Tokarev
2025-10-31 11:05 ` Daniel P. Berrangé
2025-10-29 12:06 ` [PULL 04/18] block/monitor: Use hmp_handle_error to report error Kevin Wolf
2025-10-29 12:06 ` [PULL 05/18] block/curl.c: Fix CURLOPT_VERBOSE parameter type Kevin Wolf
2025-10-29 12:06 ` [PULL 06/18] iotests: Adjust nbd expected outputs to match current behavior Kevin Wolf
2025-10-29 12:06 ` [PULL 07/18] iotests: Adjust fuse-allow-other expected output Kevin Wolf
2025-10-29 12:06 ` [PULL 08/18] block: enable stats-intervals for storage devices Kevin Wolf
2025-10-29 12:06 ` [PULL 09/18] MAINTAINERS: Mark VHDX block driver as "Odd Fixes" Kevin Wolf
2025-10-29 12:06 ` [PULL 10/18] include/block/block_int-common: document when resize callback is used Kevin Wolf
2025-10-29 12:06 ` [PULL 11/18] block: make bdrv_co_parent_cb_resize() a proper IO API function Kevin Wolf
2025-10-29 12:06 ` [PULL 12/18] block: implement 'resize' callback for child_of_bds class Kevin Wolf
2025-10-29 12:06 ` [PULL 13/18] iotests: add test for resizing a node below filters Kevin Wolf
2025-10-29 12:06 ` [PULL 14/18] iotests: add test for resizing a 'file' node below a 'raw' node Kevin Wolf
2025-10-29 12:06 ` [PULL 15/18] block: Improve comments in BlockLimits Kevin Wolf
2025-10-29 12:06 ` Kevin Wolf [this message]
2025-10-29 12:06 ` [PULL 17/18] qemu-img info: Optionally show block limits Kevin Wolf
2025-10-29 12:06 ` [PULL 18/18] qemu-img info: Add cache mode option Kevin Wolf
2025-10-31 9:25 ` [PULL 00/18] Block layer patches Richard Henderson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20251029120634.288467-17-kwolf@redhat.com \
--to=kwolf@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).