Commit 2910b995f6 for qemu.org
commit 2910b995f6c8afd3eaa950e24432a0e044274ac5
Author: Denis V. Lunev <den@openvz.org>
Date: Mon Aug 17 13:17:34 2026 +0200
iotests: cover inactivating a read-only node
A driver which writes something out on .bdrv_inactivate has nothing to
write for a node it can not write to, and has to answer such a request
with success rather than with the error its refused write produces.
The test inactivates nodes in several ways and never a read-only one,
so nothing caught that.
Add a read-only node and take it through a deactivation and back. The
case is generic, as every driver implementing the handler has to answer
the same way.
Cc: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
diff --git a/tests/qemu-iotests/tests/inactive-node-nbd b/tests/qemu-iotests/tests/inactive-node-nbd
index 664157bfd0..24242265b1 100755
--- a/tests/qemu-iotests/tests/inactive-node-nbd
+++ b/tests/qemu-iotests/tests/inactive-node-nbd
@@ -47,6 +47,7 @@ def node_is_active(_vm, node_name):
return node['active']
with iotests.FilePath('disk.img') as path, \
+ iotests.FilePath('ro.img') as ro_path, \
iotests.FilePath('snap.qcow2') as snap_path, \
iotests.FilePath('snap2.qcow2') as snap2_path, \
iotests.FilePath('target.img') as target_path, \
@@ -58,6 +59,7 @@ with iotests.FilePath('disk.img') as path, \
iotests.log('Preparing disk...')
iotests.qemu_img_create('-f', iotests.imgfmt, path, img_size)
iotests.qemu_img_create('-f', iotests.imgfmt, target_path, img_size)
+ iotests.qemu_img_create('-f', iotests.imgfmt, ro_path, img_size)
iotests.qemu_img_create('-f', 'qcow2', '-b', path, '-F', iotests.imgfmt,
snap_path)
@@ -70,6 +72,9 @@ with iotests.FilePath('disk.img') as path, \
'active=off')
vm.add_blockdev(f'file,node-name=target-file,filename={target_path}')
vm.add_blockdev(f'{iotests.imgfmt},file=target-file,node-name=target-fmt')
+ vm.add_blockdev(f'file,node-name=ro-file,filename={ro_path},read-only=on')
+ vm.add_blockdev(f'{iotests.imgfmt},file=ro-file,node-name=ro-fmt,'
+ 'read-only=on')
vm.add_blockdev(f'file,node-name=snap-file,filename={snap_path}')
vm.add_blockdev(f'file,node-name=snap2-file,filename={snap2_path}')
@@ -289,6 +294,15 @@ with iotests.FilePath('disk.img') as path, \
iotests.log(qemu_io.cmd('map'), filters=[filter_qemu_io])
qemu_io.close()
+ iotests.log('\n=== Inactivating a read-only node ===')
+
+ # A driver which writes something out on inactivation has nothing to
+ # write for a node it can not write to, and must not fail the request
+ vm.qmp_log('blockdev-set-active', node_name='ro-fmt', active=False)
+ iotests.log('ro-fmt active: %s' % node_is_active(vm, 'ro-fmt'))
+ vm.qmp_log('blockdev-set-active', node_name='ro-fmt', active=True)
+ iotests.log('ro-fmt active: %s' % node_is_active(vm, 'ro-fmt'))
+
iotests.log('\n=== Resuming VM activates all images ===')
vm.qmp_log('cont')
diff --git a/tests/qemu-iotests/tests/inactive-node-nbd.out b/tests/qemu-iotests/tests/inactive-node-nbd.out
index 0fb8c18d87..96af7608de 100644
--- a/tests/qemu-iotests/tests/inactive-node-nbd.out
+++ b/tests/qemu-iotests/tests/inactive-node-nbd.out
@@ -227,6 +227,14 @@ qemu-io: discard failed: Operation not permitted
qemu-io: Failed to get allocation status: Operation not permitted
+=== Inactivating a read-only node ===
+{"execute": "blockdev-set-active", "arguments": {"active": false, "node-name": "ro-fmt"}}
+{"return": {}}
+ro-fmt active: False
+{"execute": "blockdev-set-active", "arguments": {"active": true, "node-name": "ro-fmt"}}
+{"return": {}}
+ro-fmt active: True
+
=== Resuming VM activates all images ===
{"execute": "cont", "arguments": {}}
{"return": {}}