block/qapi.c | 4 ++++ qapi/block-core.json | 4 ++++ tests/qemu-iotests/184.out | 1 + tests/qemu-iotests/191.out | 8 ++++++++ tests/qemu-iotests/273.out | 2 ++ 5 files changed, 19 insertions(+)
In combination with using a throttle filter to enforce IO limits for
a guest device, knowing the 'file' child of a block device can be
useful. If the throttle filter is only intended for guest IO, block
jobs should not also be limited by the throttle filter, so the
block operations need to be done with the 'file' child of the top
throttle node as the target. In combination with mirroring, the name
of that child is not fixed.
Another scenario is when unplugging a guest device after mirroring
below a top throttle node, where the mirror target is added explicitly
via blockdev-add. After mirroring, the target becomes the new 'file'
child of the throttle node. For unplugging, both the top throttle node
and the mirror target need to be deleted, because only implicitly
added child nodes are deleted automatically, and the current 'file'
child of the throttle node was explicitly added (as the mirror
target).
Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
---
block/qapi.c | 4 ++++
qapi/block-core.json | 4 ++++
tests/qemu-iotests/184.out | 1 +
tests/qemu-iotests/191.out | 8 ++++++++
tests/qemu-iotests/273.out | 2 ++
5 files changed, 19 insertions(+)
diff --git a/block/qapi.c b/block/qapi.c
index 2c50a6bf3b..bbca042baf 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -77,6 +77,10 @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
info->node_name = g_strdup(bs->node_name);
}
+ if (bs->file && bs->file->bs && bs->file->bs->node_name[0]) {
+ info->file_child_node_name = g_strdup(bs->file->bs->node_name);
+ }
+
backing = bdrv_cow_bs(bs);
if (backing) {
info->backing_file = g_strdup(backing->filename);
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 1df6644f0d..74d049606b 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -481,6 +481,9 @@
# 2.5: 'host_floppy' dropped 2.6: 'luks' added 2.8: 'replication'
# added, 'tftp' dropped 2.9: 'archipelago' dropped
#
+# @file-child-node-name: the name of the 'file' child block driver node.
+# (since: 10.1)
+#
# @backing_file: the name of the backing file (for copy-on-write)
#
# @backing_file_depth: number of files in the backing file chain
@@ -559,6 +562,7 @@
##
{ 'struct': 'BlockDeviceInfo',
'data': { 'file': 'str', '*node-name': 'str', 'ro': 'bool', 'drv': 'str',
+ '*file-child-node-name': 'str',
'*backing_file': 'str', 'backing_file_depth': 'int',
'active': 'bool', 'encrypted': 'bool',
'detect_zeroes': 'BlockdevDetectZeroesOptions',
diff --git a/tests/qemu-iotests/184.out b/tests/qemu-iotests/184.out
index 52692b6b3b..aa02df950b 100644
--- a/tests/qemu-iotests/184.out
+++ b/tests/qemu-iotests/184.out
@@ -47,6 +47,7 @@ Testing:
"iops": 0,
"bps_wr": 0,
"write_threshold": 0,
+ "file-child-node-name": "disk0",
"encrypted": false,
"bps": 0,
"bps_rd": 0,
diff --git a/tests/qemu-iotests/191.out b/tests/qemu-iotests/191.out
index 2a72ca7106..f29e1b5209 100644
--- a/tests/qemu-iotests/191.out
+++ b/tests/qemu-iotests/191.out
@@ -143,6 +143,7 @@ wrote 65536/65536 bytes at offset 1048576
"bps_wr": 0,
"write_threshold": 0,
"backing_file": "TEST_DIR/t.IMGFMT.base",
+ "file-child-node-name": "NODE_NAME",
"encrypted": false,
"bps": 0,
"bps_rd": 0,
@@ -214,6 +215,7 @@ wrote 65536/65536 bytes at offset 1048576
"bps_wr": 0,
"write_threshold": 0,
"backing_file": "TEST_DIR/t.IMGFMT.base",
+ "file-child-node-name": "NODE_NAME",
"encrypted": false,
"bps": 0,
"bps_rd": 0,
@@ -285,6 +287,7 @@ wrote 65536/65536 bytes at offset 1048576
"bps_wr": 0,
"write_threshold": 0,
"backing_file": "TEST_DIR/t.IMGFMT.base",
+ "file-child-node-name": "NODE_NAME",
"encrypted": false,
"bps": 0,
"bps_rd": 0,
@@ -344,6 +347,7 @@ wrote 65536/65536 bytes at offset 1048576
"iops": 0,
"bps_wr": 0,
"write_threshold": 0,
+ "file-child-node-name": "NODE_NAME",
"encrypted": false,
"bps": 0,
"bps_rd": 0,
@@ -558,6 +562,7 @@ wrote 65536/65536 bytes at offset 1048576
"bps_wr": 0,
"write_threshold": 0,
"backing_file": "TEST_DIR/t.IMGFMT.base",
+ "file-child-node-name": "NODE_NAME",
"encrypted": false,
"bps": 0,
"bps_rd": 0,
@@ -640,6 +645,7 @@ wrote 65536/65536 bytes at offset 1048576
"bps_wr": 0,
"write_threshold": 0,
"backing_file": "TEST_DIR/t.IMGFMT.ovl2",
+ "file-child-node-name": "NODE_NAME",
"encrypted": false,
"bps": 0,
"bps_rd": 0,
@@ -699,6 +705,7 @@ wrote 65536/65536 bytes at offset 1048576
"iops": 0,
"bps_wr": 0,
"write_threshold": 0,
+ "file-child-node-name": "NODE_NAME",
"encrypted": false,
"bps": 0,
"bps_rd": 0,
@@ -770,6 +777,7 @@ wrote 65536/65536 bytes at offset 1048576
"bps_wr": 0,
"write_threshold": 0,
"backing_file": "TEST_DIR/t.IMGFMT.base",
+ "file-child-node-name": "NODE_NAME",
"encrypted": false,
"bps": 0,
"bps_rd": 0,
diff --git a/tests/qemu-iotests/273.out b/tests/qemu-iotests/273.out
index c19753c685..eabe95c1a0 100644
--- a/tests/qemu-iotests/273.out
+++ b/tests/qemu-iotests/273.out
@@ -62,6 +62,7 @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev
"bps_wr": 0,
"write_threshold": 0,
"backing_file": "TEST_DIR/t.IMGFMT.mid",
+ "file-child-node-name": "topf",
"encrypted": false,
"bps": 0,
"bps_rd": 0,
@@ -132,6 +133,7 @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev
"bps_wr": 0,
"write_threshold": 0,
"backing_file": "TEST_DIR/t.IMGFMT.base",
+ "file-child-node-name": "midf",
"encrypted": false,
"bps": 0,
"bps_rd": 0,
--
2.47.2
On 30.06.25 16:06, Fiona Ebner wrote: > In combination with using a throttle filter to enforce IO limits for > a guest device, knowing the 'file' child of a block device can be > useful. If the throttle filter is only intended for guest IO, block > jobs should not also be limited by the throttle filter, so the > block operations need to be done with the 'file' child of the top > throttle node as the target. In combination with mirroring, the name > of that child is not fixed. > > Another scenario is when unplugging a guest device after mirroring > below a top throttle node, where the mirror target is added explicitly > via blockdev-add. After mirroring, the target becomes the new 'file' > child of the throttle node. For unplugging, both the top throttle node > and the mirror target need to be deleted, because only implicitly > added child nodes are deleted automatically, and the current 'file' > child of the throttle node was explicitly added (as the mirror > target). Why not return a map of all children? Hanna > Signed-off-by: Fiona Ebner <f.ebner@proxmox.com> > --- > block/qapi.c | 4 ++++ > qapi/block-core.json | 4 ++++ > tests/qemu-iotests/184.out | 1 + > tests/qemu-iotests/191.out | 8 ++++++++ > tests/qemu-iotests/273.out | 2 ++ > 5 files changed, 19 insertions(+)
Am 01.07.2025 um 15:04 hat Hanna Czenczek geschrieben:
> On 30.06.25 16:06, Fiona Ebner wrote:
> > In combination with using a throttle filter to enforce IO limits for
> > a guest device, knowing the 'file' child of a block device can be
> > useful. If the throttle filter is only intended for guest IO, block
> > jobs should not also be limited by the throttle filter, so the
> > block operations need to be done with the 'file' child of the top
> > throttle node as the target. In combination with mirroring, the name
> > of that child is not fixed.
> >
> > Another scenario is when unplugging a guest device after mirroring
> > below a top throttle node, where the mirror target is added explicitly
> > via blockdev-add. After mirroring, the target becomes the new 'file'
> > child of the throttle node. For unplugging, both the top throttle node
> > and the mirror target need to be deleted, because only implicitly
> > added child nodes are deleted automatically, and the current 'file'
> > child of the throttle node was explicitly added (as the mirror
> > target).
>
> Why not return a map of all children?
I had the same thought, just didn't get around to actually replying. I
think "a map" in this context will be a list of objects, like this:
"children": [
{ "child": "file", "node-name": "foo" },
{ "child": "backing", "node-name": "bar" }
]
Which as a side effect automatically gives us extensibility if we ever
want to expose more details of BdrvChild.
Kevin
Am 01.07.25 um 15:04 schrieb Hanna Czenczek: > On 30.06.25 16:06, Fiona Ebner wrote: >> In combination with using a throttle filter to enforce IO limits for >> a guest device, knowing the 'file' child of a block device can be >> useful. If the throttle filter is only intended for guest IO, block >> jobs should not also be limited by the throttle filter, so the >> block operations need to be done with the 'file' child of the top >> throttle node as the target. In combination with mirroring, the name >> of that child is not fixed. >> >> Another scenario is when unplugging a guest device after mirroring >> below a top throttle node, where the mirror target is added explicitly >> via blockdev-add. After mirroring, the target becomes the new 'file' >> child of the throttle node. For unplugging, both the top throttle node >> and the mirror target need to be deleted, because only implicitly >> added child nodes are deleted automatically, and the current 'file' >> child of the throttle node was explicitly added (as the mirror >> target). > > Why not return a map of all children? No particular reason, I just didn't need to look at the others for my use-cases. I'll try and go for the map in v2. Best Regards, Fiona
© 2016 - 2025 Red Hat, Inc.