os-autoinst/SOURCES/os-autoinst-enable-multifd-support.patch
Andrew Lukoshko 03d6dff9e1 Backport multifd support for qemu >= 9.1 compatibility
Cherry-pick upstream commit 10216249 which switches from the removed
"compress" migration capability to multifd migration with compression.
2026-04-21 16:26:46 +02:00

187 lines
10 KiB
Diff

From 10216249e021a87f7a6fac89970ae463c7ae25ad Mon Sep 17 00:00:00 2001
From: Guillaume Gardet <guillaume.gardet@arm.com>
Date: Fri, 27 Sep 2024 09:53:47 +0200
Subject: [PATCH] Enable multifd support
From qemu 9.1.0, the "compress" migration capability has been removed,
but multifd migration is able to do compression and can be used instead.
---
backend/qemu.pm | 93 +++++++++++++++++++++++++++------------
doc/backend_vars.asciidoc | 5 ++-
2 files changed, 68 insertions(+), 30 deletions(-)
diff --git a/backend/qemu.pm b/backend/qemu.pm
index c86688b7a5e..474da41b2b0 100644
--- a/backend/qemu.pm
+++ b/backend/qemu.pm
@@ -240,27 +240,49 @@ sub _migrate_to_file ($self, %args) {
my $fdname = 'dumpfd';
my $compress_level = $args{compress_level} || 0;
my $compress_threads = $args{compress_threads} // 2;
+ my $multifd_channels = $args{multifd_channels} // 2;
my $filename = $args{filename};
my $max_bandwidth = $args{max_bandwidth} // LONG_MAX;
+ # poo#167218: From qemu 9.1, the "compress" migration capability has been removed,
+ # but multifd migration is able to do compression and can be used instead.
+ my $migration_use_multifd = $args{migration_use_multifd} // (version->declare($self->{qemu_version}) ge version->declare(9.1));
- # Internally compressed dumps can't be opened by crash. They need to be
- # fed back into QEMU as an incoming migration.
- $self->set_migrate_capability('compress', 1) if $compress_level > 0;
$self->set_migrate_capability('events', 1);
- $self->handle_qmp_command(
- {
- execute => 'migrate-set-parameters',
- arguments => {
- # This is ignored if the compress capability is not set
- 'compress-level' => $compress_level + 0,
- 'compress-threads' => $compress_threads + 0,
- # Ensure slow dump times are not due to a transfer rate cap
- 'max-bandwidth' => $max_bandwidth + 0,
- }
- },
- fatal => 1
- );
+ # Internally compressed dumps can't be opened by crash. They need to be
+ # fed back into QEMU as an incoming migration.
+ if ($migration_use_multifd) {
+ $self->set_migrate_capability('multifd', 1);
+ $self->set_migrate_capability('mapped-ram', 1);
+ $self->handle_qmp_command(
+ {
+ execute => 'migrate-set-parameters',
+ arguments => {
+ 'multifd-channels' => $multifd_channels + 0,
+ 'direct-io' => Mojo::JSON->true,
+ # Ensure slow dump times are not due to a transfer rate cap
+ 'max-bandwidth' => $max_bandwidth + 0,
+ }
+ },
+ fatal => 1
+ );
+ }
+ else {
+ $self->set_migrate_capability('compress', 1) if $compress_level > 0;
+ $self->handle_qmp_command(
+ {
+ execute => 'migrate-set-parameters',
+ arguments => {
+ # This is ignored if the compress capability is not set
+ 'compress-level' => $compress_level + 0,
+ 'compress-threads' => $compress_threads + 0,
+ # Ensure slow dump times are not due to a transfer rate cap
+ 'max-bandwidth' => $max_bandwidth + 0,
+ }
+ },
+ fatal => 1
+ );
+ }
$self->open_file_and_send_fd_to_qemu($filename, $fdname);
@@ -268,10 +290,11 @@ sub _migrate_to_file ($self, %args) {
# mark. However it is easier for QEMU if the VM is already frozen.
$self->freeze_vm();
# migrate consumes the file descriptor, so we do not need to call closefd
+ my $migration_strategy = $migration_use_multifd ? "file" : "fd";
$self->handle_qmp_command(
{
execute => 'migrate',
- arguments => {uri => "fd:$fdname"}
+ arguments => {uri => "$migration_strategy:$fdname"}
},
fatal => 1
);
@@ -292,6 +315,8 @@ sub save_memory_dump ($self, $args) {
my $compress_method = $vars->{QEMU_DUMP_COMPRESS_METHOD} || 'xz';
my $compress_level = $vars->{QEMU_COMPRESS_LEVEL} || 6;
my $compress_threads = $vars->{QEMU_COMPRESS_THREADS} || $vars->{QEMUCPUS} || 2;
+ my $migration_use_multifd = (version->declare($self->{qemu_version}) ge version->declare(9.1));
+ my $multifd_channels = $vars->{QEMU_MULTIFD_CHANNELS} || 2;
my $filename = $args->{filename} . '-vm-memory-dump';
my $rsp = $self->handle_qmp_command({execute => 'query-status'}, fatal => 1);
@@ -301,6 +326,8 @@ sub save_memory_dump ($self, $args) {
mkpath('ulogs');
$self->_migrate_to_file(compress_level => $compress_method eq 'internal' ? $compress_level : 0,
compress_threads => $compress_threads,
+ multifd_channels => $multifd_channels,
+ migration_use_multifd => $migration_use_multifd,
filename => "ulogs/$filename",
max_bandwidth => $vars->{QEMU_MAX_BANDWIDTH});
@@ -442,6 +469,8 @@ sub save_snapshot ($self, $args) {
filename => path(VM_SNAPSHOTS_DIR, $snapshot->name),
compress_level => $vars->{QEMU_COMPRESS_LEVEL} || 6,
compress_threads => $vars->{QEMU_COMPRESS_THREADS} // $vars->{QEMUCPUS},
+ multifd_channels => $vars->{QEMU_MULTIFD_CHANNELS} || 2,
+ migration_use_multifd => (version->declare($self->{qemu_version}) ge version->declare(9.1)),
max_bandwidth => $vars->{QEMU_MAX_BANDWIDTH});
diag('Snapshot complete');
@@ -454,6 +483,10 @@ sub save_snapshot ($self, $args) {
sub load_snapshot ($self, $args) {
my $vmname = $args->{name};
+ # poo#167218: From qemu 9.1, the "compress" migration capability has been removed,
+ # but multifd migration is able to do compression and can be used instead.
+ my $migration_use_multifd = (version->declare($self->{qemu_version}) ge version->declare(9.1));
+ my $fdname = 'dumpfd';
my $rsp = $self->handle_qmp_command({execute => 'query-status'}, fatal => 1);
bmwqemu::diag("Loading snapshot (Current VM state is $rsp->{return}->{status})");
@@ -478,18 +511,22 @@ sub load_snapshot ($self, $args) {
$self->{select_read}->add($qemu_pipe, 'qemu::load_snapshot::qemu_pipe');
$self->{select_write}->add($qemu_pipe, 'qemu::load_snapshot::qemu_pipe');
- # Ideally we want to send a file descriptor to QEMU, but it doesn't seem
- # to work for incoming migrations, so we are forced to use exec:cat instead.
- #
- # my $fdname = 'incoming';
- # $self->open_file_and_send_fd_to_qemu(VM_SNAPSHOTS_DIR . '/' . $snapshot->name,
- # $fdname);
- $self->set_migrate_capability('compress', 1);
$self->set_migrate_capability('events', 1);
- $rsp = $self->handle_qmp_command({execute => 'migrate-incoming',
- arguments => {uri => 'exec:cat ' . VM_SNAPSHOTS_DIR . '/' . $snapshot->name}},
- #arguments => { uri => "fd:$fdname" }},
- fatal => 1);
+
+ if ($migration_use_multifd) {
+ $self->set_migrate_capability('multifd', 1);
+ $self->set_migrate_capability('mapped-ram', 1) if (version->declare($self->{qemu_version}) ge version->declare(9.0));
+ $self->open_file_and_send_fd_to_qemu(VM_SNAPSHOTS_DIR . '/' . $snapshot->name,
+ $fdname);
+ $rsp = $self->handle_qmp_command({execute => 'migrate-incoming',
+ arguments => {uri => "file:$fdname"}},
+ fatal => 1);
+ } else {
+ $self->set_migrate_capability('compress', 1);
+ $rsp = $self->handle_qmp_command({execute => 'migrate-incoming',
+ arguments => {uri => 'exec:cat ' . VM_SNAPSHOTS_DIR . '/' . $snapshot->name}},
+ fatal => 1);
+ }
$self->load_console_snapshots($vmname);
diff --git a/doc/backend_vars.asciidoc b/doc/backend_vars.asciidoc
index e13b64f65d8..759164f4c5f 100644
--- a/doc/backend_vars.asciidoc
+++ b/doc/backend_vars.asciidoc
@@ -172,11 +172,12 @@ QEMU_SMBIOS;see qemu -smbios ?;undef;pass this value to qemu -smbios
QEMU_SOUNDHW;see qemu -soundhw ?;had;pass this value to qemu -soundhw (for qemu < 4.2)
QEMU_AUDIODEV;see qemu -device ?;intel-hda;Audio device to use with audiodev to qemu -device (for qemu >= 4.2)
QEMU_AUDIOBACKEND;see qemu -audio-help;none;Audio backend to use with audiodev (for qemu >= 4.2)
-QEMU_COMPRESS_LEVEL;integer;6;Sets the compression level used for memory dumps and snapshots. Zero turns compression off and 9 is the maximum level. Generally there is little improvement in compression ratio by increasing the level, but the CPU time can be high on some platforms.
-QEMU_COMPRESS_THREADS;integer;QEMUCPUS;Number of threads used for compressing memory dumps and snapshots.
+QEMU_COMPRESS_LEVEL;integer;6;Sets the compression level used for memory dumps and snapshots. Zero turns compression off and 9 is the maximum level. Generally there is little improvement in compression ratio by increasing the level, but the CPU time can be high on some platforms. (For qemu < 9.1.0)
+QEMU_COMPRESS_THREADS;integer;QEMUCPUS;Number of threads used for compressing memory dumps and snapshots. (For qemu < 9.1.0)
QEMU_NON_FATAL_DBUS_CALL;boolean;0;Ignore failed dbus calls and ignore instead of fatal exits
QEMU_MAX_BANDWIDTH;integer;INT_MAX;Limits the transfer rate during a snapshot.
QEMU_DUMP_COMPRESS_METHOD;string;xz;The compression to use during a memory dump. Can be set to xz, bzip2 or internal (QEMU's internal compression, not compatible with crash or gdb). If xz is set, but not available, it will fallback to bzip2. Also see QEMU_COMPRESSION_LEVEL.
+QEMU_MULTIFD_CHANNELS;integer;2;Number of channels used to migrate data in parallel (only when multifd is used, which means qemu >= 9.1.0). This is the same number that the number of sockets used for migration. Can be set from 1 to 255.
QEMU_APPEND;string;;Append parameters on qemu command line. The first item will have '-' prepended to it.
QEMU_ENABLE_SMBD;boolean;0;Enable QEMU's built-in samba service for user network. Exported worker's pool will be accessible on `\\10.0.2.4\qemu` share. Requires `smbd` to be installed (usually part of the `samba` package).
VIRTIO_CONSOLE;boolean;1;Enable/disable virtio console. (@see `-device virtconsole` qemu option)