* [PATCH 0/2] block: Expose block limits in monitor and qemu-img info
@ 2025-09-23 16:37 Kevin Wolf
2025-09-23 16:37 ` [PATCH 1/2] block: Expose block limits for images in QMP Kevin Wolf
` (2 more replies)
0 siblings, 3 replies; 10+ messages in thread
From: Kevin Wolf @ 2025-09-23 16:37 UTC (permalink / raw)
To: qemu-block; +Cc: kwolf, hreitz, eblake, qemu-devel
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 both in the monitor (QMP and HMP) and in
'qemu-img info'.
Kevin Wolf (2):
block: Expose block limits for images in QMP
qemu-img info: Optionally show block limits
qapi/block-core.json | 59 ++++++++++++++++++++++++++++
docs/tools/qemu-img.rst | 6 ++-
include/block/qapi.h | 2 +-
block/qapi.c | 66 ++++++++++++++++++++++++++++++--
qemu-img.c | 15 ++++++--
qemu-img-cmds.hx | 4 +-
tests/qemu-iotests/184 | 3 +-
tests/qemu-iotests/184.out | 8 ----
tests/qemu-iotests/common.filter | 3 +-
9 files changed, 145 insertions(+), 21 deletions(-)
--
2.51.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 1/2] block: Expose block limits for images in QMP
2025-09-23 16:37 [PATCH 0/2] block: Expose block limits in monitor and qemu-img info Kevin Wolf
@ 2025-09-23 16:37 ` Kevin Wolf
2025-09-23 18:03 ` Eric Blake
2025-09-24 6:10 ` Markus Armbruster
2025-09-23 16:37 ` [PATCH 2/2] qemu-img info: Optionally show block limits Kevin Wolf
2025-09-29 14:02 ` [PATCH 0/2] block: Expose block limits in monitor and qemu-img info Hanna Czenczek
2 siblings, 2 replies; 10+ messages in thread
From: Kevin Wolf @ 2025-09-23 16:37 UTC (permalink / raw)
To: qemu-block; +Cc: kwolf, hreitz, eblake, qemu-devel
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>
---
qapi/block-core.json | 59 ++++++++++++++++++++++++++++++++
block/qapi.c | 34 ++++++++++++++++--
tests/qemu-iotests/184 | 3 +-
tests/qemu-iotests/184.out | 8 -----
tests/qemu-iotests/common.filter | 3 +-
5 files changed, 94 insertions(+), 13 deletions(-)
diff --git a/qapi/block-core.json b/qapi/block-core.json
index dc6eb4ae23..eda041ac1c 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -275,6 +275,62 @@
'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. A power
+# of 2 is best, but not mandatory. 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. A power of 2 is best, but not mandatory. 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: Maximal 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: memory alignment in bytes so that no bounce buffer is needed
+#
+# @opt-mem-alignment: memory alignment in bytes that is used for bounce buffers
+##
+{ '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 +360,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 +373,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..6d44bad59f 100755
--- a/tests/qemu-iotests/184
+++ b/tests/qemu-iotests/184
@@ -46,7 +46,8 @@ do_run_qemu()
run_qemu()
{
do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu | _filter_qmp\
- | _filter_qemu_io | _filter_generated_node_ids
+ | _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
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 2/2] qemu-img info: Optionally show block limits
2025-09-23 16:37 [PATCH 0/2] block: Expose block limits in monitor and qemu-img info Kevin Wolf
2025-09-23 16:37 ` [PATCH 1/2] block: Expose block limits for images in QMP Kevin Wolf
@ 2025-09-23 16:37 ` Kevin Wolf
2025-09-23 18:09 ` Eric Blake
2025-09-29 14:02 ` [PATCH 0/2] block: Expose block limits in monitor and qemu-img info Hanna Czenczek
2 siblings, 1 reply; 10+ messages in thread
From: Kevin Wolf @ 2025-09-23 16:37 UTC (permalink / raw)
To: qemu-block; +Cc: kwolf, hreitz, eblake, qemu-devel
Add a new --limits option to 'qemu-img info' that displays the block
limits for the image and all of its children, making the information
more accessible for human users than in QMP. This option is not enabled
by default because it can be a lot of output that isn't usually relevant
if you're not specifically trying to diagnose some I/O problem.
This makes the same information automatically also available in HMP
'info block -v'.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
docs/tools/qemu-img.rst | 6 +++++-
include/block/qapi.h | 2 +-
block/qapi.c | 34 ++++++++++++++++++++++++++++++++--
qemu-img.c | 15 ++++++++++++---
qemu-img-cmds.hx | 4 ++--
5 files changed, 52 insertions(+), 9 deletions(-)
diff --git a/docs/tools/qemu-img.rst b/docs/tools/qemu-img.rst
index 5e7b85079d..fdc9ea9cf2 100644
--- a/docs/tools/qemu-img.rst
+++ b/docs/tools/qemu-img.rst
@@ -503,7 +503,7 @@ Command description:
The size syntax is similar to :manpage:`dd(1)`'s size syntax.
-.. option:: info [--object OBJECTDEF] [--image-opts] [-f FMT] [--output=OFMT] [--backing-chain] [-U] FILENAME
+.. option:: info [--object OBJECTDEF] [--image-opts] [-f FMT] [--output=OFMT] [--backing-chain] [--limits] [-U] FILENAME
Give information about the disk image *FILENAME*. Use it in
particular to know the size reserved on disk which can be different
@@ -571,6 +571,10 @@ Command description:
``ImageInfoSpecific*`` QAPI object (e.g. ``ImageInfoSpecificQCow2``
for qcow2 images).
+ *Block limits*
+ The block limits for I/O that QEMU detected for the image.
+ This information is only shown if the ``--limits`` option was specified.
+
.. option:: map [--object OBJECTDEF] [--image-opts] [-f FMT] [--start-offset=OFFSET] [--max-length=LEN] [--output=OFMT] [-U] FILENAME
Dump the metadata of image *FILENAME* and its backing file chain.
diff --git a/include/block/qapi.h b/include/block/qapi.h
index 54c48de26a..be554e53dc 100644
--- a/include/block/qapi.h
+++ b/include/block/qapi.h
@@ -42,7 +42,7 @@ bdrv_query_image_info(BlockDriverState *bs, ImageInfo **p_info, bool flat,
bool skip_implicit_filters, Error **errp);
void GRAPH_RDLOCK
bdrv_query_block_graph_info(BlockDriverState *bs, BlockGraphInfo **p_info,
- Error **errp);
+ bool limits, Error **errp);
void bdrv_snapshot_dump(QEMUSnapshotInfo *sn);
void bdrv_image_info_specific_dump(ImageInfoSpecific *info_spec,
diff --git a/block/qapi.c b/block/qapi.c
index 54521d0a68..9f5771e019 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -417,6 +417,7 @@ fail:
*/
void bdrv_query_block_graph_info(BlockDriverState *bs,
BlockGraphInfo **p_info,
+ bool limits,
Error **errp)
{
ERRP_GUARD();
@@ -425,7 +426,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), false, errp);
+ bdrv_do_query_node_info(bs, qapi_BlockGraphInfo_base(info), limits, errp);
if (*errp) {
goto fail;
}
@@ -439,7 +440,7 @@ void bdrv_query_block_graph_info(BlockDriverState *bs,
QAPI_LIST_APPEND(children_list_tail, c_info);
c_info->name = g_strdup(c->name);
- bdrv_query_block_graph_info(c->bs, &c_info->info, errp);
+ bdrv_query_block_graph_info(c->bs, &c_info->info, limits, errp);
if (*errp) {
goto fail;
}
@@ -936,6 +937,29 @@ void bdrv_image_info_specific_dump(ImageInfoSpecific *info_spec,
visit_free(v);
}
+/**
+ * Dumps the given BlockLimitsInfo object in a human-readable form,
+ * prepending an optional prefix if the dump is not empty.
+ */
+static void bdrv_image_info_limits_dump(BlockLimitsInfo *limits,
+ const char *prefix,
+ int indentation)
+{
+ QObject *obj;
+ Visitor *v = qobject_output_visitor_new(&obj);
+
+ visit_type_BlockLimitsInfo(v, NULL, &limits, &error_abort);
+ visit_complete(v, &obj);
+ if (!qobject_is_empty_dump(obj)) {
+ if (prefix) {
+ qemu_printf("%*s%s", indentation * 4, "", prefix);
+ }
+ dump_qobject(indentation + 1, obj);
+ }
+ qobject_unref(obj);
+ visit_free(v);
+}
+
/**
* Print the given @info object in human-readable form. Every field is indented
* using the given @indentation (four spaces per indentation level).
@@ -1011,6 +1035,12 @@ void bdrv_node_info_dump(BlockNodeInfo *info, int indentation, bool protocol)
}
}
+ if (info->limits) {
+ bdrv_image_info_limits_dump(info->limits,
+ "Block limits:\n",
+ indentation);
+ }
+
if (info->has_snapshots) {
SnapshotInfoList *elem;
diff --git a/qemu-img.c b/qemu-img.c
index 7a162fdc08..5cdbeda969 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -86,6 +86,7 @@ enum {
OPTION_BITMAPS = 275,
OPTION_FORCE = 276,
OPTION_SKIP_BROKEN = 277,
+ OPTION_LIMITS = 278,
};
typedef enum OutputFormat {
@@ -3002,7 +3003,8 @@ static gboolean str_equal_func(gconstpointer a, gconstpointer b)
static BlockGraphInfoList *collect_image_info_list(bool image_opts,
const char *filename,
const char *fmt,
- bool chain, bool force_share)
+ bool chain, bool limits,
+ bool force_share)
{
BlockGraphInfoList *head = NULL;
BlockGraphInfoList **tail = &head;
@@ -3039,7 +3041,7 @@ static BlockGraphInfoList *collect_image_info_list(bool image_opts,
* the chain manually here.
*/
bdrv_graph_rdlock_main_loop();
- bdrv_query_block_graph_info(bs, &info, &err);
+ bdrv_query_block_graph_info(bs, &info, limits, &err);
bdrv_graph_rdunlock_main_loop();
if (err) {
@@ -3088,6 +3090,7 @@ static int img_info(const img_cmd_t *ccmd, int argc, char **argv)
BlockGraphInfoList *list;
bool image_opts = false;
bool force_share = false;
+ bool limits = false;
fmt = NULL;
for(;;) {
@@ -3097,6 +3100,7 @@ static int img_info(const img_cmd_t *ccmd, int argc, char **argv)
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
{"backing-chain", no_argument, 0, OPTION_BACKING_CHAIN},
{"force-share", no_argument, 0, 'U'},
+ {"limits", no_argument, 0, OPTION_LIMITS},
{"output", required_argument, 0, OPTION_OUTPUT},
{"object", required_argument, 0, OPTION_OBJECT},
{0, 0, 0, 0}
@@ -3119,6 +3123,8 @@ static int img_info(const img_cmd_t *ccmd, int argc, char **argv)
" display information about the backing chain for copy-on-write overlays\n"
" -U, --force-share\n"
" open image in shared mode for concurrent access\n"
+" --limits\n"
+" show detected block limits (may depend on options, e.g. cache mode)\n"
" --output human|json\n"
" specify output format (default: human)\n"
" --object OBJDEF\n"
@@ -3140,6 +3146,9 @@ static int img_info(const img_cmd_t *ccmd, int argc, char **argv)
case 'U':
force_share = true;
break;
+ case OPTION_LIMITS:
+ limits = true;
+ break;
case OPTION_OUTPUT:
output_format = parse_output_format(argv[0], optarg);
break;
@@ -3156,7 +3165,7 @@ static int img_info(const img_cmd_t *ccmd, int argc, char **argv)
filename = argv[optind++];
list = collect_image_info_list(image_opts, filename, fmt, chain,
- force_share);
+ limits, force_share);
if (!list) {
return 1;
}
diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
index 2c5a8a28f9..74b66f9d42 100644
--- a/qemu-img-cmds.hx
+++ b/qemu-img-cmds.hx
@@ -66,9 +66,9 @@ SRST
ERST
DEF("info", img_info,
- "info [--object objectdef] [--image-opts] [-f fmt] [--output=ofmt] [--backing-chain] [-U] filename")
+ "info [--object objectdef] [--image-opts] [-f fmt] [--output=ofmt] [--backing-chain] [--limits] [-U] filename")
SRST
-.. option:: info [--object OBJECTDEF] [--image-opts] [-f FMT] [--output=OFMT] [--backing-chain] [-U] FILENAME
+.. option:: info [--object OBJECTDEF] [--image-opts] [-f FMT] [--output=OFMT] [--backing-chain] [--limits] [-U] FILENAME
ERST
DEF("map", img_map,
--
2.51.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] block: Expose block limits for images in QMP
2025-09-23 16:37 ` [PATCH 1/2] block: Expose block limits for images in QMP Kevin Wolf
@ 2025-09-23 18:03 ` Eric Blake
2025-09-24 6:10 ` Markus Armbruster
1 sibling, 0 replies; 10+ messages in thread
From: Eric Blake @ 2025-09-23 18:03 UTC (permalink / raw)
To: Kevin Wolf; +Cc: qemu-block, hreitz, qemu-devel
On Tue, Sep 23, 2025 at 06:37:34PM +0200, Kevin Wolf wrote:
> 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>
> ---
> qapi/block-core.json | 59 ++++++++++++++++++++++++++++++++
> block/qapi.c | 34 ++++++++++++++++--
> tests/qemu-iotests/184 | 3 +-
> tests/qemu-iotests/184.out | 8 -----
> tests/qemu-iotests/common.filter | 3 +-
> 5 files changed, 94 insertions(+), 13 deletions(-)
>
> diff --git a/qapi/block-core.json b/qapi/block-core.json
> index dc6eb4ae23..eda041ac1c 100644
> --- a/qapi/block-core.json
> +++ b/qapi/block-core.json
> @@ -275,6 +275,62 @@
> 'file': 'ImageInfoSpecificFileWrapper'
> } }
>
> +##
> +# @BlockLimitsInfo:
Quite a few additions to the QMP, but this is really just exposing
what we already have. I don't think the larger output is going to
make QMP any noticeably slower, and it's not recursive, so I have no
objection to your decision of just always exposing it.
> +++ b/tests/qemu-iotests/184
> @@ -46,7 +46,8 @@ do_run_qemu()
> run_qemu()
> {
> do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu | _filter_qmp\
> - | _filter_qemu_io | _filter_generated_node_ids
> + | _filter_qemu_io | _filter_generated_node_ids \
> + | _filter_img_info
Inconsistent on absence or use of space before backslash-newline.
Cosmetic only.
Reviewed-by: Eric Blake <eblake@redhat.com>
--
Eric Blake, Principal Software Engineer
Red Hat, Inc.
Virtualization: qemu.org | libguestfs.org
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/2] qemu-img info: Optionally show block limits
2025-09-23 16:37 ` [PATCH 2/2] qemu-img info: Optionally show block limits Kevin Wolf
@ 2025-09-23 18:09 ` Eric Blake
2025-09-24 8:28 ` Kevin Wolf
0 siblings, 1 reply; 10+ messages in thread
From: Eric Blake @ 2025-09-23 18:09 UTC (permalink / raw)
To: Kevin Wolf; +Cc: qemu-block, hreitz, qemu-devel
On Tue, Sep 23, 2025 at 06:37:35PM +0200, Kevin Wolf wrote:
> Add a new --limits option to 'qemu-img info' that displays the block
> limits for the image and all of its children, making the information
> more accessible for human users than in QMP. This option is not enabled
> by default because it can be a lot of output that isn't usually relevant
> if you're not specifically trying to diagnose some I/O problem.
>
> This makes the same information automatically also available in HMP
> 'info block -v'.
>
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> ---
> docs/tools/qemu-img.rst | 6 +++++-
> include/block/qapi.h | 2 +-
> block/qapi.c | 34 ++++++++++++++++++++++++++++++++--
> qemu-img.c | 15 ++++++++++++---
> qemu-img-cmds.hx | 4 ++--
> 5 files changed, 52 insertions(+), 9 deletions(-)
>
> +++ b/qemu-img.c
> @@ -3119,6 +3123,8 @@ static int img_info(const img_cmd_t *ccmd, int argc, char **argv)
> " display information about the backing chain for copy-on-write overlays\n"
> " -U, --force-share\n"
> " open image in shared mode for concurrent access\n"
> +" --limits\n"
> +" show detected block limits (may depend on options, e.g. cache mode)\n"
I'm trying to figure out how the parenthetical helps the --help
message. The fact that it is detected limits already implies that
anything else (like cache mode) that can change what gets detected
would have an impact. So I think it would be fine to just use " show
detected block limits\n".
But overall, I like the idea of being able to display what used to be
internal information.
Reviewed-by: Eric Blake <eblake@redhat.com>
--
Eric Blake, Principal Software Engineer
Red Hat, Inc.
Virtualization: qemu.org | libguestfs.org
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] block: Expose block limits for images in QMP
2025-09-23 16:37 ` [PATCH 1/2] block: Expose block limits for images in QMP Kevin Wolf
2025-09-23 18:03 ` Eric Blake
@ 2025-09-24 6:10 ` Markus Armbruster
2025-09-24 9:05 ` Kevin Wolf
1 sibling, 1 reply; 10+ messages in thread
From: Markus Armbruster @ 2025-09-24 6:10 UTC (permalink / raw)
To: Kevin Wolf; +Cc: qemu-block, hreitz, eblake, qemu-devel
Kevin Wolf <kwolf@redhat.com> writes:
> 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>
> ---
> qapi/block-core.json | 59 ++++++++++++++++++++++++++++++++
> block/qapi.c | 34 ++++++++++++++++--
> tests/qemu-iotests/184 | 3 +-
> tests/qemu-iotests/184.out | 8 -----
> tests/qemu-iotests/common.filter | 3 +-
> 5 files changed, 94 insertions(+), 13 deletions(-)
>
> diff --git a/qapi/block-core.json b/qapi/block-core.json
> index dc6eb4ae23..eda041ac1c 100644
> --- a/qapi/block-core.json
> +++ b/qapi/block-core.json
> @@ -275,6 +275,62 @@
> '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. A power
> +# of 2 is best, but not mandatory. If not present, discards don't have a
> +# alignment requirement different from @request-alignment.
What does the second sentence try to convey? As far as I can tell, QMP
has BlockLimitsInfo is only in the result of query-block and
query-named-block-nodes, i.e. it's not something the user picks.
> +#
> +# @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. A power of 2 is best, but not mandatory. If not present,
> +# write_zeroes doesn't have a alignment requirement different from
> +# @request-alignment.
Likewise.
> +#
> +# @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: Maximal number of scatter/gather elements allowed by the hardware.
Maximum number
> +# 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: memory alignment in bytes so that no bounce buffer is needed
> +#
> +# @opt-mem-alignment: memory alignment in bytes that is used for bounce buffers
Why is this "opt"? I guess it means "optimal".
> +##
> +{ '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 +360,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 +373,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' } }
>
> ##
docs/devel/qapi-code-gen.rst:
For legibility, wrap text paragraphs so every line is at most 70
characters long.
Separate sentences with two spaces.
[...]
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/2] qemu-img info: Optionally show block limits
2025-09-23 18:09 ` Eric Blake
@ 2025-09-24 8:28 ` Kevin Wolf
0 siblings, 0 replies; 10+ messages in thread
From: Kevin Wolf @ 2025-09-24 8:28 UTC (permalink / raw)
To: Eric Blake; +Cc: qemu-block, hreitz, qemu-devel
Am 23.09.2025 um 20:09 hat Eric Blake geschrieben:
> On Tue, Sep 23, 2025 at 06:37:35PM +0200, Kevin Wolf wrote:
> > Add a new --limits option to 'qemu-img info' that displays the block
> > limits for the image and all of its children, making the information
> > more accessible for human users than in QMP. This option is not enabled
> > by default because it can be a lot of output that isn't usually relevant
> > if you're not specifically trying to diagnose some I/O problem.
> >
> > This makes the same information automatically also available in HMP
> > 'info block -v'.
> >
> > Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> > ---
> > docs/tools/qemu-img.rst | 6 +++++-
> > include/block/qapi.h | 2 +-
> > block/qapi.c | 34 ++++++++++++++++++++++++++++++++--
> > qemu-img.c | 15 ++++++++++++---
> > qemu-img-cmds.hx | 4 ++--
> > 5 files changed, 52 insertions(+), 9 deletions(-)
> >
>
> > +++ b/qemu-img.c
>
> > @@ -3119,6 +3123,8 @@ static int img_info(const img_cmd_t *ccmd, int argc, char **argv)
> > " display information about the backing chain for copy-on-write overlays\n"
> > " -U, --force-share\n"
> > " open image in shared mode for concurrent access\n"
> > +" --limits\n"
> > +" show detected block limits (may depend on options, e.g. cache mode)\n"
>
> I'm trying to figure out how the parenthetical helps the --help
> message. The fact that it is detected limits already implies that
> anything else (like cache mode) that can change what gets detected
> would have an impact. So I think it would be fine to just use " show
> detected block limits\n".
Yes, other options can influence the limits, too. I just thought that
the most common pitfall for users will be that they actually want to
know the limits for cache=none because that's what their VM uses, but
'qemu-img info' returns them for cache=writeback. So it felt helpful to
add the note. But if you think that we'd better leave it out, I can
remove it.
Actually, this reminds me that I wanted to add a -t <cache_mode> option
to 'qemu-img info', too, so that you can actually get the interesting
information without using --image-opts. That will be something for a
separate patch, though.
Kevin
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] block: Expose block limits for images in QMP
2025-09-24 6:10 ` Markus Armbruster
@ 2025-09-24 9:05 ` Kevin Wolf
2025-09-24 10:43 ` Markus Armbruster
0 siblings, 1 reply; 10+ messages in thread
From: Kevin Wolf @ 2025-09-24 9:05 UTC (permalink / raw)
To: Markus Armbruster; +Cc: qemu-block, hreitz, eblake, qemu-devel
Am 24.09.2025 um 08:10 hat Markus Armbruster geschrieben:
> Kevin Wolf <kwolf@redhat.com> writes:
>
> > 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>
> > ---
> > qapi/block-core.json | 59 ++++++++++++++++++++++++++++++++
> > block/qapi.c | 34 ++++++++++++++++--
> > tests/qemu-iotests/184 | 3 +-
> > tests/qemu-iotests/184.out | 8 -----
> > tests/qemu-iotests/common.filter | 3 +-
> > 5 files changed, 94 insertions(+), 13 deletions(-)
> >
> > diff --git a/qapi/block-core.json b/qapi/block-core.json
> > index dc6eb4ae23..eda041ac1c 100644
> > --- a/qapi/block-core.json
> > +++ b/qapi/block-core.json
> > @@ -275,6 +275,62 @@
> > '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. A power
> > +# of 2 is best, but not mandatory. If not present, discards don't have a
> > +# alignment requirement different from @request-alignment.
>
> What does the second sentence try to convey? As far as I can tell, QMP
> has BlockLimitsInfo is only in the result of query-block and
> query-named-block-nodes, i.e. it's not something the user picks.
I copied these descriptions from the comments in struct BlockLimits,
just leaving out things that are clearly internal. Their nature is the
same there, we never configure block limits, we only detect them.
What I think this sentence wants to tell us is that while you may
intuitively expect power-of-two limits, you shouldn't be surprised to
occasionally find other numbers here, too.
Maybe "Note that this doesn't have to be a power of two" instead? Both
in QAPI and the struct definition.
> > +#
> > +# @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. A power of 2 is best, but not mandatory. If not present,
> > +# write_zeroes doesn't have a alignment requirement different from
> > +# @request-alignment.
>
> Likewise.
>
> > +#
> > +# @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: Maximal number of scatter/gather elements allowed by the hardware.
>
> Maximum number
>
> > +# 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: memory alignment in bytes so that no bounce buffer is needed
> > +#
> > +# @opt-mem-alignment: memory alignment in bytes that is used for bounce buffers
>
> Why is this "opt"? I guess it means "optimal".
Yes, I think so. How about this:
@min-mem-alignment: Minimal required memory alignment in bytes for
zero-copy I/O to succeed. For unaligned requrests, 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 +360,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 +373,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' } }
> >
> > ##
>
> docs/devel/qapi-code-gen.rst:
>
> For legibility, wrap text paragraphs so every line is at most 70
> characters long.
>
> Separate sentences with two spaces.
It would be better to use a uniform text width across the project that
can be trivially configured in every editor than wasting our brain
cycles on manually enforcing an idiosyncratic style in certain parts of
certain files.
I'll make the change for this patch, but without tool support, I'm
almost sure that this will happen again and again.
Kevin
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] block: Expose block limits for images in QMP
2025-09-24 9:05 ` Kevin Wolf
@ 2025-09-24 10:43 ` Markus Armbruster
0 siblings, 0 replies; 10+ messages in thread
From: Markus Armbruster @ 2025-09-24 10:43 UTC (permalink / raw)
To: Kevin Wolf; +Cc: qemu-block, hreitz, eblake, qemu-devel
Kevin Wolf <kwolf@redhat.com> writes:
> Am 24.09.2025 um 08:10 hat Markus Armbruster geschrieben:
>> Kevin Wolf <kwolf@redhat.com> writes:
>>
>> > 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>
>> > ---
>> > qapi/block-core.json | 59 ++++++++++++++++++++++++++++++++
>> > block/qapi.c | 34 ++++++++++++++++--
>> > tests/qemu-iotests/184 | 3 +-
>> > tests/qemu-iotests/184.out | 8 -----
>> > tests/qemu-iotests/common.filter | 3 +-
>> > 5 files changed, 94 insertions(+), 13 deletions(-)
>> >
>> > diff --git a/qapi/block-core.json b/qapi/block-core.json
>> > index dc6eb4ae23..eda041ac1c 100644
>> > --- a/qapi/block-core.json
>> > +++ b/qapi/block-core.json
>> > @@ -275,6 +275,62 @@
>> > '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. A power
>> > +# of 2 is best, but not mandatory. If not present, discards don't have a
>> > +# alignment requirement different from @request-alignment.
>>
>> What does the second sentence try to convey? As far as I can tell, QMP
>> has BlockLimitsInfo is only in the result of query-block and
>> query-named-block-nodes, i.e. it's not something the user picks.
>
> I copied these descriptions from the comments in struct BlockLimits,
> just leaving out things that are clearly internal. Their nature is the
> same there, we never configure block limits, we only detect them.
>
> What I think this sentence wants to tell us is that while you may
> intuitively expect power-of-two limits, you shouldn't be surprised to
> occasionally find other numbers here, too.
Well, I would be surprised, so having the doc mention it makes sense.
> Maybe "Note that this doesn't have to be a power of two" instead? Both
> in QAPI and the struct definition.
Works for me.
>> > +#
>> > +# @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. A power of 2 is best, but not mandatory. If not present,
>> > +# write_zeroes doesn't have a alignment requirement different from
>> > +# @request-alignment.
>>
>> Likewise.
>>
>> > +#
>> > +# @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: Maximal number of scatter/gather elements allowed by the hardware.
>>
>> Maximum number
>>
>> > +# 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: memory alignment in bytes so that no bounce buffer is needed
>> > +#
>> > +# @opt-mem-alignment: memory alignment in bytes that is used for bounce buffers
>>
>> Why is this "opt"? I guess it means "optimal".
>
> Yes, I think so. How about this:
>
> @min-mem-alignment: Minimal required memory alignment in bytes for
> zero-copy I/O to succeed. For unaligned requrests, a bounce buffer will
requests
> be used.
>
> @opt-mem-alignment: Optimal memory alignment in bytes. This is the
> alignment used for any buffer allocations QEMU performs internally.
Good!
[...]
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 0/2] block: Expose block limits in monitor and qemu-img info
2025-09-23 16:37 [PATCH 0/2] block: Expose block limits in monitor and qemu-img info Kevin Wolf
2025-09-23 16:37 ` [PATCH 1/2] block: Expose block limits for images in QMP Kevin Wolf
2025-09-23 16:37 ` [PATCH 2/2] qemu-img info: Optionally show block limits Kevin Wolf
@ 2025-09-29 14:02 ` Hanna Czenczek
2 siblings, 0 replies; 10+ messages in thread
From: Hanna Czenczek @ 2025-09-29 14:02 UTC (permalink / raw)
To: Kevin Wolf, qemu-block; +Cc: eblake, qemu-devel
On 23.09.25 18:37, Kevin Wolf wrote:
> 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 both in the monitor (QMP and HMP) and in
> 'qemu-img info'.
>
> Kevin Wolf (2):
> block: Expose block limits for images in QMP
> qemu-img info: Optionally show block limits
With or without the comment changes to patch 1:
Reviewed-by: Hanna Czenczek <hreitz@redhat.com>
(And I vote for keeping the paranthesized text in patch 2.)
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2025-09-29 14:04 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-23 16:37 [PATCH 0/2] block: Expose block limits in monitor and qemu-img info Kevin Wolf
2025-09-23 16:37 ` [PATCH 1/2] block: Expose block limits for images in QMP Kevin Wolf
2025-09-23 18:03 ` Eric Blake
2025-09-24 6:10 ` Markus Armbruster
2025-09-24 9:05 ` Kevin Wolf
2025-09-24 10:43 ` Markus Armbruster
2025-09-23 16:37 ` [PATCH 2/2] qemu-img info: Optionally show block limits Kevin Wolf
2025-09-23 18:09 ` Eric Blake
2025-09-24 8:28 ` Kevin Wolf
2025-09-29 14:02 ` [PATCH 0/2] block: Expose block limits in monitor and qemu-img info Hanna Czenczek
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).