* Thu Aug 27 2020 Danilo Cesar Lemes de Paula <ddepaula@redhat.com> - 5.1.0-4.el8
- kvm-Drop-bogus-IPv6-messages.patch [bz#1867075] - kvm-machine-types-numa-set-numa_mem_supported-on-old-mac.patch [bz#1849707] - kvm-machine_types-numa-compatibility-for-auto_enable_num.patch [bz#1849707] - kvm-migration-Add-block-bitmap-mapping-parameter.patch [bz#1790492] - kvm-iotests.py-Let-wait_migration-return-on-failure.patch [bz#1790492] - kvm-iotests-Test-node-bitmap-aliases-during-migration.patch [bz#1790492] - Resolves: bz#1790492 ('dirty-bitmaps' migration capability should allow configuring target nodenames) - Resolves: bz#1849707 (8.3 machine types for x86 - 5.1 update) - Resolves: bz#1867075 (CVE-2020-10756 virt:8.3/qemu-kvm: QEMU: slirp: networking out-of-bounds read information disclosure vulnerability [rhel-av-8])
This commit is contained in:
parent
915cb810be
commit
e5fba7f9b3
51
kvm-Drop-bogus-IPv6-messages.patch
Normal file
51
kvm-Drop-bogus-IPv6-messages.patch
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
From 6ceab004edfb7c1f0f03701bc2ae443941468fd7 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jon Maloy <jmaloy@redhat.com>
|
||||||
|
Date: Mon, 17 Aug 2020 22:06:08 -0400
|
||||||
|
Subject: [PATCH 1/6] Drop bogus IPv6 messages
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
RH-Author: Jon Maloy <jmaloy@redhat.com>
|
||||||
|
Message-id: <20200817220608.1142611-2-jmaloy@redhat.com>
|
||||||
|
Patchwork-id: 98161
|
||||||
|
O-Subject: [RHEL-AV-8.3.0 qemu-kvm PATCH 1/1] Drop bogus IPv6 messages
|
||||||
|
Bugzilla: 1867075
|
||||||
|
RH-Acked-by: Danilo de Paula <ddepaula@redhat.com>
|
||||||
|
RH-Acked-by: Philippe Mathieu-Daudé <philmd@redhat.com>
|
||||||
|
RH-Acked-by: Marc-André Lureau <marcandre.lureau@redhat.com>
|
||||||
|
|
||||||
|
From: Ralf Haferkamp <rhafer@suse.com>
|
||||||
|
|
||||||
|
Drop IPv6 message shorter than what's mentioned in the payload
|
||||||
|
length header (+ the size of the IPv6 header). They're invalid an could
|
||||||
|
lead to data leakage in icmp6_send_echoreply().
|
||||||
|
|
||||||
|
(cherry picked from libslirp commit c7ede54cbd2e2b25385325600958ba0124e31cc0)
|
||||||
|
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
|
||||||
|
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
|
||||||
|
---
|
||||||
|
slirp/src/ip6_input.c | 7 +++++++
|
||||||
|
1 file changed, 7 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/slirp/src/ip6_input.c b/slirp/src/ip6_input.c
|
||||||
|
index a83e4f8e3d..f7ef354ee4 100644
|
||||||
|
--- a/slirp/src/ip6_input.c
|
||||||
|
+++ b/slirp/src/ip6_input.c
|
||||||
|
@@ -56,6 +56,13 @@ void ip6_input(struct mbuf *m)
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Check if the message size is big enough to hold what's
|
||||||
|
+ // set in the payload length header. If not this is an invalid
|
||||||
|
+ // packet
|
||||||
|
+ if (m->m_len < ntohs(ip6->ip_pl) + sizeof(struct ip6)) {
|
||||||
|
+ goto bad;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/* check ip_ttl for a correct ICMP reply */
|
||||||
|
if (ip6->ip_hl == 0) {
|
||||||
|
icmp6_send_error(m, ICMP6_TIMXCEED, ICMP6_TIMXCEED_INTRANS);
|
||||||
|
--
|
||||||
|
2.27.0
|
||||||
|
|
655
kvm-iotests-Test-node-bitmap-aliases-during-migration.patch
Normal file
655
kvm-iotests-Test-node-bitmap-aliases-during-migration.patch
Normal file
@ -0,0 +1,655 @@
|
|||||||
|
From 2877fd4f92a86f43a113691f56738b09a0b4d500 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Max Reitz <mreitz@redhat.com>
|
||||||
|
Date: Mon, 24 Aug 2020 09:20:38 -0400
|
||||||
|
Subject: [PATCH 6/6] iotests: Test node/bitmap aliases during migration
|
||||||
|
|
||||||
|
RH-Author: Max Reitz <mreitz@redhat.com>
|
||||||
|
Message-id: <20200824092038.227913-4-mreitz@redhat.com>
|
||||||
|
Patchwork-id: 98214
|
||||||
|
O-Subject: [RHEL-AV-8.3.0 qemu-kvm PATCH 3/3] iotests: Test node/bitmap aliases during migration
|
||||||
|
Bugzilla: 1790492
|
||||||
|
RH-Acked-by: Stefano Garzarella <sgarzare@redhat.com>
|
||||||
|
RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
|
||||||
|
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
|
||||||
|
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
||||||
|
Message-Id: <20200820150725.68687-4-mreitz@redhat.com>
|
||||||
|
Reviewed-by: Eric Blake <eblake@redhat.com>
|
||||||
|
Tested-by: Eric Blake <eblake@redhat.com>
|
||||||
|
[eblake: fold in python cleanups recommended by Vladimir]
|
||||||
|
Signed-off-by: Eric Blake <eblake@redhat.com>
|
||||||
|
(cherry picked from commit cb5c6cd2dc984812f560fbe41f57a6bfc34d8708)
|
||||||
|
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
||||||
|
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
|
||||||
|
---
|
||||||
|
tests/qemu-iotests/300 | 593 +++++++++++++++++++++++++++++++++++++
|
||||||
|
tests/qemu-iotests/300.out | 5 +
|
||||||
|
tests/qemu-iotests/group | 1 +
|
||||||
|
3 files changed, 599 insertions(+)
|
||||||
|
create mode 100755 tests/qemu-iotests/300
|
||||||
|
create mode 100644 tests/qemu-iotests/300.out
|
||||||
|
|
||||||
|
diff --git a/tests/qemu-iotests/300 b/tests/qemu-iotests/300
|
||||||
|
new file mode 100755
|
||||||
|
index 0000000000..5b75121b84
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/tests/qemu-iotests/300
|
||||||
|
@@ -0,0 +1,593 @@
|
||||||
|
+#!/usr/bin/env python3
|
||||||
|
+#
|
||||||
|
+# Copyright (C) 2020 Red Hat, Inc.
|
||||||
|
+#
|
||||||
|
+# Tests for dirty bitmaps migration with node aliases
|
||||||
|
+#
|
||||||
|
+# 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 os
|
||||||
|
+import random
|
||||||
|
+import re
|
||||||
|
+from typing import Dict, List, Optional, Union
|
||||||
|
+import iotests
|
||||||
|
+import qemu
|
||||||
|
+
|
||||||
|
+BlockBitmapMapping = List[Dict[str, Union[str, List[Dict[str, str]]]]]
|
||||||
|
+
|
||||||
|
+assert iotests.sock_dir is not None
|
||||||
|
+mig_sock = os.path.join(iotests.sock_dir, 'mig_sock')
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+class TestDirtyBitmapMigration(iotests.QMPTestCase):
|
||||||
|
+ src_node_name: str = ''
|
||||||
|
+ dst_node_name: str = ''
|
||||||
|
+ src_bmap_name: str = ''
|
||||||
|
+ dst_bmap_name: str = ''
|
||||||
|
+
|
||||||
|
+ def setUp(self) -> None:
|
||||||
|
+ self.vm_a = iotests.VM(path_suffix='-a')
|
||||||
|
+ self.vm_a.add_blockdev(f'node-name={self.src_node_name},'
|
||||||
|
+ 'driver=null-co')
|
||||||
|
+ self.vm_a.launch()
|
||||||
|
+
|
||||||
|
+ self.vm_b = iotests.VM(path_suffix='-b')
|
||||||
|
+ self.vm_b.add_blockdev(f'node-name={self.dst_node_name},'
|
||||||
|
+ 'driver=null-co')
|
||||||
|
+ self.vm_b.add_incoming(f'unix:{mig_sock}')
|
||||||
|
+ self.vm_b.launch()
|
||||||
|
+
|
||||||
|
+ result = self.vm_a.qmp('block-dirty-bitmap-add',
|
||||||
|
+ node=self.src_node_name,
|
||||||
|
+ name=self.src_bmap_name)
|
||||||
|
+ self.assert_qmp(result, 'return', {})
|
||||||
|
+
|
||||||
|
+ # Dirty some random megabytes
|
||||||
|
+ for _ in range(9):
|
||||||
|
+ mb_ofs = random.randrange(1024)
|
||||||
|
+ self.vm_a.hmp_qemu_io(self.src_node_name, f'discard {mb_ofs}M 1M')
|
||||||
|
+
|
||||||
|
+ result = self.vm_a.qmp('x-debug-block-dirty-bitmap-sha256',
|
||||||
|
+ node=self.src_node_name,
|
||||||
|
+ name=self.src_bmap_name)
|
||||||
|
+ self.bitmap_hash_reference = result['return']['sha256']
|
||||||
|
+
|
||||||
|
+ caps = [{'capability': name, 'state': True}
|
||||||
|
+ for name in ('dirty-bitmaps', 'events')]
|
||||||
|
+
|
||||||
|
+ for vm in (self.vm_a, self.vm_b):
|
||||||
|
+ result = vm.qmp('migrate-set-capabilities', capabilities=caps)
|
||||||
|
+ self.assert_qmp(result, 'return', {})
|
||||||
|
+
|
||||||
|
+ def tearDown(self) -> None:
|
||||||
|
+ self.vm_a.shutdown()
|
||||||
|
+ self.vm_b.shutdown()
|
||||||
|
+ try:
|
||||||
|
+ os.remove(mig_sock)
|
||||||
|
+ except OSError:
|
||||||
|
+ pass
|
||||||
|
+
|
||||||
|
+ def check_bitmap(self, bitmap_name_valid: bool) -> None:
|
||||||
|
+ result = self.vm_b.qmp('x-debug-block-dirty-bitmap-sha256',
|
||||||
|
+ node=self.dst_node_name,
|
||||||
|
+ name=self.dst_bmap_name)
|
||||||
|
+ if bitmap_name_valid:
|
||||||
|
+ self.assert_qmp(result, 'return/sha256',
|
||||||
|
+ self.bitmap_hash_reference)
|
||||||
|
+ else:
|
||||||
|
+ self.assert_qmp(result, 'error/desc',
|
||||||
|
+ f"Dirty bitmap '{self.dst_bmap_name}' not found")
|
||||||
|
+
|
||||||
|
+ def migrate(self, bitmap_name_valid: bool = True,
|
||||||
|
+ migration_success: bool = True) -> None:
|
||||||
|
+ result = self.vm_a.qmp('migrate', uri=f'unix:{mig_sock}')
|
||||||
|
+ self.assert_qmp(result, 'return', {})
|
||||||
|
+
|
||||||
|
+ with iotests.Timeout(5, 'Timeout waiting for migration to complete'):
|
||||||
|
+ self.assertEqual(self.vm_a.wait_migration('postmigrate'),
|
||||||
|
+ migration_success)
|
||||||
|
+ self.assertEqual(self.vm_b.wait_migration('running'),
|
||||||
|
+ migration_success)
|
||||||
|
+
|
||||||
|
+ if migration_success:
|
||||||
|
+ self.check_bitmap(bitmap_name_valid)
|
||||||
|
+
|
||||||
|
+ def verify_dest_error(self, msg: Optional[str]) -> None:
|
||||||
|
+ """
|
||||||
|
+ Check whether the given error message is present in vm_b's log.
|
||||||
|
+ (vm_b is shut down to do so.)
|
||||||
|
+ If @msg is None, check that there has not been any error.
|
||||||
|
+ """
|
||||||
|
+ self.vm_b.shutdown()
|
||||||
|
+ if msg is None:
|
||||||
|
+ self.assertNotIn('qemu-system-', self.vm_b.get_log())
|
||||||
|
+ else:
|
||||||
|
+ self.assertIn(msg, self.vm_b.get_log())
|
||||||
|
+
|
||||||
|
+ @staticmethod
|
||||||
|
+ def mapping(node_name: str, node_alias: str,
|
||||||
|
+ bitmap_name: str, bitmap_alias: str) -> BlockBitmapMapping:
|
||||||
|
+ return [{
|
||||||
|
+ 'node-name': node_name,
|
||||||
|
+ 'alias': node_alias,
|
||||||
|
+ 'bitmaps': [{
|
||||||
|
+ 'name': bitmap_name,
|
||||||
|
+ 'alias': bitmap_alias
|
||||||
|
+ }]
|
||||||
|
+ }]
|
||||||
|
+
|
||||||
|
+ def set_mapping(self, vm: iotests.VM, mapping: BlockBitmapMapping,
|
||||||
|
+ error: Optional[str] = None) -> None:
|
||||||
|
+ """
|
||||||
|
+ Invoke migrate-set-parameters on @vm to set the given @mapping.
|
||||||
|
+ Check for success if @error is None, or verify the error message
|
||||||
|
+ if it is not.
|
||||||
|
+ On success, verify that "info migrate_parameters" on HMP returns
|
||||||
|
+ our mapping. (Just to check its formatting code.)
|
||||||
|
+ """
|
||||||
|
+ result = vm.qmp('migrate-set-parameters',
|
||||||
|
+ block_bitmap_mapping=mapping)
|
||||||
|
+
|
||||||
|
+ if error is None:
|
||||||
|
+ self.assert_qmp(result, 'return', {})
|
||||||
|
+
|
||||||
|
+ result = vm.qmp('human-monitor-command',
|
||||||
|
+ command_line='info migrate_parameters')
|
||||||
|
+
|
||||||
|
+ m = re.search(r'^block-bitmap-mapping:\r?(\n .*)*\n',
|
||||||
|
+ result['return'], flags=re.MULTILINE)
|
||||||
|
+ hmp_mapping = m.group(0).replace('\r', '') if m else None
|
||||||
|
+
|
||||||
|
+ self.assertEqual(hmp_mapping, self.to_hmp_mapping(mapping))
|
||||||
|
+ else:
|
||||||
|
+ self.assert_qmp(result, 'error/desc', error)
|
||||||
|
+
|
||||||
|
+ @staticmethod
|
||||||
|
+ def to_hmp_mapping(mapping: BlockBitmapMapping) -> str:
|
||||||
|
+ result = 'block-bitmap-mapping:\n'
|
||||||
|
+
|
||||||
|
+ for node in mapping:
|
||||||
|
+ result += f" '{node['node-name']}' -> '{node['alias']}'\n"
|
||||||
|
+
|
||||||
|
+ assert isinstance(node['bitmaps'], list)
|
||||||
|
+ for bitmap in node['bitmaps']:
|
||||||
|
+ result += f" '{bitmap['name']}' -> '{bitmap['alias']}'\n"
|
||||||
|
+
|
||||||
|
+ return result
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+class TestAliasMigration(TestDirtyBitmapMigration):
|
||||||
|
+ src_node_name = 'node0'
|
||||||
|
+ dst_node_name = 'node0'
|
||||||
|
+ src_bmap_name = 'bmap0'
|
||||||
|
+ dst_bmap_name = 'bmap0'
|
||||||
|
+
|
||||||
|
+ def test_migration_without_alias(self) -> None:
|
||||||
|
+ self.migrate(self.src_node_name == self.dst_node_name and
|
||||||
|
+ self.src_bmap_name == self.dst_bmap_name)
|
||||||
|
+
|
||||||
|
+ # Check for error message on the destination
|
||||||
|
+ if self.src_node_name != self.dst_node_name:
|
||||||
|
+ self.verify_dest_error(f"Cannot find "
|
||||||
|
+ f"device={self.src_node_name} nor "
|
||||||
|
+ f"node_name={self.src_node_name}")
|
||||||
|
+ else:
|
||||||
|
+ self.verify_dest_error(None)
|
||||||
|
+
|
||||||
|
+ def test_alias_on_src_migration(self) -> None:
|
||||||
|
+ mapping = self.mapping(self.src_node_name, self.dst_node_name,
|
||||||
|
+ self.src_bmap_name, self.dst_bmap_name)
|
||||||
|
+
|
||||||
|
+ self.set_mapping(self.vm_a, mapping)
|
||||||
|
+ self.migrate()
|
||||||
|
+ self.verify_dest_error(None)
|
||||||
|
+
|
||||||
|
+ def test_alias_on_dst_migration(self) -> None:
|
||||||
|
+ mapping = self.mapping(self.dst_node_name, self.src_node_name,
|
||||||
|
+ self.dst_bmap_name, self.src_bmap_name)
|
||||||
|
+
|
||||||
|
+ self.set_mapping(self.vm_b, mapping)
|
||||||
|
+ self.migrate()
|
||||||
|
+ self.verify_dest_error(None)
|
||||||
|
+
|
||||||
|
+ def test_alias_on_both_migration(self) -> None:
|
||||||
|
+ src_map = self.mapping(self.src_node_name, 'node-alias',
|
||||||
|
+ self.src_bmap_name, 'bmap-alias')
|
||||||
|
+
|
||||||
|
+ dst_map = self.mapping(self.dst_node_name, 'node-alias',
|
||||||
|
+ self.dst_bmap_name, 'bmap-alias')
|
||||||
|
+
|
||||||
|
+ self.set_mapping(self.vm_a, src_map)
|
||||||
|
+ self.set_mapping(self.vm_b, dst_map)
|
||||||
|
+ self.migrate()
|
||||||
|
+ self.verify_dest_error(None)
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+class TestNodeAliasMigration(TestAliasMigration):
|
||||||
|
+ src_node_name = 'node-src'
|
||||||
|
+ dst_node_name = 'node-dst'
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+class TestBitmapAliasMigration(TestAliasMigration):
|
||||||
|
+ src_bmap_name = 'bmap-src'
|
||||||
|
+ dst_bmap_name = 'bmap-dst'
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+class TestFullAliasMigration(TestAliasMigration):
|
||||||
|
+ src_node_name = 'node-src'
|
||||||
|
+ dst_node_name = 'node-dst'
|
||||||
|
+ src_bmap_name = 'bmap-src'
|
||||||
|
+ dst_bmap_name = 'bmap-dst'
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+class TestLongBitmapNames(TestAliasMigration):
|
||||||
|
+ # Giving long bitmap names is OK, as long as there is a short alias for
|
||||||
|
+ # migration
|
||||||
|
+ src_bmap_name = 'a' * 512
|
||||||
|
+ dst_bmap_name = 'b' * 512
|
||||||
|
+
|
||||||
|
+ # Skip all tests that do not use the intermediate alias
|
||||||
|
+ def test_migration_without_alias(self) -> None:
|
||||||
|
+ pass
|
||||||
|
+
|
||||||
|
+ def test_alias_on_src_migration(self) -> None:
|
||||||
|
+ pass
|
||||||
|
+
|
||||||
|
+ def test_alias_on_dst_migration(self) -> None:
|
||||||
|
+ pass
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+class TestBlockBitmapMappingErrors(TestDirtyBitmapMigration):
|
||||||
|
+ src_node_name = 'node0'
|
||||||
|
+ dst_node_name = 'node0'
|
||||||
|
+ src_bmap_name = 'bmap0'
|
||||||
|
+ dst_bmap_name = 'bmap0'
|
||||||
|
+
|
||||||
|
+ """
|
||||||
|
+ Note that mapping nodes or bitmaps that do not exist is not an error.
|
||||||
|
+ """
|
||||||
|
+
|
||||||
|
+ def test_non_injective_node_mapping(self) -> None:
|
||||||
|
+ mapping: BlockBitmapMapping = [
|
||||||
|
+ {
|
||||||
|
+ 'node-name': 'node0',
|
||||||
|
+ 'alias': 'common-alias',
|
||||||
|
+ 'bitmaps': [{
|
||||||
|
+ 'name': 'bmap0',
|
||||||
|
+ 'alias': 'bmap-alias0'
|
||||||
|
+ }]
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ 'node-name': 'node1',
|
||||||
|
+ 'alias': 'common-alias',
|
||||||
|
+ 'bitmaps': [{
|
||||||
|
+ 'name': 'bmap1',
|
||||||
|
+ 'alias': 'bmap-alias1'
|
||||||
|
+ }]
|
||||||
|
+ }
|
||||||
|
+ ]
|
||||||
|
+
|
||||||
|
+ self.set_mapping(self.vm_a, mapping,
|
||||||
|
+ "Invalid mapping given for block-bitmap-mapping: "
|
||||||
|
+ "The node alias 'common-alias' is used twice")
|
||||||
|
+
|
||||||
|
+ def test_non_injective_bitmap_mapping(self) -> None:
|
||||||
|
+ mapping: BlockBitmapMapping = [{
|
||||||
|
+ 'node-name': 'node0',
|
||||||
|
+ 'alias': 'node-alias0',
|
||||||
|
+ 'bitmaps': [
|
||||||
|
+ {
|
||||||
|
+ 'name': 'bmap0',
|
||||||
|
+ 'alias': 'common-alias'
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ 'name': 'bmap1',
|
||||||
|
+ 'alias': 'common-alias'
|
||||||
|
+ }
|
||||||
|
+ ]
|
||||||
|
+ }]
|
||||||
|
+
|
||||||
|
+ self.set_mapping(self.vm_a, mapping,
|
||||||
|
+ "Invalid mapping given for block-bitmap-mapping: "
|
||||||
|
+ "The bitmap alias 'node-alias0'/'common-alias' is "
|
||||||
|
+ "used twice")
|
||||||
|
+
|
||||||
|
+ def test_ambiguous_node_mapping(self) -> None:
|
||||||
|
+ mapping: BlockBitmapMapping = [
|
||||||
|
+ {
|
||||||
|
+ 'node-name': 'node0',
|
||||||
|
+ 'alias': 'node-alias0',
|
||||||
|
+ 'bitmaps': [{
|
||||||
|
+ 'name': 'bmap0',
|
||||||
|
+ 'alias': 'bmap-alias0'
|
||||||
|
+ }]
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ 'node-name': 'node0',
|
||||||
|
+ 'alias': 'node-alias1',
|
||||||
|
+ 'bitmaps': [{
|
||||||
|
+ 'name': 'bmap0',
|
||||||
|
+ 'alias': 'bmap-alias0'
|
||||||
|
+ }]
|
||||||
|
+ }
|
||||||
|
+ ]
|
||||||
|
+
|
||||||
|
+ self.set_mapping(self.vm_a, mapping,
|
||||||
|
+ "Invalid mapping given for block-bitmap-mapping: "
|
||||||
|
+ "The node name 'node0' is mapped twice")
|
||||||
|
+
|
||||||
|
+ def test_ambiguous_bitmap_mapping(self) -> None:
|
||||||
|
+ mapping: BlockBitmapMapping = [{
|
||||||
|
+ 'node-name': 'node0',
|
||||||
|
+ 'alias': 'node-alias0',
|
||||||
|
+ 'bitmaps': [
|
||||||
|
+ {
|
||||||
|
+ 'name': 'bmap0',
|
||||||
|
+ 'alias': 'bmap-alias0'
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ 'name': 'bmap0',
|
||||||
|
+ 'alias': 'bmap-alias1'
|
||||||
|
+ }
|
||||||
|
+ ]
|
||||||
|
+ }]
|
||||||
|
+
|
||||||
|
+ self.set_mapping(self.vm_a, mapping,
|
||||||
|
+ "Invalid mapping given for block-bitmap-mapping: "
|
||||||
|
+ "The bitmap 'node0'/'bmap0' is mapped twice")
|
||||||
|
+
|
||||||
|
+ def test_migratee_node_is_not_mapped_on_src(self) -> None:
|
||||||
|
+ self.set_mapping(self.vm_a, [])
|
||||||
|
+ # Should just ignore all bitmaps on unmapped nodes
|
||||||
|
+ self.migrate(False)
|
||||||
|
+ self.verify_dest_error(None)
|
||||||
|
+
|
||||||
|
+ def test_migratee_node_is_not_mapped_on_dst(self) -> None:
|
||||||
|
+ self.set_mapping(self.vm_b, [])
|
||||||
|
+ self.migrate(False)
|
||||||
|
+ self.verify_dest_error(f"Unknown node alias '{self.src_node_name}'")
|
||||||
|
+
|
||||||
|
+ def test_migratee_bitmap_is_not_mapped_on_src(self) -> None:
|
||||||
|
+ mapping: BlockBitmapMapping = [{
|
||||||
|
+ 'node-name': self.src_node_name,
|
||||||
|
+ 'alias': self.dst_node_name,
|
||||||
|
+ 'bitmaps': []
|
||||||
|
+ }]
|
||||||
|
+
|
||||||
|
+ self.set_mapping(self.vm_a, mapping)
|
||||||
|
+ # Should just ignore all unmapped bitmaps
|
||||||
|
+ self.migrate(False)
|
||||||
|
+ self.verify_dest_error(None)
|
||||||
|
+
|
||||||
|
+ def test_migratee_bitmap_is_not_mapped_on_dst(self) -> None:
|
||||||
|
+ mapping: BlockBitmapMapping = [{
|
||||||
|
+ 'node-name': self.dst_node_name,
|
||||||
|
+ 'alias': self.src_node_name,
|
||||||
|
+ 'bitmaps': []
|
||||||
|
+ }]
|
||||||
|
+
|
||||||
|
+ self.set_mapping(self.vm_b, mapping)
|
||||||
|
+ self.migrate(False)
|
||||||
|
+ self.verify_dest_error(f"Unknown bitmap alias "
|
||||||
|
+ f"'{self.src_bmap_name}' "
|
||||||
|
+ f"on node '{self.dst_node_name}' "
|
||||||
|
+ f"(alias '{self.src_node_name}')")
|
||||||
|
+
|
||||||
|
+ def test_unused_mapping_on_dst(self) -> None:
|
||||||
|
+ # Let the source not send any bitmaps
|
||||||
|
+ self.set_mapping(self.vm_a, [])
|
||||||
|
+
|
||||||
|
+ # Establish some mapping on the destination
|
||||||
|
+ self.set_mapping(self.vm_b, [])
|
||||||
|
+
|
||||||
|
+ # The fact that there is a mapping on B without any bitmaps
|
||||||
|
+ # being received should be fine, not fatal
|
||||||
|
+ self.migrate(False)
|
||||||
|
+ self.verify_dest_error(None)
|
||||||
|
+
|
||||||
|
+ def test_non_wellformed_node_alias(self) -> None:
|
||||||
|
+ alias = '123-foo'
|
||||||
|
+
|
||||||
|
+ mapping: BlockBitmapMapping = [{
|
||||||
|
+ 'node-name': self.src_node_name,
|
||||||
|
+ 'alias': alias,
|
||||||
|
+ 'bitmaps': []
|
||||||
|
+ }]
|
||||||
|
+
|
||||||
|
+ self.set_mapping(self.vm_a, mapping,
|
||||||
|
+ f"Invalid mapping given for block-bitmap-mapping: "
|
||||||
|
+ f"The node alias '{alias}' is not well-formed")
|
||||||
|
+
|
||||||
|
+ def test_node_alias_too_long(self) -> None:
|
||||||
|
+ alias = 'a' * 256
|
||||||
|
+
|
||||||
|
+ mapping: BlockBitmapMapping = [{
|
||||||
|
+ 'node-name': self.src_node_name,
|
||||||
|
+ 'alias': alias,
|
||||||
|
+ 'bitmaps': []
|
||||||
|
+ }]
|
||||||
|
+
|
||||||
|
+ self.set_mapping(self.vm_a, mapping,
|
||||||
|
+ f"Invalid mapping given for block-bitmap-mapping: "
|
||||||
|
+ f"The node alias '{alias}' is longer than 255 bytes")
|
||||||
|
+
|
||||||
|
+ def test_bitmap_alias_too_long(self) -> None:
|
||||||
|
+ alias = 'a' * 256
|
||||||
|
+
|
||||||
|
+ mapping = self.mapping(self.src_node_name, self.dst_node_name,
|
||||||
|
+ self.src_bmap_name, alias)
|
||||||
|
+
|
||||||
|
+ self.set_mapping(self.vm_a, mapping,
|
||||||
|
+ f"Invalid mapping given for block-bitmap-mapping: "
|
||||||
|
+ f"The bitmap alias '{alias}' is longer than 255 "
|
||||||
|
+ f"bytes")
|
||||||
|
+
|
||||||
|
+ def test_bitmap_name_too_long(self) -> None:
|
||||||
|
+ name = 'a' * 256
|
||||||
|
+
|
||||||
|
+ result = self.vm_a.qmp('block-dirty-bitmap-add',
|
||||||
|
+ node=self.src_node_name,
|
||||||
|
+ name=name)
|
||||||
|
+ self.assert_qmp(result, 'return', {})
|
||||||
|
+
|
||||||
|
+ self.migrate(False, False)
|
||||||
|
+
|
||||||
|
+ # Check for the error in the source's log
|
||||||
|
+ self.vm_a.shutdown()
|
||||||
|
+ self.assertIn(f"Cannot migrate bitmap '{name}' on node "
|
||||||
|
+ f"'{self.src_node_name}': Name is longer than 255 bytes",
|
||||||
|
+ self.vm_a.get_log())
|
||||||
|
+
|
||||||
|
+ # Expect abnormal shutdown of the destination VM because of
|
||||||
|
+ # the failed migration
|
||||||
|
+ try:
|
||||||
|
+ self.vm_b.shutdown()
|
||||||
|
+ except qemu.machine.AbnormalShutdown:
|
||||||
|
+ pass
|
||||||
|
+
|
||||||
|
+ def test_aliased_bitmap_name_too_long(self) -> None:
|
||||||
|
+ # Longer than the maximum for bitmap names
|
||||||
|
+ self.dst_bmap_name = 'a' * 1024
|
||||||
|
+
|
||||||
|
+ mapping = self.mapping(self.dst_node_name, self.src_node_name,
|
||||||
|
+ self.dst_bmap_name, self.src_bmap_name)
|
||||||
|
+
|
||||||
|
+ # We would have to create this bitmap during migration, and
|
||||||
|
+ # that would fail, because the name is too long. Better to
|
||||||
|
+ # catch it early.
|
||||||
|
+ self.set_mapping(self.vm_b, mapping,
|
||||||
|
+ f"Invalid mapping given for block-bitmap-mapping: "
|
||||||
|
+ f"The bitmap name '{self.dst_bmap_name}' is longer "
|
||||||
|
+ f"than 1023 bytes")
|
||||||
|
+
|
||||||
|
+ def test_node_name_too_long(self) -> None:
|
||||||
|
+ # Longer than the maximum for node names
|
||||||
|
+ self.dst_node_name = 'a' * 32
|
||||||
|
+
|
||||||
|
+ mapping = self.mapping(self.dst_node_name, self.src_node_name,
|
||||||
|
+ self.dst_bmap_name, self.src_bmap_name)
|
||||||
|
+
|
||||||
|
+ # During migration, this would appear simply as a node that
|
||||||
|
+ # cannot be found. Still better to catch impossible node
|
||||||
|
+ # names early (similar to test_non_wellformed_node_alias).
|
||||||
|
+ self.set_mapping(self.vm_b, mapping,
|
||||||
|
+ f"Invalid mapping given for block-bitmap-mapping: "
|
||||||
|
+ f"The node name '{self.dst_node_name}' is longer "
|
||||||
|
+ f"than 31 bytes")
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+class TestCrossAliasMigration(TestDirtyBitmapMigration):
|
||||||
|
+ """
|
||||||
|
+ Swap aliases, both to see that qemu does not get confused, and
|
||||||
|
+ that we can migrate multiple things at once.
|
||||||
|
+
|
||||||
|
+ So we migrate this:
|
||||||
|
+ node-a.bmap-a -> node-b.bmap-b
|
||||||
|
+ node-a.bmap-b -> node-b.bmap-a
|
||||||
|
+ node-b.bmap-a -> node-a.bmap-b
|
||||||
|
+ node-b.bmap-b -> node-a.bmap-a
|
||||||
|
+ """
|
||||||
|
+
|
||||||
|
+ src_node_name = 'node-a'
|
||||||
|
+ dst_node_name = 'node-b'
|
||||||
|
+ src_bmap_name = 'bmap-a'
|
||||||
|
+ dst_bmap_name = 'bmap-b'
|
||||||
|
+
|
||||||
|
+ def setUp(self) -> None:
|
||||||
|
+ TestDirtyBitmapMigration.setUp(self)
|
||||||
|
+
|
||||||
|
+ # Now create another block device and let both have two bitmaps each
|
||||||
|
+ result = self.vm_a.qmp('blockdev-add',
|
||||||
|
+ node_name='node-b', driver='null-co')
|
||||||
|
+ self.assert_qmp(result, 'return', {})
|
||||||
|
+
|
||||||
|
+ result = self.vm_b.qmp('blockdev-add',
|
||||||
|
+ node_name='node-a', driver='null-co')
|
||||||
|
+ self.assert_qmp(result, 'return', {})
|
||||||
|
+
|
||||||
|
+ bmaps_to_add = (('node-a', 'bmap-b'),
|
||||||
|
+ ('node-b', 'bmap-a'),
|
||||||
|
+ ('node-b', 'bmap-b'))
|
||||||
|
+
|
||||||
|
+ for (node, bmap) in bmaps_to_add:
|
||||||
|
+ result = self.vm_a.qmp('block-dirty-bitmap-add',
|
||||||
|
+ node=node, name=bmap)
|
||||||
|
+ self.assert_qmp(result, 'return', {})
|
||||||
|
+
|
||||||
|
+ @staticmethod
|
||||||
|
+ def cross_mapping() -> BlockBitmapMapping:
|
||||||
|
+ return [
|
||||||
|
+ {
|
||||||
|
+ 'node-name': 'node-a',
|
||||||
|
+ 'alias': 'node-b',
|
||||||
|
+ 'bitmaps': [
|
||||||
|
+ {
|
||||||
|
+ 'name': 'bmap-a',
|
||||||
|
+ 'alias': 'bmap-b'
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ 'name': 'bmap-b',
|
||||||
|
+ 'alias': 'bmap-a'
|
||||||
|
+ }
|
||||||
|
+ ]
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ 'node-name': 'node-b',
|
||||||
|
+ 'alias': 'node-a',
|
||||||
|
+ 'bitmaps': [
|
||||||
|
+ {
|
||||||
|
+ 'name': 'bmap-b',
|
||||||
|
+ 'alias': 'bmap-a'
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ 'name': 'bmap-a',
|
||||||
|
+ 'alias': 'bmap-b'
|
||||||
|
+ }
|
||||||
|
+ ]
|
||||||
|
+ }
|
||||||
|
+ ]
|
||||||
|
+
|
||||||
|
+ def verify_dest_has_all_bitmaps(self) -> None:
|
||||||
|
+ bitmaps = self.vm_b.query_bitmaps()
|
||||||
|
+
|
||||||
|
+ # Extract and sort bitmap names
|
||||||
|
+ for node in bitmaps:
|
||||||
|
+ bitmaps[node] = sorted((bmap['name'] for bmap in bitmaps[node]))
|
||||||
|
+
|
||||||
|
+ self.assertEqual(bitmaps,
|
||||||
|
+ {'node-a': ['bmap-a', 'bmap-b'],
|
||||||
|
+ 'node-b': ['bmap-a', 'bmap-b']})
|
||||||
|
+
|
||||||
|
+ def test_alias_on_src(self) -> None:
|
||||||
|
+ self.set_mapping(self.vm_a, self.cross_mapping())
|
||||||
|
+
|
||||||
|
+ # Checks that node-a.bmap-a was migrated to node-b.bmap-b, and
|
||||||
|
+ # that is enough
|
||||||
|
+ self.migrate()
|
||||||
|
+ self.verify_dest_has_all_bitmaps()
|
||||||
|
+ self.verify_dest_error(None)
|
||||||
|
+
|
||||||
|
+ def test_alias_on_dst(self) -> None:
|
||||||
|
+ self.set_mapping(self.vm_b, self.cross_mapping())
|
||||||
|
+
|
||||||
|
+ # Checks that node-a.bmap-a was migrated to node-b.bmap-b, and
|
||||||
|
+ # that is enough
|
||||||
|
+ self.migrate()
|
||||||
|
+ self.verify_dest_has_all_bitmaps()
|
||||||
|
+ self.verify_dest_error(None)
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+if __name__ == '__main__':
|
||||||
|
+ iotests.main(supported_protocols=['file'])
|
||||||
|
diff --git a/tests/qemu-iotests/300.out b/tests/qemu-iotests/300.out
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000..cafb8161f7
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/tests/qemu-iotests/300.out
|
||||||
|
@@ -0,0 +1,5 @@
|
||||||
|
+.....................................
|
||||||
|
+----------------------------------------------------------------------
|
||||||
|
+Ran 37 tests
|
||||||
|
+
|
||||||
|
+OK
|
||||||
|
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
|
||||||
|
index 025ed5238d..b0b55e241c 100644
|
||||||
|
--- a/tests/qemu-iotests/group
|
||||||
|
+++ b/tests/qemu-iotests/group
|
||||||
|
@@ -307,5 +307,6 @@
|
||||||
|
296 rw
|
||||||
|
297 meta
|
||||||
|
299 auto quick
|
||||||
|
+300 migration
|
||||||
|
301 backing quick
|
||||||
|
302 quick
|
||||||
|
--
|
||||||
|
2.27.0
|
||||||
|
|
66
kvm-iotests.py-Let-wait_migration-return-on-failure.patch
Normal file
66
kvm-iotests.py-Let-wait_migration-return-on-failure.patch
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
From 2a597bba9b1e07adb6531628962682a0e53d29b1 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Max Reitz <mreitz@redhat.com>
|
||||||
|
Date: Mon, 24 Aug 2020 09:20:37 -0400
|
||||||
|
Subject: [PATCH 5/6] iotests.py: Let wait_migration() return on failure
|
||||||
|
|
||||||
|
RH-Author: Max Reitz <mreitz@redhat.com>
|
||||||
|
Message-id: <20200824092038.227913-3-mreitz@redhat.com>
|
||||||
|
Patchwork-id: 98213
|
||||||
|
O-Subject: [RHEL-AV-8.3.0 qemu-kvm PATCH 2/3] iotests.py: Let wait_migration() return on failure
|
||||||
|
Bugzilla: 1790492
|
||||||
|
RH-Acked-by: Stefano Garzarella <sgarzare@redhat.com>
|
||||||
|
RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
|
||||||
|
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
|
||||||
|
Let wait_migration() return on failure (with the return value indicating
|
||||||
|
whether the migration was completed or has failed), so we can use it for
|
||||||
|
migrations that are expected to fail, too.
|
||||||
|
|
||||||
|
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
||||||
|
Reviewed-by: Eric Blake <eblake@redhat.com>
|
||||||
|
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
||||||
|
Message-Id: <20200820150725.68687-3-mreitz@redhat.com>
|
||||||
|
Signed-off-by: Eric Blake <eblake@redhat.com>
|
||||||
|
(cherry picked from commit 4bf63c80357031be4eb8fff8a751f40e73ef1c10)
|
||||||
|
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
||||||
|
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
|
||||||
|
---
|
||||||
|
tests/qemu-iotests/iotests.py | 18 ++++++++++++------
|
||||||
|
1 file changed, 12 insertions(+), 6 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
|
||||||
|
index 717b5b652c..e197c73ca5 100644
|
||||||
|
--- a/tests/qemu-iotests/iotests.py
|
||||||
|
+++ b/tests/qemu-iotests/iotests.py
|
||||||
|
@@ -729,16 +729,22 @@ class VM(qtest.QEMUQtestMachine):
|
||||||
|
}
|
||||||
|
]))
|
||||||
|
|
||||||
|
- def wait_migration(self, expect_runstate):
|
||||||
|
+ def wait_migration(self, expect_runstate: Optional[str]) -> bool:
|
||||||
|
while True:
|
||||||
|
event = self.event_wait('MIGRATION')
|
||||||
|
log(event, filters=[filter_qmp_event])
|
||||||
|
- if event['data']['status'] == 'completed':
|
||||||
|
+ if event['data']['status'] in ('completed', 'failed'):
|
||||||
|
break
|
||||||
|
- # The event may occur in finish-migrate, so wait for the expected
|
||||||
|
- # post-migration runstate
|
||||||
|
- while self.qmp('query-status')['return']['status'] != expect_runstate:
|
||||||
|
- pass
|
||||||
|
+
|
||||||
|
+ if event['data']['status'] == 'completed':
|
||||||
|
+ # The event may occur in finish-migrate, so wait for the expected
|
||||||
|
+ # post-migration runstate
|
||||||
|
+ runstate = None
|
||||||
|
+ while runstate != expect_runstate:
|
||||||
|
+ runstate = self.qmp('query-status')['return']['status']
|
||||||
|
+ return True
|
||||||
|
+ else:
|
||||||
|
+ return False
|
||||||
|
|
||||||
|
def node_info(self, node_name):
|
||||||
|
nodes = self.qmp('query-named-block-nodes')
|
||||||
|
--
|
||||||
|
2.27.0
|
||||||
|
|
@ -0,0 +1,77 @@
|
|||||||
|
From 6d7ba662e980fcc6f3056173043136063e6d68db Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
|
||||||
|
Date: Thu, 20 Aug 2020 15:14:18 -0400
|
||||||
|
Subject: [PATCH 2/6] machine types/numa: set numa_mem_supported on old machine
|
||||||
|
types
|
||||||
|
|
||||||
|
RH-Author: Dr. David Alan Gilbert <dgilbert@redhat.com>
|
||||||
|
Message-id: <20200820151419.14723-2-dgilbert@redhat.com>
|
||||||
|
Patchwork-id: 98197
|
||||||
|
O-Subject: [RHEL-AV 8.3.0 qemu-kvm PATCH 1/2] machine types/numa: set numa_mem_supported on old machine types
|
||||||
|
Bugzilla: 1849707
|
||||||
|
RH-Acked-by: Eduardo Habkost <ehabkost@redhat.com>
|
||||||
|
RH-Acked-by: David Hildenbrand <david@redhat.com>
|
||||||
|
RH-Acked-by: Igor Mammedov <imammedo@redhat.com>
|
||||||
|
|
||||||
|
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
|
||||||
|
|
||||||
|
Reenable the -numa mem= syntax for old machine types, this is making
|
||||||
|
the downstream old machines behave in the same way as the upstream old
|
||||||
|
machines changed in upstream 32a354dc6c07d7.
|
||||||
|
|
||||||
|
Power already seems to have the change.
|
||||||
|
|
||||||
|
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
|
||||||
|
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
|
||||||
|
---
|
||||||
|
hw/arm/virt.c | 2 +-
|
||||||
|
hw/i386/pc_piix.c | 1 +
|
||||||
|
hw/i386/pc_q35.c | 1 +
|
||||||
|
3 files changed, 3 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||||
|
index f087483a04..26a7920081 100644
|
||||||
|
--- a/hw/arm/virt.c
|
||||||
|
+++ b/hw/arm/virt.c
|
||||||
|
@@ -2755,7 +2755,6 @@ static void rhel_machine_class_init(ObjectClass *oc, void *data)
|
||||||
|
hc->plug = virt_machine_device_plug_cb;
|
||||||
|
hc->unplug_request = virt_machine_device_unplug_request_cb;
|
||||||
|
hc->unplug = virt_machine_device_unplug_cb;
|
||||||
|
- mc->numa_mem_supported = true;
|
||||||
|
mc->nvdimm_supported = true;
|
||||||
|
mc->auto_enable_numa_with_memhp = true;
|
||||||
|
mc->default_ram_id = "mach-virt.ram";
|
||||||
|
@@ -2860,5 +2859,6 @@ static void rhel820_virt_options(MachineClass *mc)
|
||||||
|
rhel830_virt_options(mc);
|
||||||
|
compat_props_add(mc->compat_props, hw_compat_rhel_8_2,
|
||||||
|
hw_compat_rhel_8_2_len);
|
||||||
|
+ mc->numa_mem_supported = true;
|
||||||
|
}
|
||||||
|
DEFINE_RHEL_MACHINE(8, 2, 0)
|
||||||
|
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
|
||||||
|
index 4af4497a0c..bda2d9ffc8 100644
|
||||||
|
--- a/hw/i386/pc_piix.c
|
||||||
|
+++ b/hw/i386/pc_piix.c
|
||||||
|
@@ -1009,6 +1009,7 @@ static void pc_machine_rhel7_options(MachineClass *m)
|
||||||
|
pcmc->default_nic_model = "e1000";
|
||||||
|
m->default_display = "std";
|
||||||
|
m->no_parallel = 1;
|
||||||
|
+ m->numa_mem_supported = true;
|
||||||
|
machine_class_allow_dynamic_sysbus_dev(m, TYPE_RAMFB_DEVICE);
|
||||||
|
compat_props_add(m->compat_props, pc_rhel_compat, pc_rhel_compat_len);
|
||||||
|
m->alias = "pc";
|
||||||
|
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
|
||||||
|
index c709460ab7..d1e3a9b575 100644
|
||||||
|
--- a/hw/i386/pc_q35.c
|
||||||
|
+++ b/hw/i386/pc_q35.c
|
||||||
|
@@ -617,6 +617,7 @@ static void pc_q35_machine_rhel820_options(MachineClass *m)
|
||||||
|
pc_q35_machine_rhel_options(m);
|
||||||
|
m->desc = "RHEL-8.2.0 PC (Q35 + ICH9, 2009)";
|
||||||
|
m->alias = NULL;
|
||||||
|
+ m->numa_mem_supported = true;
|
||||||
|
pcmc->smbios_stream_product = "RHEL-AV";
|
||||||
|
pcmc->smbios_stream_version = "8.2.0";
|
||||||
|
compat_props_add(m->compat_props, hw_compat_rhel_8_2,
|
||||||
|
--
|
||||||
|
2.27.0
|
||||||
|
|
@ -0,0 +1,81 @@
|
|||||||
|
From 25c5644164e3286dc722d59c8d7876b1c49c1385 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
|
||||||
|
Date: Thu, 20 Aug 2020 15:14:19 -0400
|
||||||
|
Subject: [PATCH 3/6] machine_types/numa: compatibility for
|
||||||
|
auto_enable_numa_with_memdev
|
||||||
|
|
||||||
|
RH-Author: Dr. David Alan Gilbert <dgilbert@redhat.com>
|
||||||
|
Message-id: <20200820151419.14723-3-dgilbert@redhat.com>
|
||||||
|
Patchwork-id: 98196
|
||||||
|
O-Subject: [RHEL-AV 8.3.0 qemu-kvm PATCH 2/2] machine_types/numa: compatibility for auto_enable_numa_with_memdev
|
||||||
|
Bugzilla: 1849707
|
||||||
|
RH-Acked-by: Eduardo Habkost <ehabkost@redhat.com>
|
||||||
|
RH-Acked-by: Igor Mammedov <imammedo@redhat.com>
|
||||||
|
RH-Acked-by: David Hildenbrand <david@redhat.com>
|
||||||
|
|
||||||
|
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
|
||||||
|
|
||||||
|
The auto_enable_numa_with_memdev flag automatically creates NUMA a
|
||||||
|
NUMA node in a case like:
|
||||||
|
|
||||||
|
-m 8G,maxmem=16G
|
||||||
|
|
||||||
|
but we need it to keep old machine types the same.
|
||||||
|
This is (mostly) done for upstream machine types in 195784a0cfad.
|
||||||
|
|
||||||
|
Power seems to have auto_enable_numa permenantly on anyway.
|
||||||
|
|
||||||
|
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
|
||||||
|
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
|
||||||
|
---
|
||||||
|
hw/arm/virt.c | 2 ++
|
||||||
|
hw/i386/pc_piix.c | 1 +
|
||||||
|
hw/i386/pc_q35.c | 1 +
|
||||||
|
3 files changed, 4 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||||
|
index 26a7920081..26102f22ff 100644
|
||||||
|
--- a/hw/arm/virt.c
|
||||||
|
+++ b/hw/arm/virt.c
|
||||||
|
@@ -2757,6 +2757,7 @@ static void rhel_machine_class_init(ObjectClass *oc, void *data)
|
||||||
|
hc->unplug = virt_machine_device_unplug_cb;
|
||||||
|
mc->nvdimm_supported = true;
|
||||||
|
mc->auto_enable_numa_with_memhp = true;
|
||||||
|
+ mc->auto_enable_numa_with_memdev = true;
|
||||||
|
mc->default_ram_id = "mach-virt.ram";
|
||||||
|
|
||||||
|
object_class_property_add(oc, "acpi", "OnOffAuto",
|
||||||
|
@@ -2860,5 +2861,6 @@ static void rhel820_virt_options(MachineClass *mc)
|
||||||
|
compat_props_add(mc->compat_props, hw_compat_rhel_8_2,
|
||||||
|
hw_compat_rhel_8_2_len);
|
||||||
|
mc->numa_mem_supported = true;
|
||||||
|
+ mc->auto_enable_numa_with_memdev = false;
|
||||||
|
}
|
||||||
|
DEFINE_RHEL_MACHINE(8, 2, 0)
|
||||||
|
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
|
||||||
|
index bda2d9ffc8..2415c5edd6 100644
|
||||||
|
--- a/hw/i386/pc_piix.c
|
||||||
|
+++ b/hw/i386/pc_piix.c
|
||||||
|
@@ -1010,6 +1010,7 @@ static void pc_machine_rhel7_options(MachineClass *m)
|
||||||
|
m->default_display = "std";
|
||||||
|
m->no_parallel = 1;
|
||||||
|
m->numa_mem_supported = true;
|
||||||
|
+ m->auto_enable_numa_with_memdev = false;
|
||||||
|
machine_class_allow_dynamic_sysbus_dev(m, TYPE_RAMFB_DEVICE);
|
||||||
|
compat_props_add(m->compat_props, pc_rhel_compat, pc_rhel_compat_len);
|
||||||
|
m->alias = "pc";
|
||||||
|
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
|
||||||
|
index d1e3a9b575..87a0572ec1 100644
|
||||||
|
--- a/hw/i386/pc_q35.c
|
||||||
|
+++ b/hw/i386/pc_q35.c
|
||||||
|
@@ -618,6 +618,7 @@ static void pc_q35_machine_rhel820_options(MachineClass *m)
|
||||||
|
m->desc = "RHEL-8.2.0 PC (Q35 + ICH9, 2009)";
|
||||||
|
m->alias = NULL;
|
||||||
|
m->numa_mem_supported = true;
|
||||||
|
+ m->auto_enable_numa_with_memdev = false;
|
||||||
|
pcmc->smbios_stream_product = "RHEL-AV";
|
||||||
|
pcmc->smbios_stream_version = "8.2.0";
|
||||||
|
compat_props_add(m->compat_props, hw_compat_rhel_8_2,
|
||||||
|
--
|
||||||
|
2.27.0
|
||||||
|
|
947
kvm-migration-Add-block-bitmap-mapping-parameter.patch
Normal file
947
kvm-migration-Add-block-bitmap-mapping-parameter.patch
Normal file
@ -0,0 +1,947 @@
|
|||||||
|
From 8ac15801169cb8744b57b939a3c751ea9d381d98 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Max Reitz <mreitz@redhat.com>
|
||||||
|
Date: Mon, 24 Aug 2020 09:20:36 -0400
|
||||||
|
Subject: [PATCH 4/6] migration: Add block-bitmap-mapping parameter
|
||||||
|
|
||||||
|
RH-Author: Max Reitz <mreitz@redhat.com>
|
||||||
|
Message-id: <20200824092038.227913-2-mreitz@redhat.com>
|
||||||
|
Patchwork-id: 98211
|
||||||
|
O-Subject: [RHEL-AV-8.3.0 qemu-kvm PATCH 1/3] migration: Add block-bitmap-mapping parameter
|
||||||
|
Bugzilla: 1790492
|
||||||
|
RH-Acked-by: Stefano Garzarella <sgarzare@redhat.com>
|
||||||
|
RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
|
||||||
|
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
|
||||||
|
This migration parameter allows mapping block node names and bitmap
|
||||||
|
names to aliases for the purpose of block dirty bitmap migration.
|
||||||
|
|
||||||
|
This way, management tools can use different node and bitmap names on
|
||||||
|
the source and destination and pass the mapping of how bitmaps are to be
|
||||||
|
transferred to qemu (on the source, the destination, or even both with
|
||||||
|
arbitrary aliases in the migration stream).
|
||||||
|
|
||||||
|
While touching this code, fix a bug where bitmap names longer than 255
|
||||||
|
bytes would fail an assertion in qemu_put_counted_string().
|
||||||
|
|
||||||
|
Suggested-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
||||||
|
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
||||||
|
Message-Id: <20200820150725.68687-2-mreitz@redhat.com>
|
||||||
|
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
||||||
|
Signed-off-by: Eric Blake <eblake@redhat.com>
|
||||||
|
(cherry picked from commit 31e4c354b38cd42a051ad030eb7779d5e7ee32fe)
|
||||||
|
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
||||||
|
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
|
||||||
|
---
|
||||||
|
migration/block-dirty-bitmap.c | 412 ++++++++++++++++++++++++++++-----
|
||||||
|
migration/migration.c | 30 +++
|
||||||
|
migration/migration.h | 3 +
|
||||||
|
monitor/hmp-cmds.c | 30 +++
|
||||||
|
qapi/migration.json | 104 ++++++++-
|
||||||
|
5 files changed, 522 insertions(+), 57 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/migration/block-dirty-bitmap.c b/migration/block-dirty-bitmap.c
|
||||||
|
index 784330ebe1..549e14daba 100644
|
||||||
|
--- a/migration/block-dirty-bitmap.c
|
||||||
|
+++ b/migration/block-dirty-bitmap.c
|
||||||
|
@@ -29,10 +29,10 @@
|
||||||
|
*
|
||||||
|
* # Header (shared for different chunk types)
|
||||||
|
* 1, 2 or 4 bytes: flags (see qemu_{put,put}_flags)
|
||||||
|
- * [ 1 byte: node name size ] \ flags & DEVICE_NAME
|
||||||
|
- * [ n bytes: node name ] /
|
||||||
|
- * [ 1 byte: bitmap name size ] \ flags & BITMAP_NAME
|
||||||
|
- * [ n bytes: bitmap name ] /
|
||||||
|
+ * [ 1 byte: node alias size ] \ flags & DEVICE_NAME
|
||||||
|
+ * [ n bytes: node alias ] /
|
||||||
|
+ * [ 1 byte: bitmap alias size ] \ flags & BITMAP_NAME
|
||||||
|
+ * [ n bytes: bitmap alias ] /
|
||||||
|
*
|
||||||
|
* # Start of bitmap migration (flags & START)
|
||||||
|
* header
|
||||||
|
@@ -72,7 +72,9 @@
|
||||||
|
#include "migration/register.h"
|
||||||
|
#include "qemu/hbitmap.h"
|
||||||
|
#include "qemu/cutils.h"
|
||||||
|
+#include "qemu/id.h"
|
||||||
|
#include "qapi/error.h"
|
||||||
|
+#include "qapi/qapi-commands-migration.h"
|
||||||
|
#include "trace.h"
|
||||||
|
|
||||||
|
#define CHUNK_SIZE (1 << 10)
|
||||||
|
@@ -104,7 +106,8 @@
|
||||||
|
typedef struct SaveBitmapState {
|
||||||
|
/* Written during setup phase. */
|
||||||
|
BlockDriverState *bs;
|
||||||
|
- const char *node_name;
|
||||||
|
+ char *node_alias;
|
||||||
|
+ char *bitmap_alias;
|
||||||
|
BdrvDirtyBitmap *bitmap;
|
||||||
|
uint64_t total_sectors;
|
||||||
|
uint64_t sectors_per_chunk;
|
||||||
|
@@ -138,8 +141,9 @@ typedef struct LoadBitmapState {
|
||||||
|
/* State of the dirty bitmap migration (DBM) during load process */
|
||||||
|
typedef struct DBMLoadState {
|
||||||
|
uint32_t flags;
|
||||||
|
- char node_name[256];
|
||||||
|
- char bitmap_name[256];
|
||||||
|
+ char node_alias[256];
|
||||||
|
+ char bitmap_alias[256];
|
||||||
|
+ char bitmap_name[BDRV_BITMAP_MAX_NAME_SIZE + 1];
|
||||||
|
BlockDriverState *bs;
|
||||||
|
BdrvDirtyBitmap *bitmap;
|
||||||
|
|
||||||
|
@@ -165,6 +169,188 @@ typedef struct DBMState {
|
||||||
|
|
||||||
|
static DBMState dbm_state;
|
||||||
|
|
||||||
|
+/* For hash tables that map node/bitmap names to aliases */
|
||||||
|
+typedef struct AliasMapInnerNode {
|
||||||
|
+ char *string;
|
||||||
|
+ GHashTable *subtree;
|
||||||
|
+} AliasMapInnerNode;
|
||||||
|
+
|
||||||
|
+static void free_alias_map_inner_node(void *amin_ptr)
|
||||||
|
+{
|
||||||
|
+ AliasMapInnerNode *amin = amin_ptr;
|
||||||
|
+
|
||||||
|
+ g_free(amin->string);
|
||||||
|
+ g_hash_table_unref(amin->subtree);
|
||||||
|
+ g_free(amin);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * Construct an alias map based on the given QMP structure.
|
||||||
|
+ *
|
||||||
|
+ * (Note that we cannot store such maps in the MigrationParameters
|
||||||
|
+ * object, because that struct is defined by the QAPI schema, which
|
||||||
|
+ * makes it basically impossible to have dicts with arbitrary keys.
|
||||||
|
+ * Therefore, we instead have to construct these maps when migration
|
||||||
|
+ * starts.)
|
||||||
|
+ *
|
||||||
|
+ * @bbm is the block_bitmap_mapping from the migration parameters.
|
||||||
|
+ *
|
||||||
|
+ * If @name_to_alias is true, the returned hash table will map node
|
||||||
|
+ * and bitmap names to their respective aliases (for outgoing
|
||||||
|
+ * migration).
|
||||||
|
+ *
|
||||||
|
+ * If @name_to_alias is false, the returned hash table will map node
|
||||||
|
+ * and bitmap aliases to their respective names (for incoming
|
||||||
|
+ * migration).
|
||||||
|
+ *
|
||||||
|
+ * The hash table maps node names/aliases to AliasMapInnerNode
|
||||||
|
+ * objects, whose .string is the respective node alias/name, and whose
|
||||||
|
+ * .subtree table maps bitmap names/aliases to the respective bitmap
|
||||||
|
+ * alias/name.
|
||||||
|
+ */
|
||||||
|
+static GHashTable *construct_alias_map(const BitmapMigrationNodeAliasList *bbm,
|
||||||
|
+ bool name_to_alias,
|
||||||
|
+ Error **errp)
|
||||||
|
+{
|
||||||
|
+ GHashTable *alias_map;
|
||||||
|
+ size_t max_node_name_len = sizeof_field(BlockDriverState, node_name) - 1;
|
||||||
|
+
|
||||||
|
+ alias_map = g_hash_table_new_full(g_str_hash, g_str_equal,
|
||||||
|
+ g_free, free_alias_map_inner_node);
|
||||||
|
+
|
||||||
|
+ for (; bbm; bbm = bbm->next) {
|
||||||
|
+ const BitmapMigrationNodeAlias *bmna = bbm->value;
|
||||||
|
+ const BitmapMigrationBitmapAliasList *bmbal;
|
||||||
|
+ AliasMapInnerNode *amin;
|
||||||
|
+ GHashTable *bitmaps_map;
|
||||||
|
+ const char *node_map_from, *node_map_to;
|
||||||
|
+
|
||||||
|
+ if (!id_wellformed(bmna->alias)) {
|
||||||
|
+ error_setg(errp, "The node alias '%s' is not well-formed",
|
||||||
|
+ bmna->alias);
|
||||||
|
+ goto fail;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (strlen(bmna->alias) > UINT8_MAX) {
|
||||||
|
+ error_setg(errp, "The node alias '%s' is longer than %u bytes",
|
||||||
|
+ bmna->alias, UINT8_MAX);
|
||||||
|
+ goto fail;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (strlen(bmna->node_name) > max_node_name_len) {
|
||||||
|
+ error_setg(errp, "The node name '%s' is longer than %zu bytes",
|
||||||
|
+ bmna->node_name, max_node_name_len);
|
||||||
|
+ goto fail;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (name_to_alias) {
|
||||||
|
+ if (g_hash_table_contains(alias_map, bmna->node_name)) {
|
||||||
|
+ error_setg(errp, "The node name '%s' is mapped twice",
|
||||||
|
+ bmna->node_name);
|
||||||
|
+ goto fail;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ node_map_from = bmna->node_name;
|
||||||
|
+ node_map_to = bmna->alias;
|
||||||
|
+ } else {
|
||||||
|
+ if (g_hash_table_contains(alias_map, bmna->alias)) {
|
||||||
|
+ error_setg(errp, "The node alias '%s' is used twice",
|
||||||
|
+ bmna->alias);
|
||||||
|
+ goto fail;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ node_map_from = bmna->alias;
|
||||||
|
+ node_map_to = bmna->node_name;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ bitmaps_map = g_hash_table_new_full(g_str_hash, g_str_equal,
|
||||||
|
+ g_free, g_free);
|
||||||
|
+
|
||||||
|
+ amin = g_new(AliasMapInnerNode, 1);
|
||||||
|
+ *amin = (AliasMapInnerNode){
|
||||||
|
+ .string = g_strdup(node_map_to),
|
||||||
|
+ .subtree = bitmaps_map,
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ g_hash_table_insert(alias_map, g_strdup(node_map_from), amin);
|
||||||
|
+
|
||||||
|
+ for (bmbal = bmna->bitmaps; bmbal; bmbal = bmbal->next) {
|
||||||
|
+ const BitmapMigrationBitmapAlias *bmba = bmbal->value;
|
||||||
|
+ const char *bmap_map_from, *bmap_map_to;
|
||||||
|
+
|
||||||
|
+ if (strlen(bmba->alias) > UINT8_MAX) {
|
||||||
|
+ error_setg(errp,
|
||||||
|
+ "The bitmap alias '%s' is longer than %u bytes",
|
||||||
|
+ bmba->alias, UINT8_MAX);
|
||||||
|
+ goto fail;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (strlen(bmba->name) > BDRV_BITMAP_MAX_NAME_SIZE) {
|
||||||
|
+ error_setg(errp, "The bitmap name '%s' is longer than %d bytes",
|
||||||
|
+ bmba->name, BDRV_BITMAP_MAX_NAME_SIZE);
|
||||||
|
+ goto fail;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (name_to_alias) {
|
||||||
|
+ bmap_map_from = bmba->name;
|
||||||
|
+ bmap_map_to = bmba->alias;
|
||||||
|
+
|
||||||
|
+ if (g_hash_table_contains(bitmaps_map, bmba->name)) {
|
||||||
|
+ error_setg(errp, "The bitmap '%s'/'%s' is mapped twice",
|
||||||
|
+ bmna->node_name, bmba->name);
|
||||||
|
+ goto fail;
|
||||||
|
+ }
|
||||||
|
+ } else {
|
||||||
|
+ bmap_map_from = bmba->alias;
|
||||||
|
+ bmap_map_to = bmba->name;
|
||||||
|
+
|
||||||
|
+ if (g_hash_table_contains(bitmaps_map, bmba->alias)) {
|
||||||
|
+ error_setg(errp, "The bitmap alias '%s'/'%s' is used twice",
|
||||||
|
+ bmna->alias, bmba->alias);
|
||||||
|
+ goto fail;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ g_hash_table_insert(bitmaps_map,
|
||||||
|
+ g_strdup(bmap_map_from), g_strdup(bmap_map_to));
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return alias_map;
|
||||||
|
+
|
||||||
|
+fail:
|
||||||
|
+ g_hash_table_destroy(alias_map);
|
||||||
|
+ return NULL;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * Run construct_alias_map() in both directions to check whether @bbm
|
||||||
|
+ * is valid.
|
||||||
|
+ * (This function is to be used by migration/migration.c to validate
|
||||||
|
+ * the user-specified block-bitmap-mapping migration parameter.)
|
||||||
|
+ *
|
||||||
|
+ * Returns true if and only if the mapping is valid.
|
||||||
|
+ */
|
||||||
|
+bool check_dirty_bitmap_mig_alias_map(const BitmapMigrationNodeAliasList *bbm,
|
||||||
|
+ Error **errp)
|
||||||
|
+{
|
||||||
|
+ GHashTable *alias_map;
|
||||||
|
+
|
||||||
|
+ alias_map = construct_alias_map(bbm, true, errp);
|
||||||
|
+ if (!alias_map) {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+ g_hash_table_destroy(alias_map);
|
||||||
|
+
|
||||||
|
+ alias_map = construct_alias_map(bbm, false, errp);
|
||||||
|
+ if (!alias_map) {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+ g_hash_table_destroy(alias_map);
|
||||||
|
+
|
||||||
|
+ return true;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static uint32_t qemu_get_bitmap_flags(QEMUFile *f)
|
||||||
|
{
|
||||||
|
uint8_t flags = qemu_get_byte(f);
|
||||||
|
@@ -207,11 +393,11 @@ static void send_bitmap_header(QEMUFile *f, DBMSaveState *s,
|
||||||
|
qemu_put_bitmap_flags(f, flags);
|
||||||
|
|
||||||
|
if (flags & DIRTY_BITMAP_MIG_FLAG_DEVICE_NAME) {
|
||||||
|
- qemu_put_counted_string(f, dbms->node_name);
|
||||||
|
+ qemu_put_counted_string(f, dbms->node_alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & DIRTY_BITMAP_MIG_FLAG_BITMAP_NAME) {
|
||||||
|
- qemu_put_counted_string(f, bdrv_dirty_bitmap_name(bitmap));
|
||||||
|
+ qemu_put_counted_string(f, dbms->bitmap_alias);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -282,18 +468,25 @@ static void dirty_bitmap_do_save_cleanup(DBMSaveState *s)
|
||||||
|
QSIMPLEQ_REMOVE_HEAD(&s->dbms_list, entry);
|
||||||
|
bdrv_dirty_bitmap_set_busy(dbms->bitmap, false);
|
||||||
|
bdrv_unref(dbms->bs);
|
||||||
|
+ g_free(dbms->node_alias);
|
||||||
|
+ g_free(dbms->bitmap_alias);
|
||||||
|
g_free(dbms);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Called with iothread lock taken. */
|
||||||
|
static int add_bitmaps_to_list(DBMSaveState *s, BlockDriverState *bs,
|
||||||
|
- const char *bs_name)
|
||||||
|
+ const char *bs_name, GHashTable *alias_map)
|
||||||
|
{
|
||||||
|
BdrvDirtyBitmap *bitmap;
|
||||||
|
SaveBitmapState *dbms;
|
||||||
|
+ GHashTable *bitmap_aliases;
|
||||||
|
+ const char *node_alias, *bitmap_name, *bitmap_alias;
|
||||||
|
Error *local_err = NULL;
|
||||||
|
|
||||||
|
+ /* When an alias map is given, @bs_name must be @bs's node name */
|
||||||
|
+ assert(!alias_map || !strcmp(bs_name, bdrv_get_node_name(bs)));
|
||||||
|
+
|
||||||
|
FOR_EACH_DIRTY_BITMAP(bs, bitmap) {
|
||||||
|
if (bdrv_dirty_bitmap_name(bitmap)) {
|
||||||
|
break;
|
||||||
|
@@ -303,21 +496,39 @@ static int add_bitmaps_to_list(DBMSaveState *s, BlockDriverState *bs,
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ bitmap_name = bdrv_dirty_bitmap_name(bitmap);
|
||||||
|
+
|
||||||
|
if (!bs_name || strcmp(bs_name, "") == 0) {
|
||||||
|
error_report("Bitmap '%s' in unnamed node can't be migrated",
|
||||||
|
- bdrv_dirty_bitmap_name(bitmap));
|
||||||
|
+ bitmap_name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (bs_name[0] == '#') {
|
||||||
|
+ if (alias_map) {
|
||||||
|
+ const AliasMapInnerNode *amin = g_hash_table_lookup(alias_map, bs_name);
|
||||||
|
+
|
||||||
|
+ if (!amin) {
|
||||||
|
+ /* Skip bitmaps on nodes with no alias */
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ node_alias = amin->string;
|
||||||
|
+ bitmap_aliases = amin->subtree;
|
||||||
|
+ } else {
|
||||||
|
+ node_alias = bs_name;
|
||||||
|
+ bitmap_aliases = NULL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (node_alias[0] == '#') {
|
||||||
|
error_report("Bitmap '%s' in a node with auto-generated "
|
||||||
|
"name '%s' can't be migrated",
|
||||||
|
- bdrv_dirty_bitmap_name(bitmap), bs_name);
|
||||||
|
+ bitmap_name, node_alias);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
FOR_EACH_DIRTY_BITMAP(bs, bitmap) {
|
||||||
|
- if (!bdrv_dirty_bitmap_name(bitmap)) {
|
||||||
|
+ bitmap_name = bdrv_dirty_bitmap_name(bitmap);
|
||||||
|
+ if (!bitmap_name) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -326,12 +537,29 @@ static int add_bitmaps_to_list(DBMSaveState *s, BlockDriverState *bs,
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (bitmap_aliases) {
|
||||||
|
+ bitmap_alias = g_hash_table_lookup(bitmap_aliases, bitmap_name);
|
||||||
|
+ if (!bitmap_alias) {
|
||||||
|
+ /* Skip bitmaps with no alias */
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+ } else {
|
||||||
|
+ if (strlen(bitmap_name) > UINT8_MAX) {
|
||||||
|
+ error_report("Cannot migrate bitmap '%s' on node '%s': "
|
||||||
|
+ "Name is longer than %u bytes",
|
||||||
|
+ bitmap_name, bs_name, UINT8_MAX);
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+ bitmap_alias = bitmap_name;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
bdrv_ref(bs);
|
||||||
|
bdrv_dirty_bitmap_set_busy(bitmap, true);
|
||||||
|
|
||||||
|
dbms = g_new0(SaveBitmapState, 1);
|
||||||
|
dbms->bs = bs;
|
||||||
|
- dbms->node_name = bs_name;
|
||||||
|
+ dbms->node_alias = g_strdup(node_alias);
|
||||||
|
+ dbms->bitmap_alias = g_strdup(bitmap_alias);
|
||||||
|
dbms->bitmap = bitmap;
|
||||||
|
dbms->total_sectors = bdrv_nb_sectors(bs);
|
||||||
|
dbms->sectors_per_chunk = CHUNK_SIZE * 8 *
|
||||||
|
@@ -356,43 +584,52 @@ static int init_dirty_bitmap_migration(DBMSaveState *s)
|
||||||
|
SaveBitmapState *dbms;
|
||||||
|
GHashTable *handled_by_blk = g_hash_table_new(NULL, NULL);
|
||||||
|
BlockBackend *blk;
|
||||||
|
+ const MigrationParameters *mig_params = &migrate_get_current()->parameters;
|
||||||
|
+ GHashTable *alias_map = NULL;
|
||||||
|
+
|
||||||
|
+ if (mig_params->has_block_bitmap_mapping) {
|
||||||
|
+ alias_map = construct_alias_map(mig_params->block_bitmap_mapping, true,
|
||||||
|
+ &error_abort);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
s->bulk_completed = false;
|
||||||
|
s->prev_bs = NULL;
|
||||||
|
s->prev_bitmap = NULL;
|
||||||
|
s->no_bitmaps = false;
|
||||||
|
|
||||||
|
- /*
|
||||||
|
- * Use blockdevice name for direct (or filtered) children of named block
|
||||||
|
- * backends.
|
||||||
|
- */
|
||||||
|
- for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
|
||||||
|
- const char *name = blk_name(blk);
|
||||||
|
-
|
||||||
|
- if (!name || strcmp(name, "") == 0) {
|
||||||
|
- continue;
|
||||||
|
- }
|
||||||
|
+ if (!alias_map) {
|
||||||
|
+ /*
|
||||||
|
+ * Use blockdevice name for direct (or filtered) children of named block
|
||||||
|
+ * backends.
|
||||||
|
+ */
|
||||||
|
+ for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
|
||||||
|
+ const char *name = blk_name(blk);
|
||||||
|
|
||||||
|
- bs = blk_bs(blk);
|
||||||
|
+ if (!name || strcmp(name, "") == 0) {
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- /* Skip filters without bitmaps */
|
||||||
|
- while (bs && bs->drv && bs->drv->is_filter &&
|
||||||
|
- !bdrv_has_named_bitmaps(bs))
|
||||||
|
- {
|
||||||
|
- if (bs->backing) {
|
||||||
|
- bs = bs->backing->bs;
|
||||||
|
- } else if (bs->file) {
|
||||||
|
- bs = bs->file->bs;
|
||||||
|
- } else {
|
||||||
|
- bs = NULL;
|
||||||
|
+ bs = blk_bs(blk);
|
||||||
|
+
|
||||||
|
+ /* Skip filters without bitmaps */
|
||||||
|
+ while (bs && bs->drv && bs->drv->is_filter &&
|
||||||
|
+ !bdrv_has_named_bitmaps(bs))
|
||||||
|
+ {
|
||||||
|
+ if (bs->backing) {
|
||||||
|
+ bs = bs->backing->bs;
|
||||||
|
+ } else if (bs->file) {
|
||||||
|
+ bs = bs->file->bs;
|
||||||
|
+ } else {
|
||||||
|
+ bs = NULL;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
- }
|
||||||
|
|
||||||
|
- if (bs && bs->drv && !bs->drv->is_filter) {
|
||||||
|
- if (add_bitmaps_to_list(s, bs, name)) {
|
||||||
|
- goto fail;
|
||||||
|
+ if (bs && bs->drv && !bs->drv->is_filter) {
|
||||||
|
+ if (add_bitmaps_to_list(s, bs, name, NULL)) {
|
||||||
|
+ goto fail;
|
||||||
|
+ }
|
||||||
|
+ g_hash_table_add(handled_by_blk, bs);
|
||||||
|
}
|
||||||
|
- g_hash_table_add(handled_by_blk, bs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -401,7 +638,7 @@ static int init_dirty_bitmap_migration(DBMSaveState *s)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (add_bitmaps_to_list(s, bs, bdrv_get_node_name(bs))) {
|
||||||
|
+ if (add_bitmaps_to_list(s, bs, bdrv_get_node_name(bs), alias_map)) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -416,11 +653,17 @@ static int init_dirty_bitmap_migration(DBMSaveState *s)
|
||||||
|
}
|
||||||
|
|
||||||
|
g_hash_table_destroy(handled_by_blk);
|
||||||
|
+ if (alias_map) {
|
||||||
|
+ g_hash_table_destroy(alias_map);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
g_hash_table_destroy(handled_by_blk);
|
||||||
|
+ if (alias_map) {
|
||||||
|
+ g_hash_table_destroy(alias_map);
|
||||||
|
+ }
|
||||||
|
dirty_bitmap_do_save_cleanup(s);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
@@ -770,8 +1013,10 @@ static int dirty_bitmap_load_bits(QEMUFile *f, DBMLoadState *s)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int dirty_bitmap_load_header(QEMUFile *f, DBMLoadState *s)
|
||||||
|
+static int dirty_bitmap_load_header(QEMUFile *f, DBMLoadState *s,
|
||||||
|
+ GHashTable *alias_map)
|
||||||
|
{
|
||||||
|
+ GHashTable *bitmap_alias_map = NULL;
|
||||||
|
Error *local_err = NULL;
|
||||||
|
bool nothing;
|
||||||
|
s->flags = qemu_get_bitmap_flags(f);
|
||||||
|
@@ -780,28 +1025,75 @@ static int dirty_bitmap_load_header(QEMUFile *f, DBMLoadState *s)
|
||||||
|
nothing = s->flags == (s->flags & DIRTY_BITMAP_MIG_FLAG_EOS);
|
||||||
|
|
||||||
|
if (s->flags & DIRTY_BITMAP_MIG_FLAG_DEVICE_NAME) {
|
||||||
|
- if (!qemu_get_counted_string(f, s->node_name)) {
|
||||||
|
- error_report("Unable to read node name string");
|
||||||
|
+ if (!qemu_get_counted_string(f, s->node_alias)) {
|
||||||
|
+ error_report("Unable to read node alias string");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
if (!s->cancelled) {
|
||||||
|
- s->bs = bdrv_lookup_bs(s->node_name, s->node_name, &local_err);
|
||||||
|
+ if (alias_map) {
|
||||||
|
+ const AliasMapInnerNode *amin;
|
||||||
|
+
|
||||||
|
+ amin = g_hash_table_lookup(alias_map, s->node_alias);
|
||||||
|
+ if (!amin) {
|
||||||
|
+ error_setg(&local_err, "Error: Unknown node alias '%s'",
|
||||||
|
+ s->node_alias);
|
||||||
|
+ s->bs = NULL;
|
||||||
|
+ } else {
|
||||||
|
+ bitmap_alias_map = amin->subtree;
|
||||||
|
+ s->bs = bdrv_lookup_bs(NULL, amin->string, &local_err);
|
||||||
|
+ }
|
||||||
|
+ } else {
|
||||||
|
+ s->bs = bdrv_lookup_bs(s->node_alias, s->node_alias,
|
||||||
|
+ &local_err);
|
||||||
|
+ }
|
||||||
|
if (!s->bs) {
|
||||||
|
error_report_err(local_err);
|
||||||
|
cancel_incoming_locked(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- } else if (!s->bs && !nothing && !s->cancelled) {
|
||||||
|
+ } else if (s->bs) {
|
||||||
|
+ if (alias_map) {
|
||||||
|
+ const AliasMapInnerNode *amin;
|
||||||
|
+
|
||||||
|
+ /* Must be present in the map, or s->bs would not be set */
|
||||||
|
+ amin = g_hash_table_lookup(alias_map, s->node_alias);
|
||||||
|
+ assert(amin != NULL);
|
||||||
|
+
|
||||||
|
+ bitmap_alias_map = amin->subtree;
|
||||||
|
+ }
|
||||||
|
+ } else if (!nothing && !s->cancelled) {
|
||||||
|
error_report("Error: block device name is not set");
|
||||||
|
cancel_incoming_locked(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ assert(nothing || s->cancelled || !!alias_map == !!bitmap_alias_map);
|
||||||
|
+
|
||||||
|
if (s->flags & DIRTY_BITMAP_MIG_FLAG_BITMAP_NAME) {
|
||||||
|
- if (!qemu_get_counted_string(f, s->bitmap_name)) {
|
||||||
|
- error_report("Unable to read bitmap name string");
|
||||||
|
+ const char *bitmap_name;
|
||||||
|
+
|
||||||
|
+ if (!qemu_get_counted_string(f, s->bitmap_alias)) {
|
||||||
|
+ error_report("Unable to read bitmap alias string");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ if (!s->cancelled) {
|
||||||
|
+ if (bitmap_alias_map) {
|
||||||
|
+ bitmap_name = g_hash_table_lookup(bitmap_alias_map,
|
||||||
|
+ s->bitmap_alias);
|
||||||
|
+ if (!bitmap_name) {
|
||||||
|
+ error_report("Error: Unknown bitmap alias '%s' on node "
|
||||||
|
+ "'%s' (alias '%s')", s->bitmap_alias,
|
||||||
|
+ s->bs->node_name, s->node_alias);
|
||||||
|
+ cancel_incoming_locked(s);
|
||||||
|
+ }
|
||||||
|
+ } else {
|
||||||
|
+ bitmap_name = s->bitmap_alias;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (!s->cancelled) {
|
||||||
|
+ g_strlcpy(s->bitmap_name, bitmap_name, sizeof(s->bitmap_name));
|
||||||
|
s->bitmap = bdrv_find_dirty_bitmap(s->bs, s->bitmap_name);
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -811,7 +1103,7 @@ static int dirty_bitmap_load_header(QEMUFile *f, DBMLoadState *s)
|
||||||
|
if (!s->bitmap && !(s->flags & DIRTY_BITMAP_MIG_FLAG_START)) {
|
||||||
|
error_report("Error: unknown dirty bitmap "
|
||||||
|
"'%s' for block device '%s'",
|
||||||
|
- s->bitmap_name, s->node_name);
|
||||||
|
+ s->bitmap_name, s->bs->node_name);
|
||||||
|
cancel_incoming_locked(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -835,6 +1127,8 @@ static int dirty_bitmap_load_header(QEMUFile *f, DBMLoadState *s)
|
||||||
|
*/
|
||||||
|
static int dirty_bitmap_load(QEMUFile *f, void *opaque, int version_id)
|
||||||
|
{
|
||||||
|
+ GHashTable *alias_map = NULL;
|
||||||
|
+ const MigrationParameters *mig_params = &migrate_get_current()->parameters;
|
||||||
|
DBMLoadState *s = &((DBMState *)opaque)->load;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
@@ -846,13 +1140,18 @@ static int dirty_bitmap_load(QEMUFile *f, void *opaque, int version_id)
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (mig_params->has_block_bitmap_mapping) {
|
||||||
|
+ alias_map = construct_alias_map(mig_params->block_bitmap_mapping,
|
||||||
|
+ false, &error_abort);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
do {
|
||||||
|
QEMU_LOCK_GUARD(&s->lock);
|
||||||
|
|
||||||
|
- ret = dirty_bitmap_load_header(f, s);
|
||||||
|
+ ret = dirty_bitmap_load_header(f, s, alias_map);
|
||||||
|
if (ret < 0) {
|
||||||
|
cancel_incoming_locked(s);
|
||||||
|
- return ret;
|
||||||
|
+ goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s->flags & DIRTY_BITMAP_MIG_FLAG_START) {
|
||||||
|
@@ -869,12 +1168,17 @@ static int dirty_bitmap_load(QEMUFile *f, void *opaque, int version_id)
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
cancel_incoming_locked(s);
|
||||||
|
- return ret;
|
||||||
|
+ goto fail;
|
||||||
|
}
|
||||||
|
} while (!(s->flags & DIRTY_BITMAP_MIG_FLAG_EOS));
|
||||||
|
|
||||||
|
trace_dirty_bitmap_load_success();
|
||||||
|
- return 0;
|
||||||
|
+ ret = 0;
|
||||||
|
+fail:
|
||||||
|
+ if (alias_map) {
|
||||||
|
+ g_hash_table_destroy(alias_map);
|
||||||
|
+ }
|
||||||
|
+ return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dirty_bitmap_save_setup(QEMUFile *f, void *opaque)
|
||||||
|
diff --git a/migration/migration.c b/migration/migration.c
|
||||||
|
index bf684185b7..7a89ce39a7 100644
|
||||||
|
--- a/migration/migration.c
|
||||||
|
+++ b/migration/migration.c
|
||||||
|
@@ -36,6 +36,7 @@
|
||||||
|
#include "block/block.h"
|
||||||
|
#include "qapi/error.h"
|
||||||
|
#include "qapi/clone-visitor.h"
|
||||||
|
+#include "qapi/qapi-visit-migration.h"
|
||||||
|
#include "qapi/qapi-visit-sockets.h"
|
||||||
|
#include "qapi/qapi-commands-migration.h"
|
||||||
|
#include "qapi/qapi-events-migration.h"
|
||||||
|
@@ -845,6 +846,13 @@ MigrationParameters *qmp_query_migrate_parameters(Error **errp)
|
||||||
|
params->has_announce_step = true;
|
||||||
|
params->announce_step = s->parameters.announce_step;
|
||||||
|
|
||||||
|
+ if (s->parameters.has_block_bitmap_mapping) {
|
||||||
|
+ params->has_block_bitmap_mapping = true;
|
||||||
|
+ params->block_bitmap_mapping =
|
||||||
|
+ QAPI_CLONE(BitmapMigrationNodeAliasList,
|
||||||
|
+ s->parameters.block_bitmap_mapping);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1310,6 +1318,13 @@ static bool migrate_params_check(MigrationParameters *params, Error **errp)
|
||||||
|
"is invalid, it must be in the range of 1 to 10000 ms");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ if (params->has_block_bitmap_mapping &&
|
||||||
|
+ !check_dirty_bitmap_mig_alias_map(params->block_bitmap_mapping, errp)) {
|
||||||
|
+ error_prepend(errp, "Invalid mapping given for block-bitmap-mapping: ");
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1404,6 +1419,11 @@ static void migrate_params_test_apply(MigrateSetParameters *params,
|
||||||
|
if (params->has_announce_step) {
|
||||||
|
dest->announce_step = params->announce_step;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ if (params->has_block_bitmap_mapping) {
|
||||||
|
+ dest->has_block_bitmap_mapping = true;
|
||||||
|
+ dest->block_bitmap_mapping = params->block_bitmap_mapping;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
static void migrate_params_apply(MigrateSetParameters *params, Error **errp)
|
||||||
|
@@ -1516,6 +1536,16 @@ static void migrate_params_apply(MigrateSetParameters *params, Error **errp)
|
||||||
|
if (params->has_announce_step) {
|
||||||
|
s->parameters.announce_step = params->announce_step;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ if (params->has_block_bitmap_mapping) {
|
||||||
|
+ qapi_free_BitmapMigrationNodeAliasList(
|
||||||
|
+ s->parameters.block_bitmap_mapping);
|
||||||
|
+
|
||||||
|
+ s->parameters.has_block_bitmap_mapping = true;
|
||||||
|
+ s->parameters.block_bitmap_mapping =
|
||||||
|
+ QAPI_CLONE(BitmapMigrationNodeAliasList,
|
||||||
|
+ params->block_bitmap_mapping);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
void qmp_migrate_set_parameters(MigrateSetParameters *params, Error **errp)
|
||||||
|
diff --git a/migration/migration.h b/migration/migration.h
|
||||||
|
index 721e272713..4be42e8c11 100644
|
||||||
|
--- a/migration/migration.h
|
||||||
|
+++ b/migration/migration.h
|
||||||
|
@@ -337,6 +337,9 @@ void migrate_send_rp_resume_ack(MigrationIncomingState *mis, uint32_t value);
|
||||||
|
void dirty_bitmap_mig_before_vm_start(void);
|
||||||
|
void dirty_bitmap_mig_cancel_outgoing(void);
|
||||||
|
void dirty_bitmap_mig_cancel_incoming(void);
|
||||||
|
+bool check_dirty_bitmap_mig_alias_map(const BitmapMigrationNodeAliasList *bbm,
|
||||||
|
+ Error **errp);
|
||||||
|
+
|
||||||
|
void migrate_add_address(SocketAddress *address);
|
||||||
|
|
||||||
|
int foreach_not_ignored_block(RAMBlockIterFunc func, void *opaque);
|
||||||
|
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
|
||||||
|
index ae4b6a4246..7711726fd2 100644
|
||||||
|
--- a/monitor/hmp-cmds.c
|
||||||
|
+++ b/monitor/hmp-cmds.c
|
||||||
|
@@ -469,6 +469,32 @@ void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict)
|
||||||
|
monitor_printf(mon, "%s: '%s'\n",
|
||||||
|
MigrationParameter_str(MIGRATION_PARAMETER_TLS_AUTHZ),
|
||||||
|
params->tls_authz);
|
||||||
|
+
|
||||||
|
+ if (params->has_block_bitmap_mapping) {
|
||||||
|
+ const BitmapMigrationNodeAliasList *bmnal;
|
||||||
|
+
|
||||||
|
+ monitor_printf(mon, "%s:\n",
|
||||||
|
+ MigrationParameter_str(
|
||||||
|
+ MIGRATION_PARAMETER_BLOCK_BITMAP_MAPPING));
|
||||||
|
+
|
||||||
|
+ for (bmnal = params->block_bitmap_mapping;
|
||||||
|
+ bmnal;
|
||||||
|
+ bmnal = bmnal->next)
|
||||||
|
+ {
|
||||||
|
+ const BitmapMigrationNodeAlias *bmna = bmnal->value;
|
||||||
|
+ const BitmapMigrationBitmapAliasList *bmbal;
|
||||||
|
+
|
||||||
|
+ monitor_printf(mon, " '%s' -> '%s'\n",
|
||||||
|
+ bmna->node_name, bmna->alias);
|
||||||
|
+
|
||||||
|
+ for (bmbal = bmna->bitmaps; bmbal; bmbal = bmbal->next) {
|
||||||
|
+ const BitmapMigrationBitmapAlias *bmba = bmbal->value;
|
||||||
|
+
|
||||||
|
+ monitor_printf(mon, " '%s' -> '%s'\n",
|
||||||
|
+ bmba->name, bmba->alias);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
qapi_free_MigrationParameters(params);
|
||||||
|
@@ -1384,6 +1410,10 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
|
||||||
|
p->has_announce_step = true;
|
||||||
|
visit_type_size(v, param, &p->announce_step, &err);
|
||||||
|
break;
|
||||||
|
+ case MIGRATION_PARAMETER_BLOCK_BITMAP_MAPPING:
|
||||||
|
+ error_setg(&err, "The block-bitmap-mapping parameter can only be set "
|
||||||
|
+ "through QMP");
|
||||||
|
+ break;
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
diff --git a/qapi/migration.json b/qapi/migration.json
|
||||||
|
index ea53b23dca..5f6b06172c 100644
|
||||||
|
--- a/qapi/migration.json
|
||||||
|
+++ b/qapi/migration.json
|
||||||
|
@@ -508,6 +508,44 @@
|
||||||
|
'data': [ 'none', 'zlib',
|
||||||
|
{ 'name': 'zstd', 'if': 'defined(CONFIG_ZSTD)' } ] }
|
||||||
|
|
||||||
|
+##
|
||||||
|
+# @BitmapMigrationBitmapAlias:
|
||||||
|
+#
|
||||||
|
+# @name: The name of the bitmap.
|
||||||
|
+#
|
||||||
|
+# @alias: An alias name for migration (for example the bitmap name on
|
||||||
|
+# the opposite site).
|
||||||
|
+#
|
||||||
|
+# Since: 5.2
|
||||||
|
+##
|
||||||
|
+{ 'struct': 'BitmapMigrationBitmapAlias',
|
||||||
|
+ 'data': {
|
||||||
|
+ 'name': 'str',
|
||||||
|
+ 'alias': 'str'
|
||||||
|
+ } }
|
||||||
|
+
|
||||||
|
+##
|
||||||
|
+# @BitmapMigrationNodeAlias:
|
||||||
|
+#
|
||||||
|
+# Maps a block node name and the bitmaps it has to aliases for dirty
|
||||||
|
+# bitmap migration.
|
||||||
|
+#
|
||||||
|
+# @node-name: A block node name.
|
||||||
|
+#
|
||||||
|
+# @alias: An alias block node name for migration (for example the
|
||||||
|
+# node name on the opposite site).
|
||||||
|
+#
|
||||||
|
+# @bitmaps: Mappings for the bitmaps on this node.
|
||||||
|
+#
|
||||||
|
+# Since: 5.2
|
||||||
|
+##
|
||||||
|
+{ 'struct': 'BitmapMigrationNodeAlias',
|
||||||
|
+ 'data': {
|
||||||
|
+ 'node-name': 'str',
|
||||||
|
+ 'alias': 'str',
|
||||||
|
+ 'bitmaps': [ 'BitmapMigrationBitmapAlias' ]
|
||||||
|
+ } }
|
||||||
|
+
|
||||||
|
##
|
||||||
|
# @MigrationParameter:
|
||||||
|
#
|
||||||
|
@@ -642,6 +680,25 @@
|
||||||
|
# will consume more CPU.
|
||||||
|
# Defaults to 1. (Since 5.0)
|
||||||
|
#
|
||||||
|
+# @block-bitmap-mapping: Maps block nodes and bitmaps on them to
|
||||||
|
+# aliases for the purpose of dirty bitmap migration. Such
|
||||||
|
+# aliases may for example be the corresponding names on the
|
||||||
|
+# opposite site.
|
||||||
|
+# The mapping must be one-to-one, but not necessarily
|
||||||
|
+# complete: On the source, unmapped bitmaps and all bitmaps
|
||||||
|
+# on unmapped nodes will be ignored. On the destination,
|
||||||
|
+# encountering an unmapped alias in the incoming migration
|
||||||
|
+# stream will result in a report, and all further bitmap
|
||||||
|
+# migration data will then be discarded.
|
||||||
|
+# Note that the destination does not know about bitmaps it
|
||||||
|
+# does not receive, so there is no limitation or requirement
|
||||||
|
+# regarding the number of bitmaps received, or how they are
|
||||||
|
+# named, or on which nodes they are placed.
|
||||||
|
+# By default (when this parameter has never been set), bitmap
|
||||||
|
+# names are mapped to themselves. Nodes are mapped to their
|
||||||
|
+# block device name if there is one, and to their node name
|
||||||
|
+# otherwise. (Since 5.2)
|
||||||
|
+#
|
||||||
|
# Since: 2.4
|
||||||
|
##
|
||||||
|
{ 'enum': 'MigrationParameter',
|
||||||
|
@@ -656,7 +713,8 @@
|
||||||
|
'multifd-channels',
|
||||||
|
'xbzrle-cache-size', 'max-postcopy-bandwidth',
|
||||||
|
'max-cpu-throttle', 'multifd-compression',
|
||||||
|
- 'multifd-zlib-level' ,'multifd-zstd-level' ] }
|
||||||
|
+ 'multifd-zlib-level' ,'multifd-zstd-level',
|
||||||
|
+ 'block-bitmap-mapping' ] }
|
||||||
|
|
||||||
|
##
|
||||||
|
# @MigrateSetParameters:
|
||||||
|
@@ -782,6 +840,25 @@
|
||||||
|
# will consume more CPU.
|
||||||
|
# Defaults to 1. (Since 5.0)
|
||||||
|
#
|
||||||
|
+# @block-bitmap-mapping: Maps block nodes and bitmaps on them to
|
||||||
|
+# aliases for the purpose of dirty bitmap migration. Such
|
||||||
|
+# aliases may for example be the corresponding names on the
|
||||||
|
+# opposite site.
|
||||||
|
+# The mapping must be one-to-one, but not necessarily
|
||||||
|
+# complete: On the source, unmapped bitmaps and all bitmaps
|
||||||
|
+# on unmapped nodes will be ignored. On the destination,
|
||||||
|
+# encountering an unmapped alias in the incoming migration
|
||||||
|
+# stream will result in a report, and all further bitmap
|
||||||
|
+# migration data will then be discarded.
|
||||||
|
+# Note that the destination does not know about bitmaps it
|
||||||
|
+# does not receive, so there is no limitation or requirement
|
||||||
|
+# regarding the number of bitmaps received, or how they are
|
||||||
|
+# named, or on which nodes they are placed.
|
||||||
|
+# By default (when this parameter has never been set), bitmap
|
||||||
|
+# names are mapped to themselves. Nodes are mapped to their
|
||||||
|
+# block device name if there is one, and to their node name
|
||||||
|
+# otherwise. (Since 5.2)
|
||||||
|
+#
|
||||||
|
# Since: 2.4
|
||||||
|
##
|
||||||
|
# TODO either fuse back into MigrationParameters, or make
|
||||||
|
@@ -812,7 +889,8 @@
|
||||||
|
'*max-cpu-throttle': 'int',
|
||||||
|
'*multifd-compression': 'MultiFDCompression',
|
||||||
|
'*multifd-zlib-level': 'int',
|
||||||
|
- '*multifd-zstd-level': 'int' } }
|
||||||
|
+ '*multifd-zstd-level': 'int',
|
||||||
|
+ '*block-bitmap-mapping': [ 'BitmapMigrationNodeAlias' ] } }
|
||||||
|
|
||||||
|
##
|
||||||
|
# @migrate-set-parameters:
|
||||||
|
@@ -958,6 +1036,25 @@
|
||||||
|
# will consume more CPU.
|
||||||
|
# Defaults to 1. (Since 5.0)
|
||||||
|
#
|
||||||
|
+# @block-bitmap-mapping: Maps block nodes and bitmaps on them to
|
||||||
|
+# aliases for the purpose of dirty bitmap migration. Such
|
||||||
|
+# aliases may for example be the corresponding names on the
|
||||||
|
+# opposite site.
|
||||||
|
+# The mapping must be one-to-one, but not necessarily
|
||||||
|
+# complete: On the source, unmapped bitmaps and all bitmaps
|
||||||
|
+# on unmapped nodes will be ignored. On the destination,
|
||||||
|
+# encountering an unmapped alias in the incoming migration
|
||||||
|
+# stream will result in a report, and all further bitmap
|
||||||
|
+# migration data will then be discarded.
|
||||||
|
+# Note that the destination does not know about bitmaps it
|
||||||
|
+# does not receive, so there is no limitation or requirement
|
||||||
|
+# regarding the number of bitmaps received, or how they are
|
||||||
|
+# named, or on which nodes they are placed.
|
||||||
|
+# By default (when this parameter has never been set), bitmap
|
||||||
|
+# names are mapped to themselves. Nodes are mapped to their
|
||||||
|
+# block device name if there is one, and to their node name
|
||||||
|
+# otherwise. (Since 5.2)
|
||||||
|
+#
|
||||||
|
# Since: 2.4
|
||||||
|
##
|
||||||
|
{ 'struct': 'MigrationParameters',
|
||||||
|
@@ -986,7 +1083,8 @@
|
||||||
|
'*max-cpu-throttle': 'uint8',
|
||||||
|
'*multifd-compression': 'MultiFDCompression',
|
||||||
|
'*multifd-zlib-level': 'uint8',
|
||||||
|
- '*multifd-zstd-level': 'uint8' } }
|
||||||
|
+ '*multifd-zstd-level': 'uint8',
|
||||||
|
+ '*block-bitmap-mapping': [ 'BitmapMigrationNodeAlias' ] } }
|
||||||
|
|
||||||
|
##
|
||||||
|
# @query-migrate-parameters:
|
||||||
|
--
|
||||||
|
2.27.0
|
||||||
|
|
@ -69,7 +69,7 @@ Obsoletes: %1-rhev
|
|||||||
Summary: QEMU is a machine emulator and virtualizer
|
Summary: QEMU is a machine emulator and virtualizer
|
||||||
Name: qemu-kvm
|
Name: qemu-kvm
|
||||||
Version: 5.1.0
|
Version: 5.1.0
|
||||||
Release: 3%{?dist}
|
Release: 4%{?dist}
|
||||||
# Epoch because we pushed a qemu-1.0 package. AIUI this can't ever be dropped
|
# Epoch because we pushed a qemu-1.0 package. AIUI this can't ever be dropped
|
||||||
Epoch: 15
|
Epoch: 15
|
||||||
License: GPLv2 and GPLv2+ and CC-BY
|
License: GPLv2 and GPLv2+ and CC-BY
|
||||||
@ -146,6 +146,18 @@ Patch38: kvm-redhat-Update-hw_compat_8_2.patch
|
|||||||
Patch39: kvm-redhat-update-pseries-rhel8.2.0-machine-type.patch
|
Patch39: kvm-redhat-update-pseries-rhel8.2.0-machine-type.patch
|
||||||
# For bz#1801242 - [aarch64] vTPM support in machvirt
|
# For bz#1801242 - [aarch64] vTPM support in machvirt
|
||||||
Patch40: kvm-Disable-TPM-passthrough-backend-on-ARM.patch
|
Patch40: kvm-Disable-TPM-passthrough-backend-on-ARM.patch
|
||||||
|
# For bz#1867075 - CVE-2020-10756 virt:8.3/qemu-kvm: QEMU: slirp: networking out-of-bounds read information disclosure vulnerability [rhel-av-8]
|
||||||
|
Patch41: kvm-Drop-bogus-IPv6-messages.patch
|
||||||
|
# For bz#1849707 - 8.3 machine types for x86 - 5.1 update
|
||||||
|
Patch42: kvm-machine-types-numa-set-numa_mem_supported-on-old-mac.patch
|
||||||
|
# For bz#1849707 - 8.3 machine types for x86 - 5.1 update
|
||||||
|
Patch43: kvm-machine_types-numa-compatibility-for-auto_enable_num.patch
|
||||||
|
# For bz#1790492 - 'dirty-bitmaps' migration capability should allow configuring target nodenames
|
||||||
|
Patch44: kvm-migration-Add-block-bitmap-mapping-parameter.patch
|
||||||
|
# For bz#1790492 - 'dirty-bitmaps' migration capability should allow configuring target nodenames
|
||||||
|
Patch45: kvm-iotests.py-Let-wait_migration-return-on-failure.patch
|
||||||
|
# For bz#1790492 - 'dirty-bitmaps' migration capability should allow configuring target nodenames
|
||||||
|
Patch46: kvm-iotests-Test-node-bitmap-aliases-during-migration.patch
|
||||||
|
|
||||||
BuildRequires: wget
|
BuildRequires: wget
|
||||||
BuildRequires: rpm-build
|
BuildRequires: rpm-build
|
||||||
@ -1114,6 +1126,20 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \
|
|||||||
|
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Thu Aug 27 2020 Danilo Cesar Lemes de Paula <ddepaula@redhat.com> - 5.1.0-4.el8
|
||||||
|
- kvm-Drop-bogus-IPv6-messages.patch [bz#1867075]
|
||||||
|
- kvm-machine-types-numa-set-numa_mem_supported-on-old-mac.patch [bz#1849707]
|
||||||
|
- kvm-machine_types-numa-compatibility-for-auto_enable_num.patch [bz#1849707]
|
||||||
|
- kvm-migration-Add-block-bitmap-mapping-parameter.patch [bz#1790492]
|
||||||
|
- kvm-iotests.py-Let-wait_migration-return-on-failure.patch [bz#1790492]
|
||||||
|
- kvm-iotests-Test-node-bitmap-aliases-during-migration.patch [bz#1790492]
|
||||||
|
- Resolves: bz#1790492
|
||||||
|
('dirty-bitmaps' migration capability should allow configuring target nodenames)
|
||||||
|
- Resolves: bz#1849707
|
||||||
|
(8.3 machine types for x86 - 5.1 update)
|
||||||
|
- Resolves: bz#1867075
|
||||||
|
(CVE-2020-10756 virt:8.3/qemu-kvm: QEMU: slirp: networking out-of-bounds read information disclosure vulnerability [rhel-av-8])
|
||||||
|
|
||||||
* Wed Aug 19 2020 Danilo Cesar Lemes de Paula <ddepaula@redhat.com> - 5.1.0-3.el8
|
* Wed Aug 19 2020 Danilo Cesar Lemes de Paula <ddepaula@redhat.com> - 5.1.0-3.el8
|
||||||
- kvm-redhat-Update-hw_compat_8_2.patch [bz#1843348]
|
- kvm-redhat-Update-hw_compat_8_2.patch [bz#1843348]
|
||||||
- kvm-redhat-update-pseries-rhel8.2.0-machine-type.patch [bz#1843348]
|
- kvm-redhat-update-pseries-rhel8.2.0-machine-type.patch [bz#1843348]
|
||||||
|
Loading…
Reference in New Issue
Block a user