From: Hanna Reitz <hreitz@redhat.com>
To: qemu-block@nongnu.org
Cc: qemu-devel@nongnu.org, Hanna Reitz <hreitz@redhat.com>,
Kevin Wolf <kwolf@redhat.com>,
Stefan Hajnoczi <stefanha@redhat.com>
Subject: [PATCH 3/3] iotests/backing-file-invalidation: Add new test
Date: Wed, 3 Aug 2022 16:44:46 +0200 [thread overview]
Message-ID: <20220803144446.20723-4-hreitz@redhat.com> (raw)
In-Reply-To: <20220803144446.20723-1-hreitz@redhat.com>
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>
---
.../tests/backing-file-invalidation | 152 ++++++++++++++++++
.../tests/backing-file-invalidation.out | 5 +
2 files changed, 157 insertions(+)
create mode 100755 tests/qemu-iotests/tests/backing-file-invalidation
create mode 100644 tests/qemu-iotests/tests/backing-file-invalidation.out
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
--
2.36.1
next prev parent reply other threads:[~2022-08-03 14:48 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-08-03 14:44 [PATCH 0/3] block: Keep auto_backing_file post-migration Hanna Reitz
2022-08-03 14:44 ` [PATCH 1/3] block/qcow2: Keep auto_backing_file if possible Hanna Reitz
2022-08-03 14:44 ` [PATCH 2/3] block/qed: " Hanna Reitz
2022-08-03 14:44 ` Hanna Reitz [this message]
2022-09-22 16:26 ` [PATCH 0/3] block: Keep auto_backing_file post-migration Kevin Wolf
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=20220803144446.20723-4-hreitz@redhat.com \
--to=hreitz@redhat.com \
--cc=kwolf@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@redhat.com \
/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).