summaryrefslogtreecommitdiffstats
path: root/tests/qemu-iotests
diff options
context:
space:
mode:
authorHanna Reitz2022-08-03 16:44:46 +0200
committerKevin Wolf2022-09-30 18:43:44 +0200
commit283153f10ab474cb2f14cc2b3f272edcf13aedaf (patch)
tree71caa8b2f010cc07e4b800deb1691d124d767fc7 /tests/qemu-iotests
parentblock/qed: Keep auto_backing_file if possible (diff)
downloadqemu-283153f10ab474cb2f14cc2b3f272edcf13aedaf.tar.gz
qemu-283153f10ab474cb2f14cc2b3f272edcf13aedaf.tar.xz
qemu-283153f10ab474cb2f14cc2b3f272edcf13aedaf.zip
iotests/backing-file-invalidation: Add new test
Add a new test to see what happens when you migrate a VM with a backing chain that has json:{} backing file strings, which, when opened, will be resolved to plain filenames. Signed-off-by: Hanna Reitz <hreitz@redhat.com> Message-Id: <20220803144446.20723-4-hreitz@redhat.com> Reviewed-by: Kevin Wolf <kwolf@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Diffstat (limited to 'tests/qemu-iotests')
-rwxr-xr-xtests/qemu-iotests/tests/backing-file-invalidation152
-rw-r--r--tests/qemu-iotests/tests/backing-file-invalidation.out5
2 files changed, 157 insertions, 0 deletions
diff --git a/tests/qemu-iotests/tests/backing-file-invalidation b/tests/qemu-iotests/tests/backing-file-invalidation
new file mode 100755
index 0000000000..4eccc80153
--- /dev/null
+++ b/tests/qemu-iotests/tests/backing-file-invalidation
@@ -0,0 +1,152 @@
+#!/usr/bin/env python3
+# group: rw migration
+#
+# Migrate a VM with a BDS with backing nodes, which runs
+# bdrv_invalidate_cache(), which for qcow2 and qed triggers reading the
+# backing file string from the image header. Check whether this
+# interferes with bdrv_backing_overridden().
+#
+# Copyright (C) 2022 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+import json
+import os
+from typing import Optional
+
+import iotests
+from iotests import qemu_img_create, qemu_img_info
+
+
+image_size = 1 * 1024 * 1024
+imgs = [os.path.join(iotests.test_dir, f'{i}.img') for i in range(0, 4)]
+
+mig_sock = os.path.join(iotests.sock_dir, 'mig.sock')
+
+
+class TestPostMigrateFilename(iotests.QMPTestCase):
+ vm_s: Optional[iotests.VM] = None
+ vm_d: Optional[iotests.VM] = None
+
+ def setUp(self) -> None:
+ # Create backing chain of three images, where the backing file strings
+ # are json:{} filenames
+ qemu_img_create('-f', iotests.imgfmt, imgs[0], str(image_size))
+ for i in range(1, 3):
+ backing = {
+ 'driver': iotests.imgfmt,
+ 'file': {
+ 'driver': 'file',
+ 'filename': imgs[i - 1]
+ }
+ }
+ qemu_img_create('-f', iotests.imgfmt, '-F', iotests.imgfmt,
+ '-b', 'json:' + json.dumps(backing),
+ imgs[i], str(image_size))
+
+ def tearDown(self) -> None:
+ if self.vm_s is not None:
+ self.vm_s.shutdown()
+ if self.vm_d is not None:
+ self.vm_d.shutdown()
+
+ for img in imgs:
+ try:
+ os.remove(img)
+ except OSError:
+ pass
+ try:
+ os.remove(mig_sock)
+ except OSError:
+ pass
+
+ def test_migration(self) -> None:
+ """
+ Migrate a VM with the backing chain created in setUp() attached. At
+ the end of the migration process, the destination will run
+ bdrv_invalidate_cache(), which for some image formats (qcow2 and qed)
+ means the backing file string is re-read from the image header. If
+ this overwrites bs->auto_backing_file, doing so may cause
+ bdrv_backing_overridden() to become true: The image header reports a
+ json:{} filename, but when opening it, bdrv_refresh_filename() will
+ simplify it to a plain simple filename; and when bs->auto_backing_file
+ and bs->backing->bs->filename differ, bdrv_backing_overridden() becomes
+ true.
+ If bdrv_backing_overridden() is true, the BDS will be forced to get a
+ json:{} filename, which in general is not the end of the world, but not
+ great. Check whether that happens, i.e. whether migration changes the
+ node's filename.
+ """
+
+ blockdev = {
+ 'node-name': 'node0',
+ 'driver': iotests.imgfmt,
+ 'file': {
+ 'driver': 'file',
+ 'filename': imgs[2]
+ }
+ }
+
+ self.vm_s = iotests.VM(path_suffix='a') \
+ .add_blockdev(json.dumps(blockdev))
+ self.vm_d = iotests.VM(path_suffix='b') \
+ .add_blockdev(json.dumps(blockdev)) \
+ .add_incoming(f'unix:{mig_sock}')
+
+ assert self.vm_s is not None
+ assert self.vm_d is not None
+
+ self.vm_s.launch()
+ self.vm_d.launch()
+
+ pre_mig_filename = self.vm_s.node_info('node0')['file']
+
+ self.vm_s.qmp('migrate', uri=f'unix:{mig_sock}')
+
+ # Wait for migration to be done
+ self.vm_s.event_wait('STOP')
+ self.vm_d.event_wait('RESUME')
+
+ post_mig_filename = self.vm_d.node_info('node0')['file']
+
+ # Verify that the filename hasn't changed from before the migration
+ self.assertEqual(pre_mig_filename, post_mig_filename)
+
+ self.vm_s.shutdown()
+ self.vm_s = None
+
+ # For good measure, try creating an overlay and check its backing
+ # chain below. This is how the issue was originally found.
+ result = self.vm_d.qmp('blockdev-snapshot-sync',
+ format=iotests.imgfmt,
+ snapshot_file=imgs[3],
+ node_name='node0',
+ snapshot_node_name='node0-overlay')
+ self.assert_qmp(result, 'return', {})
+
+ self.vm_d.shutdown()
+ self.vm_d = None
+
+ # Check the newly created overlay's backing chain
+ chain = qemu_img_info('--backing-chain', imgs[3])
+ for index, image in enumerate(chain):
+ self.assertEqual(image['filename'], imgs[3 - index])
+
+
+if __name__ == '__main__':
+ # These are the image formats that run their open() function from their
+ # .bdrv_co_invaliate_cache() implementations, so test them
+ iotests.main(supported_fmts=['qcow2', 'qed'],
+ supported_protocols=['file'])
diff --git a/tests/qemu-iotests/tests/backing-file-invalidation.out b/tests/qemu-iotests/tests/backing-file-invalidation.out
new file mode 100644
index 0000000000..ae1213e6f8
--- /dev/null
+++ b/tests/qemu-iotests/tests/backing-file-invalidation.out
@@ -0,0 +1,5 @@
+.
+----------------------------------------------------------------------
+Ran 1 tests
+
+OK