Migration pull request

- Will's WITH_QEMU_LOCK_GUARD cleanup
 - Vladimir's new exit-on-error parameter
 - Fabiano's removals and deprecations series
   (block migration and non-multifd compression removed)
 - Peter's documentation fix for HMP migrate command
 
 v2:
 - updated Peter's documentation fix.
 -----BEGIN PGP SIGNATURE-----
 
 iQJEBAABCAAuFiEEqhtIsKIjJqWkw2TPx5jcdBvsMZ0FAmY7934QHGZhcm9zYXNA
 c3VzZS5kZQAKCRDHmNx0G+wxnXynEADHjRa7HqwuYPhft3wGgLiFbCyQNFpNrjM9
 prQSiLlYt9gRlE4c9ZavCxR28xtOrK2oFhCnLMXaIEkct6JuylfiwCPwPuxNQP9+
 EZirECf1yKkyt+RV/LfIx3R/prJgoH5XWhpna+WIBFFo2qSorHTAzjb5dKYZDjkB
 EjfN8R9goVH6aCPd4SyiCUUNxuR6/0si9AxfhUgUvUXyLZmE1ztZEoWI02FCYzVj
 kKDdVK2+Z1Rlv88tyY4/E6z4pwYLWx5EiXSFv0NXIpTdyO3dM+jeAHxcN7KmQ1+5
 GvX0n+mFYOzRIbRfAnhSZbkez/nuPcbJ76phzSYDs8f/7YtOpuOFKFw7yuGrl5N5
 ZqXo5MOOGliF2wozTjacsOrUhB+MbSb0iA71T7aAdBC2s4H9+XIWfoN/OZfsBhAW
 r2i1gSytVLQqsip7A0CFF+DqeSse9QHHlH8vfb8NUn1Tp0o2QfsX+/7LHlvl/2eJ
 EP/zmjD6c/8vjB3fTKZr52h2lEO/36xmX+OtZpep3EBvvl1BY1LP4nBNOW1vQM/b
 fzcq+agaikwS5gI2QSOC9HJ3aX6q416+wZEm3rQ8XRGSPDFfLPKM/GPPfWdj6ngb
 +e3EZPrs+3dOeH1kly5xVMGXGUof+VVBmVwdv4C+XNMM8fRZOxoqd0SD8dz/vOC7
 nSGztXUPqw==
 =5T+K
 -----END PGP SIGNATURE-----

Merge tag 'migration-20240508-pull-request' of https://gitlab.com/farosas/qemu into staging

Migration pull request

- Will's WITH_QEMU_LOCK_GUARD cleanup
- Vladimir's new exit-on-error parameter
- Fabiano's removals and deprecations series
  (block migration and non-multifd compression removed)
- Peter's documentation fix for HMP migrate command

v2:
- updated Peter's documentation fix.

# -----BEGIN PGP SIGNATURE-----
#
# iQJEBAABCAAuFiEEqhtIsKIjJqWkw2TPx5jcdBvsMZ0FAmY7934QHGZhcm9zYXNA
# c3VzZS5kZQAKCRDHmNx0G+wxnXynEADHjRa7HqwuYPhft3wGgLiFbCyQNFpNrjM9
# prQSiLlYt9gRlE4c9ZavCxR28xtOrK2oFhCnLMXaIEkct6JuylfiwCPwPuxNQP9+
# EZirECf1yKkyt+RV/LfIx3R/prJgoH5XWhpna+WIBFFo2qSorHTAzjb5dKYZDjkB
# EjfN8R9goVH6aCPd4SyiCUUNxuR6/0si9AxfhUgUvUXyLZmE1ztZEoWI02FCYzVj
# kKDdVK2+Z1Rlv88tyY4/E6z4pwYLWx5EiXSFv0NXIpTdyO3dM+jeAHxcN7KmQ1+5
# GvX0n+mFYOzRIbRfAnhSZbkez/nuPcbJ76phzSYDs8f/7YtOpuOFKFw7yuGrl5N5
# ZqXo5MOOGliF2wozTjacsOrUhB+MbSb0iA71T7aAdBC2s4H9+XIWfoN/OZfsBhAW
# r2i1gSytVLQqsip7A0CFF+DqeSse9QHHlH8vfb8NUn1Tp0o2QfsX+/7LHlvl/2eJ
# EP/zmjD6c/8vjB3fTKZr52h2lEO/36xmX+OtZpep3EBvvl1BY1LP4nBNOW1vQM/b
# fzcq+agaikwS5gI2QSOC9HJ3aX6q416+wZEm3rQ8XRGSPDFfLPKM/GPPfWdj6ngb
# +e3EZPrs+3dOeH1kly5xVMGXGUof+VVBmVwdv4C+XNMM8fRZOxoqd0SD8dz/vOC7
# nSGztXUPqw==
# =5T+K
# -----END PGP SIGNATURE-----
# gpg: Signature made Thu 09 May 2024 12:06:54 AM CEST
# gpg:                using RSA key AA1B48B0A22326A5A4C364CFC798DC741BEC319D
# gpg:                issuer "farosas@suse.de"
# gpg: Good signature from "Fabiano Rosas <farosas@suse.de>" [unknown]
# gpg:                 aka "Fabiano Almeida Rosas <fabiano.rosas@suse.com>" [unknown]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: AA1B 48B0 A223 26A5 A4C3  64CF C798 DC74 1BEC 319D

* tag 'migration-20240508-pull-request' of https://gitlab.com/farosas/qemu:
  hmp/migration: Fix "migrate" command's documentation
  migration: Deprecate fd: for file migration
  migration: Remove non-multifd compression
  migration: Remove block migration
  migration: Remove 'blk/-b' option from migrate commands
  migration: Remove 'inc' option from migrate command
  migration: Remove 'skipped' field from MigrationStats
  qapi: introduce exit-on-error parameter for migrate-incoming
  migration: process_incoming_migration_co(): rework error reporting
  migration: process_incoming_migration_co(): fix reporting s->error
  migration: process_incoming_migration_co(): complete cleanup on failure
  migration: move trace-point from migrate_fd_error to migrate_set_error
  migration/ram.c: API Conversion qemu_mutex_lock(), and qemu_mutex_unlock() to WITH_QEMU_LOCK_GUARD macro

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2024-05-09 10:11:09 +02:00
commit a016dd5005
34 changed files with 209 additions and 3035 deletions

View File

@ -342,7 +342,7 @@ build-tcg-disabled:
- cd tests/qemu-iotests/ - cd tests/qemu-iotests/
- ./check -raw 001 002 003 004 005 008 009 010 011 012 021 025 032 033 048 - ./check -raw 001 002 003 004 005 008 009 010 011 012 021 025 032 033 048
052 063 077 086 101 104 106 113 148 150 151 152 157 159 160 163 052 063 077 086 101 104 106 113 148 150 151 152 157 159 160 163
170 171 183 184 192 194 208 221 226 227 236 253 277 image-fleecing 170 171 184 192 194 208 221 226 227 236 253 277 image-fleecing
- ./check -qcow2 028 051 056 057 058 065 068 082 085 091 095 096 102 122 - ./check -qcow2 028 051 056 057 058 065 068 082 085 091 095 096 102 122
124 132 139 142 144 145 151 152 155 157 165 194 196 200 202 124 132 139 142 144 145 151 152 155 157 165 194 196 200 202
208 209 216 218 227 234 246 247 248 250 254 255 257 258 208 209 216 218 227 234 246 247 248 250 254 255 257 258

View File

@ -2870,7 +2870,6 @@ F: util/aio-*.h
F: util/defer-call.c F: util/defer-call.c
F: util/fdmon-*.c F: util/fdmon-*.c
F: block/io.c F: block/io.c
F: migration/block*
F: include/block/aio.h F: include/block/aio.h
F: include/block/aio-wait.h F: include/block/aio-wait.h
F: include/qemu/defer-call.h F: include/qemu/defer-call.h

View File

@ -485,44 +485,13 @@ option).
Migration Migration
--------- ---------
``skipped`` MigrationStats field (since 8.1) ``fd:`` URI when used for file migration (since 9.1)
'''''''''''''''''''''''''''''''''''''''''''' ''''''''''''''''''''''''''''''''''''''''''''''''''''
``skipped`` field in Migration stats has been deprecated. It hasn't The ``fd:`` URI can currently provide a file descriptor that
been used for more than 10 years. references either a socket or a plain file. These are two different
types of migration. In order to reduce ambiguity, the ``fd:`` URI
``inc`` migrate command option (since 8.2) usage of providing a file descriptor to a plain file has been
'''''''''''''''''''''''''''''''''''''''''' deprecated in favor of explicitly using the ``file:`` URI with the
file descriptor being passed as an ``fdset``. Refer to the ``add-fd``
Use blockdev-mirror with NBD instead. command documentation for details on the ``fdset`` usage.
As an intermediate step the ``inc`` functionality can be achieved by
setting the ``block-incremental`` migration parameter to ``true``.
But this parameter is also deprecated.
``blk`` migrate command option (since 8.2)
''''''''''''''''''''''''''''''''''''''''''
Use blockdev-mirror with NBD instead.
As an intermediate step the ``blk`` functionality can be achieved by
setting the ``block`` migration capability to ``true``. But this
capability is also deprecated.
block migration (since 8.2)
'''''''''''''''''''''''''''
Block migration is too inflexible. It needs to migrate all block
devices or none.
Please see "QMP invocation for live storage migration with
``blockdev-mirror`` + NBD" in docs/interop/live-block-operations.rst
for a detailed explanation.
old compression method (since 8.2)
''''''''''''''''''''''''''''''''''
Compression method fails too much. Too many races. We are going to
remove it if nobody fixes it. For starters, migration-test
compression tests are disabled because they fail randomly. If you need
compression, use multifd compression methods.

View File

@ -505,6 +505,11 @@ configurations (e.g. -smp 8,sockets=0) is removed since 9.0, users have
to ensure that all the topology members described with -smp are greater to ensure that all the topology members described with -smp are greater
than zero. than zero.
``-global migration.decompress-error-check`` (removed in 9.1)
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Removed along with the ``compression`` migration capability.
User-mode emulator command line arguments User-mode emulator command line arguments
----------------------------------------- -----------------------------------------
@ -614,6 +619,58 @@ was superseded by ``sections``.
Member ``section-size`` in the return value of ``query-sgx-capabilities`` Member ``section-size`` in the return value of ``query-sgx-capabilities``
was superseded by ``sections``. was superseded by ``sections``.
``query-migrate`` return value member ``skipped`` (removed in 9.1)
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Member ``skipped`` of the ``MigrationStats`` struct hasn't been used
for more than 10 years. Removed with no replacement.
``migrate`` command option ``inc`` (removed in 9.1)
'''''''''''''''''''''''''''''''''''''''''''''''''''
Use blockdev-mirror with NBD instead. See "QMP invocation for live
storage migration with ``blockdev-mirror`` + NBD" in
docs/interop/live-block-operations.rst for a detailed explanation.
``migrate`` command option ``blk`` (removed in 9.1)
'''''''''''''''''''''''''''''''''''''''''''''''''''
Use blockdev-mirror with NBD instead. See "QMP invocation for live
storage migration with ``blockdev-mirror`` + NBD" in
docs/interop/live-block-operations.rst for a detailed explanation.
``migrate-set-capabilities`` ``block`` option (removed in 9.1)
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Block migration has been removed. For a replacement, see "QMP
invocation for live storage migration with ``blockdev-mirror`` + NBD"
in docs/interop/live-block-operations.rst.
``migrate-set-parameter`` ``compress-level`` option (removed in 9.1)
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Use ``multifd-zlib-level`` or ``multifd-zstd-level`` instead.
``migrate-set-parameter`` ``compress-threads`` option (removed in 9.1)
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Use ``multifd-channels`` instead.
``migrate-set-parameter`` ``compress-wait-thread`` option (removed in 9.1)
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Removed with no replacement.
``migrate-set-parameter`` ``decompress-threads`` option (removed in 9.1)
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Use ``multifd-channels`` instead.
``migrate-set-capability`` ``compress`` option (removed in 9.1)
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Use ``multifd-compression`` instead.
Human Monitor Protocol (HMP) commands Human Monitor Protocol (HMP) commands
------------------------------------- -------------------------------------
@ -674,6 +731,52 @@ This command didn't produce any output already. Removed with no replacement.
The ``singlestep`` command has been replaced by the ``one-insn-per-tb`` The ``singlestep`` command has been replaced by the ``one-insn-per-tb``
command, which has the same behaviour but a less misleading name. command, which has the same behaviour but a less misleading name.
``migrate`` command ``-i`` option (removed in 9.1)
''''''''''''''''''''''''''''''''''''''''''''''''''
Use blockdev-mirror with NBD instead. See "QMP invocation for live
storage migration with ``blockdev-mirror`` + NBD" in
docs/interop/live-block-operations.rst for a detailed explanation.
``migrate`` command ``-b`` option (removed in 9.1)
''''''''''''''''''''''''''''''''''''''''''''''''''
Use blockdev-mirror with NBD instead. See "QMP invocation for live
storage migration with ``blockdev-mirror`` + NBD" in
docs/interop/live-block-operations.rst for a detailed explanation.
``migrate_set_capability`` ``block`` option (removed in 9.1)
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Block migration has been removed. For a replacement, see "QMP
invocation for live storage migration with ``blockdev-mirror`` + NBD"
in docs/interop/live-block-operations.rst.
``migrate_set_parameter`` ``compress-level`` option (removed in 9.1)
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Use ``multifd-zlib-level`` or ``multifd-zstd-level`` instead.
``migrate_set_parameter`` ``compress-threads`` option (removed in 9.1)
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Use ``multifd-channels`` instead.
``migrate_set_parameter`` ``compress-wait-thread`` option (removed in 9.1)
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Removed with no replacement.
``migrate_set_parameter`` ``decompress-threads`` option (removed in 9.1)
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Use ``multifd-channels`` instead.
``migrate_set_capability`` ``compress`` option (removed in 9.1)
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Use ``multifd-compression`` instead.
Host Architectures Host Architectures
------------------ ------------------

View File

@ -454,7 +454,7 @@ Examples of such API functions are:
Iterative device migration Iterative device migration
-------------------------- --------------------------
Some devices, such as RAM, Block storage or certain platform devices, Some devices, such as RAM or certain platform devices,
have large amounts of data that would mean that the CPUs would be have large amounts of data that would mean that the CPUs would be
paused for too long if they were sent in one section. For these paused for too long if they were sent in one section. For these
devices an *iterative* approach is taken. devices an *iterative* approach is taken.

View File

@ -909,26 +909,23 @@ ERST
{ {
.name = "migrate", .name = "migrate",
.args_type = "detach:-d,blk:-b,inc:-i,resume:-r,uri:s", .args_type = "detach:-d,resume:-r,uri:s",
.params = "[-d] [-b] [-i] [-r] uri", .params = "[-d] [-r] uri",
.help = "migrate to URI (using -d to not wait for completion)" .help = "migrate to URI (using -d to not wait for completion)"
"\n\t\t\t -b for migration without shared storage with" "\n\t\t\t -r to resume a paused postcopy migration",
" full copy of disk\n\t\t\t -i for migration without "
"shared storage with incremental copy of disk "
"(base image shared between src and destination)"
"\n\t\t\t -r to resume a paused migration",
.cmd = hmp_migrate, .cmd = hmp_migrate,
}, },
SRST SRST
``migrate [-d] [-b] [-i]`` *uri* ``migrate [-d] [-r]`` *uri*
Migrate to *uri* (using -d to not wait for completion). Migrate the VM to *uri*.
``-b`` ``-d``
for migration with full copy of disk Start the migration process, but do not wait for its completion. To
``-i`` query an ongoing migration process, use "info migrate".
for migration with incremental copy of disk (base image is shared) ``-r``
Resume a paused postcopy migration.
ERST ERST
{ {

View File

@ -192,7 +192,6 @@ GlobalProperty hw_compat_3_0[] = {};
const size_t hw_compat_3_0_len = G_N_ELEMENTS(hw_compat_3_0); const size_t hw_compat_3_0_len = G_N_ELEMENTS(hw_compat_3_0);
GlobalProperty hw_compat_2_12[] = { GlobalProperty hw_compat_2_12[] = {
{ "migration", "decompress-error-check", "off" },
{ "hda-audio", "use-timer", "false" }, { "hda-audio", "use-timer", "false" },
{ "cirrus-vga", "global-vmstate", "true" }, { "cirrus-vga", "global-vmstate", "true" },
{ "VGA", "global-vmstate", "true" }, { "VGA", "global-vmstate", "true" },

View File

@ -45,12 +45,6 @@ bool migrate_ram_is_ignored(RAMBlock *block);
/* migration/block.c */ /* migration/block.c */
#ifdef CONFIG_LIVE_BLOCK_MIGRATION
void blk_mig_init(void);
#else
static inline void blk_mig_init(void) {}
#endif
AnnounceParameters *migrate_announce_params(void); AnnounceParameters *migrate_announce_params(void);
/* migration/savevm.c */ /* migration/savevm.c */

View File

@ -2351,7 +2351,6 @@ config_host_data.set('CONFIG_DEBUG_MUTEX', get_option('debug_mutex'))
config_host_data.set('CONFIG_DEBUG_STACK_USAGE', get_option('debug_stack_usage')) config_host_data.set('CONFIG_DEBUG_STACK_USAGE', get_option('debug_stack_usage'))
config_host_data.set('CONFIG_DEBUG_TCG', get_option('debug_tcg')) config_host_data.set('CONFIG_DEBUG_TCG', get_option('debug_tcg'))
config_host_data.set('CONFIG_DEBUG_REMAP', get_option('debug_remap')) config_host_data.set('CONFIG_DEBUG_REMAP', get_option('debug_remap'))
config_host_data.set('CONFIG_LIVE_BLOCK_MIGRATION', get_option('live_block_migration').allowed())
config_host_data.set('CONFIG_QOM_CAST_DEBUG', get_option('qom_cast_debug')) config_host_data.set('CONFIG_QOM_CAST_DEBUG', get_option('qom_cast_debug'))
config_host_data.set('CONFIG_REPLICATION', get_option('replication').allowed()) config_host_data.set('CONFIG_REPLICATION', get_option('replication').allowed())
@ -4302,7 +4301,6 @@ if have_block
summary_info += {'Use block whitelist in tools': get_option('block_drv_whitelist_in_tools')} summary_info += {'Use block whitelist in tools': get_option('block_drv_whitelist_in_tools')}
summary_info += {'VirtFS (9P) support': have_virtfs} summary_info += {'VirtFS (9P) support': have_virtfs}
summary_info += {'VirtFS (9P) Proxy Helper support (deprecated)': have_virtfs_proxy_helper} summary_info += {'VirtFS (9P) Proxy Helper support (deprecated)': have_virtfs_proxy_helper}
summary_info += {'Live block migration': config_host_data.get('CONFIG_LIVE_BLOCK_MIGRATION')}
summary_info += {'replication support': config_host_data.get('CONFIG_REPLICATION')} summary_info += {'replication support': config_host_data.get('CONFIG_REPLICATION')}
summary_info += {'bochs support': get_option('bochs').allowed()} summary_info += {'bochs support': get_option('bochs').allowed()}
summary_info += {'cloop support': get_option('cloop').allowed()} summary_info += {'cloop support': get_option('cloop').allowed()}

View File

@ -314,8 +314,6 @@ option('fdt', type: 'combo', value: 'auto',
option('selinux', type: 'feature', value: 'auto', option('selinux', type: 'feature', value: 'auto',
description: 'SELinux support in qemu-nbd') description: 'SELinux support in qemu-nbd')
option('live_block_migration', type: 'feature', value: 'auto',
description: 'block migration in the main migration stream')
option('replication', type: 'feature', value: 'auto', option('replication', type: 'feature', value: 'auto',
description: 'replication support') description: 'replication support')
option('colo_proxy', type: 'feature', value: 'auto', option('colo_proxy', type: 'feature', value: 'auto',

File diff suppressed because it is too large Load Diff

View File

@ -1,52 +0,0 @@
/*
* QEMU live block migration
*
* Copyright IBM, Corp. 2009
*
* Authors:
* Liran Schour <lirans@il.ibm.com>
*
* This work is licensed under the terms of the GNU GPL, version 2. See
* the COPYING file in the top-level directory.
*
*/
#ifndef MIGRATION_BLOCK_H
#define MIGRATION_BLOCK_H
#ifdef CONFIG_LIVE_BLOCK_MIGRATION
int blk_mig_active(void);
int blk_mig_bulk_active(void);
uint64_t blk_mig_bytes_transferred(void);
uint64_t blk_mig_bytes_remaining(void);
uint64_t blk_mig_bytes_total(void);
#else
static inline int blk_mig_active(void)
{
return false;
}
static inline int blk_mig_bulk_active(void)
{
return false;
}
static inline uint64_t blk_mig_bytes_transferred(void)
{
return 0;
}
static inline uint64_t blk_mig_bytes_remaining(void)
{
return 0;
}
static inline uint64_t blk_mig_bytes_total(void)
{
return 0;
}
#endif /* CONFIG_LIVE_BLOCK_MIGRATION */
void migrate_set_block_enabled(bool value, Error **errp);
#endif /* MIGRATION_BLOCK_H */

View File

@ -18,7 +18,6 @@
#include "qemu-file.h" #include "qemu-file.h"
#include "savevm.h" #include "savevm.h"
#include "migration/colo.h" #include "migration/colo.h"
#include "block.h"
#include "io/channel-buffer.h" #include "io/channel-buffer.h"
#include "trace.h" #include "trace.h"
#include "qemu/error-report.h" #include "qemu/error-report.h"

View File

@ -20,6 +20,8 @@
#include "file.h" #include "file.h"
#include "migration.h" #include "migration.h"
#include "monitor/monitor.h" #include "monitor/monitor.h"
#include "qemu/error-report.h"
#include "qemu/sockets.h"
#include "io/channel-util.h" #include "io/channel-util.h"
#include "trace.h" #include "trace.h"
@ -32,6 +34,11 @@ void fd_start_outgoing_migration(MigrationState *s, const char *fdname, Error **
return; return;
} }
if (!fd_is_socket(fd)) {
warn_report("fd: migration to a file is deprecated."
" Use file: instead.");
}
trace_migration_fd_outgoing(fd); trace_migration_fd_outgoing(fd);
ioc = qio_channel_new_fd(fd, errp); ioc = qio_channel_new_fd(fd, errp);
if (!ioc) { if (!ioc) {
@ -61,6 +68,11 @@ void fd_start_incoming_migration(const char *fdname, Error **errp)
return; return;
} }
if (!fd_is_socket(fd)) {
warn_report("fd: migration to a file is deprecated."
" Use file: instead.");
}
trace_migration_fd_incoming(fd); trace_migration_fd_incoming(fd);
ioc = qio_channel_new_fd(fd, errp); ioc = qio_channel_new_fd(fd, errp);

View File

@ -23,7 +23,6 @@ system_ss.add(files(
'multifd.c', 'multifd.c',
'multifd-zlib.c', 'multifd-zlib.c',
'multifd-zero-page.c', 'multifd-zero-page.c',
'ram-compress.c',
'options.c', 'options.c',
'postcopy-ram.c', 'postcopy-ram.c',
'savevm.c', 'savevm.c',
@ -39,9 +38,6 @@ else
endif endif
system_ss.add(when: rdma, if_true: files('rdma.c')) system_ss.add(when: rdma, if_true: files('rdma.c'))
if get_option('live_block_migration').allowed()
system_ss.add(files('block.c'))
endif
system_ss.add(when: zstd, if_true: files('multifd-zstd.c')) system_ss.add(when: zstd, if_true: files('multifd-zstd.c'))
specific_ss.add(when: 'CONFIG_SYSTEM_ONLY', specific_ss.add(when: 'CONFIG_SYSTEM_ONLY',

View File

@ -46,8 +46,6 @@ static void migration_global_dump(Monitor *mon)
ms->send_configuration ? "on" : "off"); ms->send_configuration ? "on" : "off");
monitor_printf(mon, "send-section-footer: %s\n", monitor_printf(mon, "send-section-footer: %s\n",
ms->send_section_footer ? "on" : "off"); ms->send_section_footer ? "on" : "off");
monitor_printf(mon, "decompress-error-check: %s\n",
ms->decompress_error_check ? "on" : "off");
monitor_printf(mon, "clear-bitmap-shift: %u\n", monitor_printf(mon, "clear-bitmap-shift: %u\n",
ms->clear_bitmap_shift); ms->clear_bitmap_shift);
} }
@ -105,8 +103,6 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict)
info->ram->total >> 10); info->ram->total >> 10);
monitor_printf(mon, "duplicate: %" PRIu64 " pages\n", monitor_printf(mon, "duplicate: %" PRIu64 " pages\n",
info->ram->duplicate); info->ram->duplicate);
monitor_printf(mon, "skipped: %" PRIu64 " pages\n",
info->ram->skipped);
monitor_printf(mon, "normal: %" PRIu64 " pages\n", monitor_printf(mon, "normal: %" PRIu64 " pages\n",
info->ram->normal); info->ram->normal);
monitor_printf(mon, "normal bytes: %" PRIu64 " kbytes\n", monitor_printf(mon, "normal bytes: %" PRIu64 " kbytes\n",
@ -147,15 +143,6 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict)
} }
} }
if (info->disk) {
monitor_printf(mon, "transferred disk: %" PRIu64 " kbytes\n",
info->disk->transferred >> 10);
monitor_printf(mon, "remaining disk: %" PRIu64 " kbytes\n",
info->disk->remaining >> 10);
monitor_printf(mon, "total disk: %" PRIu64 " kbytes\n",
info->disk->total >> 10);
}
if (info->xbzrle_cache) { if (info->xbzrle_cache) {
monitor_printf(mon, "cache size: %" PRIu64 " bytes\n", monitor_printf(mon, "cache size: %" PRIu64 " bytes\n",
info->xbzrle_cache->cache_size); info->xbzrle_cache->cache_size);
@ -173,19 +160,6 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict)
info->xbzrle_cache->overflow); info->xbzrle_cache->overflow);
} }
if (info->compression) {
monitor_printf(mon, "compression pages: %" PRIu64 " pages\n",
info->compression->pages);
monitor_printf(mon, "compression busy: %" PRIu64 "\n",
info->compression->busy);
monitor_printf(mon, "compression busy rate: %0.2f\n",
info->compression->busy_rate);
monitor_printf(mon, "compressed size: %" PRIu64 " kbytes\n",
info->compression->compressed_size >> 10);
monitor_printf(mon, "compression rate: %0.2f\n",
info->compression->compression_rate);
}
if (info->has_cpu_throttle_percentage) { if (info->has_cpu_throttle_percentage) {
monitor_printf(mon, "cpu throttle percentage: %" PRIu64 "\n", monitor_printf(mon, "cpu throttle percentage: %" PRIu64 "\n",
info->cpu_throttle_percentage); info->cpu_throttle_percentage);
@ -274,22 +248,6 @@ void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict)
monitor_printf(mon, "%s: %" PRIu64 " ms\n", monitor_printf(mon, "%s: %" PRIu64 " ms\n",
MigrationParameter_str(MIGRATION_PARAMETER_ANNOUNCE_STEP), MigrationParameter_str(MIGRATION_PARAMETER_ANNOUNCE_STEP),
params->announce_step); params->announce_step);
assert(params->has_compress_level);
monitor_printf(mon, "%s: %u\n",
MigrationParameter_str(MIGRATION_PARAMETER_COMPRESS_LEVEL),
params->compress_level);
assert(params->has_compress_threads);
monitor_printf(mon, "%s: %u\n",
MigrationParameter_str(MIGRATION_PARAMETER_COMPRESS_THREADS),
params->compress_threads);
assert(params->has_compress_wait_thread);
monitor_printf(mon, "%s: %s\n",
MigrationParameter_str(MIGRATION_PARAMETER_COMPRESS_WAIT_THREAD),
params->compress_wait_thread ? "on" : "off");
assert(params->has_decompress_threads);
monitor_printf(mon, "%s: %u\n",
MigrationParameter_str(MIGRATION_PARAMETER_DECOMPRESS_THREADS),
params->decompress_threads);
assert(params->has_throttle_trigger_threshold); assert(params->has_throttle_trigger_threshold);
monitor_printf(mon, "%s: %u\n", monitor_printf(mon, "%s: %u\n",
MigrationParameter_str(MIGRATION_PARAMETER_THROTTLE_TRIGGER_THRESHOLD), MigrationParameter_str(MIGRATION_PARAMETER_THROTTLE_TRIGGER_THRESHOLD),
@ -334,10 +292,6 @@ void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict)
monitor_printf(mon, "%s: %u ms\n", monitor_printf(mon, "%s: %u ms\n",
MigrationParameter_str(MIGRATION_PARAMETER_X_CHECKPOINT_DELAY), MigrationParameter_str(MIGRATION_PARAMETER_X_CHECKPOINT_DELAY),
params->x_checkpoint_delay); params->x_checkpoint_delay);
assert(params->has_block_incremental);
monitor_printf(mon, "%s: %s\n",
MigrationParameter_str(MIGRATION_PARAMETER_BLOCK_INCREMENTAL),
params->block_incremental ? "on" : "off");
monitor_printf(mon, "%s: %u\n", monitor_printf(mon, "%s: %u\n",
MigrationParameter_str(MIGRATION_PARAMETER_MULTIFD_CHANNELS), MigrationParameter_str(MIGRATION_PARAMETER_MULTIFD_CHANNELS),
params->multifd_channels); params->multifd_channels);
@ -466,7 +420,7 @@ void hmp_migrate_incoming(Monitor *mon, const QDict *qdict)
} }
QAPI_LIST_PREPEND(caps, g_steal_pointer(&channel)); QAPI_LIST_PREPEND(caps, g_steal_pointer(&channel));
qmp_migrate_incoming(NULL, true, caps, &err); qmp_migrate_incoming(NULL, true, caps, true, false, &err);
qapi_free_MigrationChannelList(caps); qapi_free_MigrationChannelList(caps);
end: end:
@ -535,22 +489,6 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
} }
switch (val) { switch (val) {
case MIGRATION_PARAMETER_COMPRESS_LEVEL:
p->has_compress_level = true;
visit_type_uint8(v, param, &p->compress_level, &err);
break;
case MIGRATION_PARAMETER_COMPRESS_THREADS:
p->has_compress_threads = true;
visit_type_uint8(v, param, &p->compress_threads, &err);
break;
case MIGRATION_PARAMETER_COMPRESS_WAIT_THREAD:
p->has_compress_wait_thread = true;
visit_type_bool(v, param, &p->compress_wait_thread, &err);
break;
case MIGRATION_PARAMETER_DECOMPRESS_THREADS:
p->has_decompress_threads = true;
visit_type_uint8(v, param, &p->decompress_threads, &err);
break;
case MIGRATION_PARAMETER_THROTTLE_TRIGGER_THRESHOLD: case MIGRATION_PARAMETER_THROTTLE_TRIGGER_THRESHOLD:
p->has_throttle_trigger_threshold = true; p->has_throttle_trigger_threshold = true;
visit_type_uint8(v, param, &p->throttle_trigger_threshold, &err); visit_type_uint8(v, param, &p->throttle_trigger_threshold, &err);
@ -618,10 +556,6 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
p->has_x_checkpoint_delay = true; p->has_x_checkpoint_delay = true;
visit_type_uint32(v, param, &p->x_checkpoint_delay, &err); visit_type_uint32(v, param, &p->x_checkpoint_delay, &err);
break; break;
case MIGRATION_PARAMETER_BLOCK_INCREMENTAL:
p->has_block_incremental = true;
visit_type_bool(v, param, &p->block_incremental, &err);
break;
case MIGRATION_PARAMETER_MULTIFD_CHANNELS: case MIGRATION_PARAMETER_MULTIFD_CHANNELS:
p->has_multifd_channels = true; p->has_multifd_channels = true;
visit_type_uint8(v, param, &p->multifd_channels, &err); visit_type_uint8(v, param, &p->multifd_channels, &err);
@ -736,24 +670,8 @@ static void hmp_migrate_status_cb(void *opaque)
info = qmp_query_migrate(NULL); info = qmp_query_migrate(NULL);
if (!info->has_status || info->status == MIGRATION_STATUS_ACTIVE || if (!info->has_status || info->status == MIGRATION_STATUS_ACTIVE ||
info->status == MIGRATION_STATUS_SETUP) { info->status == MIGRATION_STATUS_SETUP) {
if (info->disk) {
int progress;
if (info->disk->remaining) {
progress = info->disk->transferred * 100 / info->disk->total;
} else {
progress = 100;
}
monitor_printf(status->mon, "Completed %d %%\r", progress);
monitor_flush(status->mon);
}
timer_mod(status->timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 1000); timer_mod(status->timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 1000);
} else { } else {
if (migrate_block()) {
monitor_printf(status->mon, "\n");
}
if (info->error_desc) { if (info->error_desc) {
error_report("%s", info->error_desc); error_report("%s", info->error_desc);
} }
@ -768,32 +686,19 @@ static void hmp_migrate_status_cb(void *opaque)
void hmp_migrate(Monitor *mon, const QDict *qdict) void hmp_migrate(Monitor *mon, const QDict *qdict)
{ {
bool detach = qdict_get_try_bool(qdict, "detach", false); bool detach = qdict_get_try_bool(qdict, "detach", false);
bool blk = qdict_get_try_bool(qdict, "blk", false);
bool inc = qdict_get_try_bool(qdict, "inc", false);
bool resume = qdict_get_try_bool(qdict, "resume", false); bool resume = qdict_get_try_bool(qdict, "resume", false);
const char *uri = qdict_get_str(qdict, "uri"); const char *uri = qdict_get_str(qdict, "uri");
Error *err = NULL; Error *err = NULL;
g_autoptr(MigrationChannelList) caps = NULL; g_autoptr(MigrationChannelList) caps = NULL;
g_autoptr(MigrationChannel) channel = NULL; g_autoptr(MigrationChannel) channel = NULL;
if (inc) {
warn_report("option '-i' is deprecated;"
" use blockdev-mirror with NBD instead");
}
if (blk) {
warn_report("option '-b' is deprecated;"
" use blockdev-mirror with NBD instead");
}
if (!migrate_uri_parse(uri, &channel, &err)) { if (!migrate_uri_parse(uri, &channel, &err)) {
hmp_handle_error(mon, err); hmp_handle_error(mon, err);
return; return;
} }
QAPI_LIST_PREPEND(caps, g_steal_pointer(&channel)); QAPI_LIST_PREPEND(caps, g_steal_pointer(&channel));
qmp_migrate(NULL, true, caps, !!blk, blk, !!inc, inc, qmp_migrate(NULL, true, caps, false, false, true, resume, &err);
false, false, true, resume, &err);
if (hmp_handle_error(mon, err)) { if (hmp_handle_error(mon, err)) {
return; return;
} }

View File

@ -27,7 +27,6 @@
#include "sysemu/cpu-throttle.h" #include "sysemu/cpu-throttle.h"
#include "rdma.h" #include "rdma.h"
#include "ram.h" #include "ram.h"
#include "ram-compress.h"
#include "migration/global_state.h" #include "migration/global_state.h"
#include "migration/misc.h" #include "migration/misc.h"
#include "migration.h" #include "migration.h"
@ -46,7 +45,6 @@
#include "qapi/qmp/qerror.h" #include "qapi/qmp/qerror.h"
#include "qapi/qmp/qnull.h" #include "qapi/qmp/qnull.h"
#include "qemu/rcu.h" #include "qemu/rcu.h"
#include "block.h"
#include "postcopy-ram.h" #include "postcopy-ram.h"
#include "qemu/thread.h" #include "qemu/thread.h"
#include "trace.h" #include "trace.h"
@ -72,6 +70,8 @@
#define NOTIFIER_ELEM_INIT(array, elem) \ #define NOTIFIER_ELEM_INIT(array, elem) \
[elem] = NOTIFIER_WITH_RETURN_LIST_INITIALIZER((array)[elem]) [elem] = NOTIFIER_WITH_RETURN_LIST_INITIALIZER((array)[elem])
#define INMIGRATE_DEFAULT_EXIT_ON_ERROR true
static NotifierWithReturnList migration_state_notifiers[] = { static NotifierWithReturnList migration_state_notifiers[] = {
NOTIFIER_ELEM_INIT(migration_state_notifiers, MIG_MODE_NORMAL), NOTIFIER_ELEM_INIT(migration_state_notifiers, MIG_MODE_NORMAL),
NOTIFIER_ELEM_INIT(migration_state_notifiers, MIG_MODE_CPR_REBOOT), NOTIFIER_ELEM_INIT(migration_state_notifiers, MIG_MODE_CPR_REBOOT),
@ -234,9 +234,10 @@ void migration_object_init(void)
qemu_cond_init(&current_incoming->page_request_cond); qemu_cond_init(&current_incoming->page_request_cond);
current_incoming->page_requested = g_tree_new(page_request_addr_cmp); current_incoming->page_requested = g_tree_new(page_request_addr_cmp);
current_incoming->exit_on_error = INMIGRATE_DEFAULT_EXIT_ON_ERROR;
migration_object_check(current_migration, &error_fatal); migration_object_check(current_migration, &error_fatal);
blk_mig_init();
ram_mig_init(); ram_mig_init();
dirty_bitmap_mig_init(); dirty_bitmap_mig_init();
} }
@ -354,7 +355,6 @@ void migration_incoming_state_destroy(void)
struct MigrationIncomingState *mis = migration_incoming_get_current(); struct MigrationIncomingState *mis = migration_incoming_get_current();
multifd_recv_cleanup(); multifd_recv_cleanup();
compress_threads_load_cleanup();
if (mis->to_src_file) { if (mis->to_src_file) {
/* Tell source that we are done */ /* Tell source that we are done */
@ -647,10 +647,6 @@ static void qemu_start_incoming_migration(const char *uri, bool has_channels,
} }
#ifdef CONFIG_RDMA #ifdef CONFIG_RDMA
} else if (addr->transport == MIGRATION_ADDRESS_TYPE_RDMA) { } else if (addr->transport == MIGRATION_ADDRESS_TYPE_RDMA) {
if (migrate_compress()) {
error_setg(errp, "RDMA and compression can't be used together");
return;
}
if (migrate_xbzrle()) { if (migrate_xbzrle()) {
error_setg(errp, "RDMA and XBZRLE can't be used together"); error_setg(errp, "RDMA and XBZRLE can't be used together");
return; return;
@ -735,17 +731,14 @@ static void process_incoming_migration_bh(void *opaque)
static void coroutine_fn static void coroutine_fn
process_incoming_migration_co(void *opaque) process_incoming_migration_co(void *opaque)
{ {
MigrationState *s = migrate_get_current();
MigrationIncomingState *mis = migration_incoming_get_current(); MigrationIncomingState *mis = migration_incoming_get_current();
PostcopyState ps; PostcopyState ps;
int ret; int ret;
Error *local_err = NULL;
assert(mis->from_src_file); assert(mis->from_src_file);
if (compress_threads_load_setup(mis->from_src_file)) {
error_report("Failed to setup decompress threads");
goto fail;
}
mis->largest_page_size = qemu_ram_pagesize_largest(); mis->largest_page_size = qemu_ram_pagesize_largest();
postcopy_state_set(POSTCOPY_INCOMING_NONE); postcopy_state_set(POSTCOPY_INCOMING_NONE);
migrate_set_state(&mis->state, MIGRATION_STATUS_SETUP, migrate_set_state(&mis->state, MIGRATION_STATUS_SETUP,
@ -779,18 +772,12 @@ process_incoming_migration_co(void *opaque)
} }
if (ret < 0) { if (ret < 0) {
MigrationState *s = migrate_get_current(); error_setg(&local_err, "load of migration failed: %s", strerror(-ret));
if (migrate_has_error(s)) {
WITH_QEMU_LOCK_GUARD(&s->error_mutex) {
error_report_err(s->error);
}
}
error_report("load of migration failed: %s", strerror(-ret));
goto fail; goto fail;
} }
if (colo_incoming_co() < 0) { if (colo_incoming_co() < 0) {
error_setg(&local_err, "colo incoming failed");
goto fail; goto fail;
} }
@ -799,13 +786,20 @@ process_incoming_migration_co(void *opaque)
fail: fail:
migrate_set_state(&mis->state, MIGRATION_STATUS_ACTIVE, migrate_set_state(&mis->state, MIGRATION_STATUS_ACTIVE,
MIGRATION_STATUS_FAILED); MIGRATION_STATUS_FAILED);
qemu_fclose(mis->from_src_file); migrate_set_error(s, local_err);
error_free(local_err);
multifd_recv_cleanup(); migration_incoming_state_destroy();
compress_threads_load_cleanup();
if (mis->exit_on_error) {
WITH_QEMU_LOCK_GUARD(&s->error_mutex) {
error_report_err(s->error);
s->error = NULL;
}
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
}
/** /**
* migration_incoming_setup: Setup incoming migration * migration_incoming_setup: Setup incoming migration
@ -1149,8 +1143,6 @@ static void populate_ram_info(MigrationInfo *info, MigrationState *s)
info->ram->transferred = migration_transferred_bytes(); info->ram->transferred = migration_transferred_bytes();
info->ram->total = ram_bytes_total(); info->ram->total = ram_bytes_total();
info->ram->duplicate = stat64_get(&mig_stats.zero_pages); info->ram->duplicate = stat64_get(&mig_stats.zero_pages);
/* legacy value. It is not used anymore */
info->ram->skipped = 0;
info->ram->normal = stat64_get(&mig_stats.normal_pages); info->ram->normal = stat64_get(&mig_stats.normal_pages);
info->ram->normal_bytes = info->ram->normal * page_size; info->ram->normal_bytes = info->ram->normal * page_size;
info->ram->mbps = s->mbps; info->ram->mbps = s->mbps;
@ -1178,8 +1170,6 @@ static void populate_ram_info(MigrationInfo *info, MigrationState *s)
info->xbzrle_cache->overflow = xbzrle_counters.overflow; info->xbzrle_cache->overflow = xbzrle_counters.overflow;
} }
populate_compress(info);
if (cpu_throttle_active()) { if (cpu_throttle_active()) {
info->has_cpu_throttle_percentage = true; info->has_cpu_throttle_percentage = true;
info->cpu_throttle_percentage = cpu_throttle_get_percentage(); info->cpu_throttle_percentage = cpu_throttle_get_percentage();
@ -1201,16 +1191,6 @@ static void populate_ram_info(MigrationInfo *info, MigrationState *s)
} }
} }
static void populate_disk_info(MigrationInfo *info)
{
if (blk_mig_active()) {
info->disk = g_malloc0(sizeof(*info->disk));
info->disk->transferred = blk_mig_bytes_transferred();
info->disk->remaining = blk_mig_bytes_remaining();
info->disk->total = blk_mig_bytes_total();
}
}
static void fill_source_migration_info(MigrationInfo *info) static void fill_source_migration_info(MigrationInfo *info)
{ {
MigrationState *s = migrate_get_current(); MigrationState *s = migrate_get_current();
@ -1253,7 +1233,6 @@ static void fill_source_migration_info(MigrationInfo *info)
/* TODO add some postcopy stats */ /* TODO add some postcopy stats */
populate_time_info(info, s); populate_time_info(info, s);
populate_ram_info(info, s); populate_ram_info(info, s);
populate_disk_info(info);
migration_populate_vfio_info(info); migration_populate_vfio_info(info);
break; break;
case MIGRATION_STATUS_COLO: case MIGRATION_STATUS_COLO:
@ -1313,6 +1292,15 @@ static void fill_destination_migration_info(MigrationInfo *info)
break; break;
} }
info->status = mis->state; info->status = mis->state;
if (!info->error_desc) {
MigrationState *s = migrate_get_current();
QEMU_LOCK_GUARD(&s->error_mutex);
if (s->error) {
info->error_desc = g_strdup(error_get_pretty(s->error));
}
}
} }
MigrationInfo *qmp_query_migrate(Error **errp) MigrationInfo *qmp_query_migrate(Error **errp)
@ -1409,7 +1397,6 @@ static void migrate_fd_cleanup(MigrationState *s)
type = migration_has_failed(s) ? MIG_EVENT_PRECOPY_FAILED : type = migration_has_failed(s) ? MIG_EVENT_PRECOPY_FAILED :
MIG_EVENT_PRECOPY_DONE; MIG_EVENT_PRECOPY_DONE;
migration_call_notifiers(s, type, NULL); migration_call_notifiers(s, type, NULL);
block_cleanup_parameters();
yank_unregister_instance(MIGRATION_YANK_INSTANCE); yank_unregister_instance(MIGRATION_YANK_INSTANCE);
} }
@ -1421,6 +1408,9 @@ static void migrate_fd_cleanup_bh(void *opaque)
void migrate_set_error(MigrationState *s, const Error *error) void migrate_set_error(MigrationState *s, const Error *error)
{ {
QEMU_LOCK_GUARD(&s->error_mutex); QEMU_LOCK_GUARD(&s->error_mutex);
trace_migrate_error(error_get_pretty(error));
if (!s->error) { if (!s->error) {
s->error = error_copy(error); s->error = error_copy(error);
} }
@ -1444,7 +1434,6 @@ static void migrate_error_free(MigrationState *s)
static void migrate_fd_error(MigrationState *s, const Error *error) static void migrate_fd_error(MigrationState *s, const Error *error)
{ {
trace_migrate_fd_error(error_get_pretty(error));
assert(s->to_dst_file == NULL); assert(s->to_dst_file == NULL);
migrate_set_state(&s->state, MIGRATION_STATUS_SETUP, migrate_set_state(&s->state, MIGRATION_STATUS_SETUP,
MIGRATION_STATUS_FAILED); MIGRATION_STATUS_FAILED);
@ -1794,10 +1783,13 @@ void migrate_del_blocker(Error **reasonp)
} }
void qmp_migrate_incoming(const char *uri, bool has_channels, void qmp_migrate_incoming(const char *uri, bool has_channels,
MigrationChannelList *channels, Error **errp) MigrationChannelList *channels,
bool has_exit_on_error, bool exit_on_error,
Error **errp)
{ {
Error *local_err = NULL; Error *local_err = NULL;
static bool once = true; static bool once = true;
MigrationIncomingState *mis = migration_incoming_get_current();
if (!once) { if (!once) {
error_setg(errp, "The incoming migration has already been started"); error_setg(errp, "The incoming migration has already been started");
@ -1812,6 +1804,9 @@ void qmp_migrate_incoming(const char *uri, bool has_channels,
return; return;
} }
mis->exit_on_error =
has_exit_on_error ? exit_on_error : INMIGRATE_DEFAULT_EXIT_ON_ERROR;
qemu_start_incoming_migration(uri, has_channels, channels, &local_err); qemu_start_incoming_migration(uri, has_channels, channels, &local_err);
if (local_err) { if (local_err) {
@ -1913,19 +1908,8 @@ bool migration_is_blocked(Error **errp)
} }
/* Returns true if continue to migrate, or false if error detected */ /* Returns true if continue to migrate, or false if error detected */
static bool migrate_prepare(MigrationState *s, bool blk, bool blk_inc, static bool migrate_prepare(MigrationState *s, bool resume, Error **errp)
bool resume, Error **errp)
{ {
if (blk_inc) {
warn_report("parameter 'inc' is deprecated;"
" use blockdev-mirror with NBD instead");
}
if (blk) {
warn_report("parameter 'blk' is deprecated;"
" use blockdev-mirror with NBD instead");
}
if (resume) { if (resume) {
if (s->state != MIGRATION_STATUS_POSTCOPY_PAUSED) { if (s->state != MIGRATION_STATUS_POSTCOPY_PAUSED) {
error_setg(errp, "Cannot resume if there is no " error_setg(errp, "Cannot resume if there is no "
@ -2010,26 +1994,6 @@ static bool migrate_prepare(MigrationState *s, bool blk, bool blk_inc,
} }
} }
if (blk || blk_inc) {
if (migrate_colo()) {
error_setg(errp, "No disk migration is required in COLO mode");
return false;
}
if (migrate_block() || migrate_block_incremental()) {
error_setg(errp, "Command options are incompatible with "
"current migration capabilities");
return false;
}
if (!migrate_cap_set(MIGRATION_CAPABILITY_BLOCK, true, errp)) {
return false;
}
s->must_remove_block_options = true;
}
if (blk_inc) {
migrate_set_block_incremental(true);
}
if (migrate_init(s, errp)) { if (migrate_init(s, errp)) {
return false; return false;
} }
@ -2038,8 +2002,7 @@ static bool migrate_prepare(MigrationState *s, bool blk, bool blk_inc,
} }
void qmp_migrate(const char *uri, bool has_channels, void qmp_migrate(const char *uri, bool has_channels,
MigrationChannelList *channels, bool has_blk, bool blk, MigrationChannelList *channels, bool has_detach, bool detach,
bool has_inc, bool inc, bool has_detach, bool detach,
bool has_resume, bool resume, Error **errp) bool has_resume, bool resume, Error **errp)
{ {
bool resume_requested; bool resume_requested;
@ -2079,8 +2042,7 @@ void qmp_migrate(const char *uri, bool has_channels,
} }
resume_requested = has_resume && resume; resume_requested = has_resume && resume;
if (!migrate_prepare(s, has_blk && blk, has_inc && inc, if (!migrate_prepare(s, resume_requested, errp)) {
resume_requested, errp)) {
/* Error detected, put into errp */ /* Error detected, put into errp */
return; return;
} }
@ -2113,7 +2075,6 @@ void qmp_migrate(const char *uri, bool has_channels,
"a valid migration protocol"); "a valid migration protocol");
migrate_set_state(&s->state, MIGRATION_STATUS_SETUP, migrate_set_state(&s->state, MIGRATION_STATUS_SETUP,
MIGRATION_STATUS_FAILED); MIGRATION_STATUS_FAILED);
block_cleanup_parameters();
} }
if (local_err) { if (local_err) {

View File

@ -227,6 +227,9 @@ struct MigrationIncomingState {
* is needed as this field is updated serially. * is needed as this field is updated serially.
*/ */
unsigned int switchover_ack_pending_num; unsigned int switchover_ack_pending_num;
/* Do exit on incoming migration failure */
bool exit_on_error;
}; };
MigrationIncomingState *migration_incoming_get_current(void); MigrationIncomingState *migration_incoming_get_current(void);
@ -376,10 +379,6 @@ struct MigrationState {
/* mutex to protect errp */ /* mutex to protect errp */
QemuMutex error_mutex; QemuMutex error_mutex;
/* Do we have to clean up -b/-i from old migrate parameters */
/* This feature is deprecated and will be removed */
bool must_remove_block_options;
/* /*
* Global switch on whether we need to store the global state * Global switch on whether we need to store the global state
* during migration. * during migration.
@ -393,13 +392,6 @@ struct MigrationState {
/* Needed by postcopy-pause state */ /* Needed by postcopy-pause state */
QemuSemaphore postcopy_pause_sem; QemuSemaphore postcopy_pause_sem;
/*
* Whether we abort the migration if decompression errors are
* detected at the destination. It is left at false for qemu
* older than 3.0, since only newer qemu sends streams that
* do not trigger spurious decompression errors.
*/
bool decompress_error_check;
/* /*
* This variable only affects behavior when postcopy preempt mode is * This variable only affects behavior when postcopy preempt mode is
* enabled. * enabled.

View File

@ -40,13 +40,6 @@
* for sending the last part */ * for sending the last part */
#define DEFAULT_MIGRATE_SET_DOWNTIME 300 #define DEFAULT_MIGRATE_SET_DOWNTIME 300
/* Default compression thread count */
#define DEFAULT_MIGRATE_COMPRESS_THREAD_COUNT 8
/* Default decompression thread count, usually decompression is at
* least 4 times as fast as compression.*/
#define DEFAULT_MIGRATE_DECOMPRESS_THREAD_COUNT 2
/*0: means nocompress, 1: best speed, ... 9: best compress ratio */
#define DEFAULT_MIGRATE_COMPRESS_LEVEL 1
/* Define default autoconverge cpu throttle migration parameters */ /* Define default autoconverge cpu throttle migration parameters */
#define DEFAULT_MIGRATE_THROTTLE_TRIGGER_THRESHOLD 50 #define DEFAULT_MIGRATE_THROTTLE_TRIGGER_THRESHOLD 50
#define DEFAULT_MIGRATE_CPU_THROTTLE_INITIAL 20 #define DEFAULT_MIGRATE_CPU_THROTTLE_INITIAL 20
@ -92,8 +85,6 @@ Property migration_properties[] = {
send_configuration, true), send_configuration, true),
DEFINE_PROP_BOOL("send-section-footer", MigrationState, DEFINE_PROP_BOOL("send-section-footer", MigrationState,
send_section_footer, true), send_section_footer, true),
DEFINE_PROP_BOOL("decompress-error-check", MigrationState,
decompress_error_check, true),
DEFINE_PROP_BOOL("multifd-flush-after-each-section", MigrationState, DEFINE_PROP_BOOL("multifd-flush-after-each-section", MigrationState,
multifd_flush_after_each_section, false), multifd_flush_after_each_section, false),
DEFINE_PROP_UINT8("x-clear-bitmap-shift", MigrationState, DEFINE_PROP_UINT8("x-clear-bitmap-shift", MigrationState,
@ -102,17 +93,6 @@ Property migration_properties[] = {
preempt_pre_7_2, false), preempt_pre_7_2, false),
/* Migration parameters */ /* Migration parameters */
DEFINE_PROP_UINT8("x-compress-level", MigrationState,
parameters.compress_level,
DEFAULT_MIGRATE_COMPRESS_LEVEL),
DEFINE_PROP_UINT8("x-compress-threads", MigrationState,
parameters.compress_threads,
DEFAULT_MIGRATE_COMPRESS_THREAD_COUNT),
DEFINE_PROP_BOOL("x-compress-wait-thread", MigrationState,
parameters.compress_wait_thread, true),
DEFINE_PROP_UINT8("x-decompress-threads", MigrationState,
parameters.decompress_threads,
DEFAULT_MIGRATE_DECOMPRESS_THREAD_COUNT),
DEFINE_PROP_UINT8("x-throttle-trigger-threshold", MigrationState, DEFINE_PROP_UINT8("x-throttle-trigger-threshold", MigrationState,
parameters.throttle_trigger_threshold, parameters.throttle_trigger_threshold,
DEFAULT_MIGRATE_THROTTLE_TRIGGER_THRESHOLD), DEFAULT_MIGRATE_THROTTLE_TRIGGER_THRESHOLD),
@ -188,14 +168,12 @@ Property migration_properties[] = {
DEFINE_PROP_MIG_CAP("x-rdma-pin-all", MIGRATION_CAPABILITY_RDMA_PIN_ALL), DEFINE_PROP_MIG_CAP("x-rdma-pin-all", MIGRATION_CAPABILITY_RDMA_PIN_ALL),
DEFINE_PROP_MIG_CAP("x-auto-converge", MIGRATION_CAPABILITY_AUTO_CONVERGE), DEFINE_PROP_MIG_CAP("x-auto-converge", MIGRATION_CAPABILITY_AUTO_CONVERGE),
DEFINE_PROP_MIG_CAP("x-zero-blocks", MIGRATION_CAPABILITY_ZERO_BLOCKS), DEFINE_PROP_MIG_CAP("x-zero-blocks", MIGRATION_CAPABILITY_ZERO_BLOCKS),
DEFINE_PROP_MIG_CAP("x-compress", MIGRATION_CAPABILITY_COMPRESS),
DEFINE_PROP_MIG_CAP("x-events", MIGRATION_CAPABILITY_EVENTS), DEFINE_PROP_MIG_CAP("x-events", MIGRATION_CAPABILITY_EVENTS),
DEFINE_PROP_MIG_CAP("x-postcopy-ram", MIGRATION_CAPABILITY_POSTCOPY_RAM), DEFINE_PROP_MIG_CAP("x-postcopy-ram", MIGRATION_CAPABILITY_POSTCOPY_RAM),
DEFINE_PROP_MIG_CAP("x-postcopy-preempt", DEFINE_PROP_MIG_CAP("x-postcopy-preempt",
MIGRATION_CAPABILITY_POSTCOPY_PREEMPT), MIGRATION_CAPABILITY_POSTCOPY_PREEMPT),
DEFINE_PROP_MIG_CAP("x-colo", MIGRATION_CAPABILITY_X_COLO), DEFINE_PROP_MIG_CAP("x-colo", MIGRATION_CAPABILITY_X_COLO),
DEFINE_PROP_MIG_CAP("x-release-ram", MIGRATION_CAPABILITY_RELEASE_RAM), DEFINE_PROP_MIG_CAP("x-release-ram", MIGRATION_CAPABILITY_RELEASE_RAM),
DEFINE_PROP_MIG_CAP("x-block", MIGRATION_CAPABILITY_BLOCK),
DEFINE_PROP_MIG_CAP("x-return-path", MIGRATION_CAPABILITY_RETURN_PATH), DEFINE_PROP_MIG_CAP("x-return-path", MIGRATION_CAPABILITY_RETURN_PATH),
DEFINE_PROP_MIG_CAP("x-multifd", MIGRATION_CAPABILITY_MULTIFD), DEFINE_PROP_MIG_CAP("x-multifd", MIGRATION_CAPABILITY_MULTIFD),
DEFINE_PROP_MIG_CAP("x-background-snapshot", DEFINE_PROP_MIG_CAP("x-background-snapshot",
@ -225,13 +203,6 @@ bool migrate_background_snapshot(void)
return s->capabilities[MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT]; return s->capabilities[MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT];
} }
bool migrate_block(void)
{
MigrationState *s = migrate_get_current();
return s->capabilities[MIGRATION_CAPABILITY_BLOCK];
}
bool migrate_colo(void) bool migrate_colo(void)
{ {
MigrationState *s = migrate_get_current(); MigrationState *s = migrate_get_current();
@ -239,13 +210,6 @@ bool migrate_colo(void)
return s->capabilities[MIGRATION_CAPABILITY_X_COLO]; return s->capabilities[MIGRATION_CAPABILITY_X_COLO];
} }
bool migrate_compress(void)
{
MigrationState *s = migrate_get_current();
return s->capabilities[MIGRATION_CAPABILITY_COMPRESS];
}
bool migrate_dirty_bitmaps(void) bool migrate_dirty_bitmaps(void)
{ {
MigrationState *s = migrate_get_current(); MigrationState *s = migrate_get_current();
@ -459,7 +423,6 @@ INITIALIZE_MIGRATE_CAPS_SET(check_caps_background_snapshot,
MIGRATION_CAPABILITY_AUTO_CONVERGE, MIGRATION_CAPABILITY_AUTO_CONVERGE,
MIGRATION_CAPABILITY_RELEASE_RAM, MIGRATION_CAPABILITY_RELEASE_RAM,
MIGRATION_CAPABILITY_RDMA_PIN_ALL, MIGRATION_CAPABILITY_RDMA_PIN_ALL,
MIGRATION_CAPABILITY_COMPRESS,
MIGRATION_CAPABILITY_XBZRLE, MIGRATION_CAPABILITY_XBZRLE,
MIGRATION_CAPABILITY_X_COLO, MIGRATION_CAPABILITY_X_COLO,
MIGRATION_CAPABILITY_VALIDATE_UUID, MIGRATION_CAPABILITY_VALIDATE_UUID,
@ -484,24 +447,6 @@ bool migrate_caps_check(bool *old_caps, bool *new_caps, Error **errp)
ERRP_GUARD(); ERRP_GUARD();
MigrationIncomingState *mis = migration_incoming_get_current(); MigrationIncomingState *mis = migration_incoming_get_current();
#ifndef CONFIG_LIVE_BLOCK_MIGRATION
if (new_caps[MIGRATION_CAPABILITY_BLOCK]) {
error_setg(errp, "QEMU compiled without old-style (blk/-b, inc/-i) "
"block migration");
error_append_hint(errp, "Use blockdev-mirror with NBD instead.\n");
return false;
}
#endif
if (new_caps[MIGRATION_CAPABILITY_BLOCK]) {
warn_report("block migration is deprecated;"
" use blockdev-mirror with NBD instead");
}
if (new_caps[MIGRATION_CAPABILITY_COMPRESS]) {
warn_report("old compression method is deprecated;"
" use multifd compression methods instead");
}
#ifndef CONFIG_REPLICATION #ifndef CONFIG_REPLICATION
if (new_caps[MIGRATION_CAPABILITY_X_COLO]) { if (new_caps[MIGRATION_CAPABILITY_X_COLO]) {
error_setg(errp, "QEMU compiled without replication module" error_setg(errp, "QEMU compiled without replication module"
@ -570,7 +515,6 @@ bool migrate_caps_check(bool *old_caps, bool *new_caps, Error **errp)
#ifdef CONFIG_LINUX #ifdef CONFIG_LINUX
if (new_caps[MIGRATION_CAPABILITY_ZERO_COPY_SEND] && if (new_caps[MIGRATION_CAPABILITY_ZERO_COPY_SEND] &&
(!new_caps[MIGRATION_CAPABILITY_MULTIFD] || (!new_caps[MIGRATION_CAPABILITY_MULTIFD] ||
new_caps[MIGRATION_CAPABILITY_COMPRESS] ||
new_caps[MIGRATION_CAPABILITY_XBZRLE] || new_caps[MIGRATION_CAPABILITY_XBZRLE] ||
migrate_multifd_compression() || migrate_multifd_compression() ||
migrate_tls())) { migrate_tls())) {
@ -592,17 +536,6 @@ bool migrate_caps_check(bool *old_caps, bool *new_caps, Error **errp)
return false; return false;
} }
/*
* Preempt mode requires urgent pages to be sent in separate
* channel, OTOH compression logic will disorder all pages into
* different compression channels, which is not compatible with the
* preempt assumptions on channel assignments.
*/
if (new_caps[MIGRATION_CAPABILITY_COMPRESS]) {
error_setg(errp, "Postcopy preempt not compatible with compress");
return false;
}
if (migrate_incoming_started()) { if (migrate_incoming_started()) {
error_setg(errp, error_setg(errp,
"Postcopy preempt must be set before incoming starts"); "Postcopy preempt must be set before incoming starts");
@ -611,10 +544,6 @@ bool migrate_caps_check(bool *old_caps, bool *new_caps, Error **errp)
} }
if (new_caps[MIGRATION_CAPABILITY_MULTIFD]) { if (new_caps[MIGRATION_CAPABILITY_MULTIFD]) {
if (new_caps[MIGRATION_CAPABILITY_COMPRESS]) {
error_setg(errp, "Multifd is not compatible with compress");
return false;
}
if (migrate_incoming_started()) { if (migrate_incoming_started()) {
error_setg(errp, "Multifd must be set before incoming starts"); error_setg(errp, "Multifd must be set before incoming starts");
return false; return false;
@ -649,13 +578,6 @@ bool migrate_caps_check(bool *old_caps, bool *new_caps, Error **errp)
} }
} }
if (new_caps[MIGRATION_CAPABILITY_COMPRESS]) {
if (new_caps[MIGRATION_CAPABILITY_XBZRLE]) {
error_setg(errp, "Compression is not compatible with xbzrle");
return false;
}
}
if (new_caps[MIGRATION_CAPABILITY_MAPPED_RAM]) { if (new_caps[MIGRATION_CAPABILITY_MAPPED_RAM]) {
if (new_caps[MIGRATION_CAPABILITY_XBZRLE]) { if (new_caps[MIGRATION_CAPABILITY_XBZRLE]) {
error_setg(errp, error_setg(errp,
@ -663,12 +585,6 @@ bool migrate_caps_check(bool *old_caps, bool *new_caps, Error **errp)
return false; return false;
} }
if (new_caps[MIGRATION_CAPABILITY_COMPRESS]) {
error_setg(errp,
"Mapped-ram migration is incompatible with compression");
return false;
}
if (new_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM]) { if (new_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM]) {
error_setg(errp, error_setg(errp,
"Mapped-ram migration is incompatible with postcopy"); "Mapped-ram migration is incompatible with postcopy");
@ -707,11 +623,6 @@ MigrationCapabilityStatusList *qmp_query_migrate_capabilities(Error **errp)
int i; int i;
for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) { for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
#ifndef CONFIG_LIVE_BLOCK_MIGRATION
if (i == MIGRATION_CAPABILITY_BLOCK) {
continue;
}
#endif
caps = g_malloc0(sizeof(*caps)); caps = g_malloc0(sizeof(*caps));
caps->capability = i; caps->capability = i;
caps->state = s->capabilities[i]; caps->state = s->capabilities[i];
@ -763,13 +674,6 @@ bool migrate_has_block_bitmap_mapping(void)
return s->parameters.has_block_bitmap_mapping; return s->parameters.has_block_bitmap_mapping;
} }
bool migrate_block_incremental(void)
{
MigrationState *s = migrate_get_current();
return s->parameters.block_incremental;
}
uint32_t migrate_checkpoint_delay(void) uint32_t migrate_checkpoint_delay(void)
{ {
MigrationState *s = migrate_get_current(); MigrationState *s = migrate_get_current();
@ -777,27 +681,6 @@ uint32_t migrate_checkpoint_delay(void)
return s->parameters.x_checkpoint_delay; return s->parameters.x_checkpoint_delay;
} }
int migrate_compress_level(void)
{
MigrationState *s = migrate_get_current();
return s->parameters.compress_level;
}
int migrate_compress_threads(void)
{
MigrationState *s = migrate_get_current();
return s->parameters.compress_threads;
}
int migrate_compress_wait_thread(void)
{
MigrationState *s = migrate_get_current();
return s->parameters.compress_wait_thread;
}
uint8_t migrate_cpu_throttle_increment(void) uint8_t migrate_cpu_throttle_increment(void)
{ {
MigrationState *s = migrate_get_current(); MigrationState *s = migrate_get_current();
@ -819,13 +702,6 @@ bool migrate_cpu_throttle_tailslow(void)
return s->parameters.cpu_throttle_tailslow; return s->parameters.cpu_throttle_tailslow;
} }
int migrate_decompress_threads(void)
{
MigrationState *s = migrate_get_current();
return s->parameters.decompress_threads;
}
uint64_t migrate_downtime_limit(void) uint64_t migrate_downtime_limit(void)
{ {
MigrationState *s = migrate_get_current(); MigrationState *s = migrate_get_current();
@ -948,29 +824,8 @@ ZeroPageDetection migrate_zero_page_detection(void)
return s->parameters.zero_page_detection; return s->parameters.zero_page_detection;
} }
/* parameter setters */
void migrate_set_block_incremental(bool value)
{
MigrationState *s = migrate_get_current();
s->parameters.block_incremental = value;
}
/* parameters helpers */ /* parameters helpers */
void block_cleanup_parameters(void)
{
MigrationState *s = migrate_get_current();
if (s->must_remove_block_options) {
/* setting to false can never fail */
migrate_cap_set(MIGRATION_CAPABILITY_BLOCK, false, &error_abort);
migrate_set_block_incremental(false);
s->must_remove_block_options = false;
}
}
AnnounceParameters *migrate_announce_params(void) AnnounceParameters *migrate_announce_params(void)
{ {
static AnnounceParameters ap; static AnnounceParameters ap;
@ -992,14 +847,6 @@ MigrationParameters *qmp_query_migrate_parameters(Error **errp)
/* TODO use QAPI_CLONE() instead of duplicating it inline */ /* TODO use QAPI_CLONE() instead of duplicating it inline */
params = g_malloc0(sizeof(*params)); params = g_malloc0(sizeof(*params));
params->has_compress_level = true;
params->compress_level = s->parameters.compress_level;
params->has_compress_threads = true;
params->compress_threads = s->parameters.compress_threads;
params->has_compress_wait_thread = true;
params->compress_wait_thread = s->parameters.compress_wait_thread;
params->has_decompress_threads = true;
params->decompress_threads = s->parameters.decompress_threads;
params->has_throttle_trigger_threshold = true; params->has_throttle_trigger_threshold = true;
params->throttle_trigger_threshold = s->parameters.throttle_trigger_threshold; params->throttle_trigger_threshold = s->parameters.throttle_trigger_threshold;
params->has_cpu_throttle_initial = true; params->has_cpu_throttle_initial = true;
@ -1020,8 +867,6 @@ MigrationParameters *qmp_query_migrate_parameters(Error **errp)
params->downtime_limit = s->parameters.downtime_limit; params->downtime_limit = s->parameters.downtime_limit;
params->has_x_checkpoint_delay = true; params->has_x_checkpoint_delay = true;
params->x_checkpoint_delay = s->parameters.x_checkpoint_delay; params->x_checkpoint_delay = s->parameters.x_checkpoint_delay;
params->has_block_incremental = true;
params->block_incremental = s->parameters.block_incremental;
params->has_multifd_channels = true; params->has_multifd_channels = true;
params->multifd_channels = s->parameters.multifd_channels; params->multifd_channels = s->parameters.multifd_channels;
params->has_multifd_compression = true; params->has_multifd_compression = true;
@ -1070,10 +915,6 @@ void migrate_params_init(MigrationParameters *params)
params->tls_creds = g_strdup(""); params->tls_creds = g_strdup("");
/* Set has_* up only for parameter checks */ /* Set has_* up only for parameter checks */
params->has_compress_level = true;
params->has_compress_threads = true;
params->has_compress_wait_thread = true;
params->has_decompress_threads = true;
params->has_throttle_trigger_threshold = true; params->has_throttle_trigger_threshold = true;
params->has_cpu_throttle_initial = true; params->has_cpu_throttle_initial = true;
params->has_cpu_throttle_increment = true; params->has_cpu_throttle_increment = true;
@ -1081,7 +922,6 @@ void migrate_params_init(MigrationParameters *params)
params->has_max_bandwidth = true; params->has_max_bandwidth = true;
params->has_downtime_limit = true; params->has_downtime_limit = true;
params->has_x_checkpoint_delay = true; params->has_x_checkpoint_delay = true;
params->has_block_incremental = true;
params->has_multifd_channels = true; params->has_multifd_channels = true;
params->has_multifd_compression = true; params->has_multifd_compression = true;
params->has_multifd_zlib_level = true; params->has_multifd_zlib_level = true;
@ -1107,27 +947,6 @@ bool migrate_params_check(MigrationParameters *params, Error **errp)
{ {
ERRP_GUARD(); ERRP_GUARD();
if (params->has_compress_level &&
(params->compress_level > 9)) {
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "compress_level",
"a value between 0 and 9");
return false;
}
if (params->has_compress_threads && (params->compress_threads < 1)) {
error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
"compress_threads",
"a value between 1 and 255");
return false;
}
if (params->has_decompress_threads && (params->decompress_threads < 1)) {
error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
"decompress_threads",
"a value between 1 and 255");
return false;
}
if (params->has_throttle_trigger_threshold && if (params->has_throttle_trigger_threshold &&
(params->throttle_trigger_threshold < 1 || (params->throttle_trigger_threshold < 1 ||
params->throttle_trigger_threshold > 100)) { params->throttle_trigger_threshold > 100)) {
@ -1301,22 +1120,6 @@ static void migrate_params_test_apply(MigrateSetParameters *params,
/* TODO use QAPI_CLONE() instead of duplicating it inline */ /* TODO use QAPI_CLONE() instead of duplicating it inline */
if (params->has_compress_level) {
dest->compress_level = params->compress_level;
}
if (params->has_compress_threads) {
dest->compress_threads = params->compress_threads;
}
if (params->has_compress_wait_thread) {
dest->compress_wait_thread = params->compress_wait_thread;
}
if (params->has_decompress_threads) {
dest->decompress_threads = params->decompress_threads;
}
if (params->has_throttle_trigger_threshold) { if (params->has_throttle_trigger_threshold) {
dest->throttle_trigger_threshold = params->throttle_trigger_threshold; dest->throttle_trigger_threshold = params->throttle_trigger_threshold;
} }
@ -1359,9 +1162,6 @@ static void migrate_params_test_apply(MigrateSetParameters *params,
dest->x_checkpoint_delay = params->x_checkpoint_delay; dest->x_checkpoint_delay = params->x_checkpoint_delay;
} }
if (params->has_block_incremental) {
dest->block_incremental = params->block_incremental;
}
if (params->has_multifd_channels) { if (params->has_multifd_channels) {
dest->multifd_channels = params->multifd_channels; dest->multifd_channels = params->multifd_channels;
} }
@ -1424,30 +1224,6 @@ static void migrate_params_apply(MigrateSetParameters *params, Error **errp)
/* TODO use QAPI_CLONE() instead of duplicating it inline */ /* TODO use QAPI_CLONE() instead of duplicating it inline */
if (params->has_compress_level) {
warn_report("old compression is deprecated;"
" use multifd compression methods instead");
s->parameters.compress_level = params->compress_level;
}
if (params->has_compress_threads) {
warn_report("old compression is deprecated;"
" use multifd compression methods instead");
s->parameters.compress_threads = params->compress_threads;
}
if (params->has_compress_wait_thread) {
warn_report("old compression is deprecated;"
" use multifd compression methods instead");
s->parameters.compress_wait_thread = params->compress_wait_thread;
}
if (params->has_decompress_threads) {
warn_report("old compression is deprecated;"
" use multifd compression methods instead");
s->parameters.decompress_threads = params->decompress_threads;
}
if (params->has_throttle_trigger_threshold) { if (params->has_throttle_trigger_threshold) {
s->parameters.throttle_trigger_threshold = params->throttle_trigger_threshold; s->parameters.throttle_trigger_threshold = params->throttle_trigger_threshold;
} }
@ -1502,11 +1278,6 @@ static void migrate_params_apply(MigrateSetParameters *params, Error **errp)
colo_checkpoint_delay_set(); colo_checkpoint_delay_set();
} }
if (params->has_block_incremental) {
warn_report("block migration is deprecated;"
" use blockdev-mirror with NBD instead");
s->parameters.block_incremental = params->block_incremental;
}
if (params->has_multifd_channels) { if (params->has_multifd_channels) {
s->parameters.multifd_channels = params->multifd_channels; s->parameters.multifd_channels = params->multifd_channels;
} }

View File

@ -25,9 +25,7 @@ extern Property migration_properties[];
/* capabilities */ /* capabilities */
bool migrate_auto_converge(void); bool migrate_auto_converge(void);
bool migrate_block(void);
bool migrate_colo(void); bool migrate_colo(void);
bool migrate_compress(void);
bool migrate_dirty_bitmaps(void); bool migrate_dirty_bitmaps(void);
bool migrate_events(void); bool migrate_events(void);
bool migrate_mapped_ram(void); bool migrate_mapped_ram(void);
@ -67,15 +65,10 @@ bool migrate_cap_set(int cap, bool value, Error **errp);
const BitmapMigrationNodeAliasList *migrate_block_bitmap_mapping(void); const BitmapMigrationNodeAliasList *migrate_block_bitmap_mapping(void);
bool migrate_has_block_bitmap_mapping(void); bool migrate_has_block_bitmap_mapping(void);
bool migrate_block_incremental(void);
uint32_t migrate_checkpoint_delay(void); uint32_t migrate_checkpoint_delay(void);
int migrate_compress_level(void);
int migrate_compress_threads(void);
int migrate_compress_wait_thread(void);
uint8_t migrate_cpu_throttle_increment(void); uint8_t migrate_cpu_throttle_increment(void);
uint8_t migrate_cpu_throttle_initial(void); uint8_t migrate_cpu_throttle_initial(void);
bool migrate_cpu_throttle_tailslow(void); bool migrate_cpu_throttle_tailslow(void);
int migrate_decompress_threads(void);
uint64_t migrate_downtime_limit(void); uint64_t migrate_downtime_limit(void);
uint8_t migrate_max_cpu_throttle(void); uint8_t migrate_max_cpu_throttle(void);
uint64_t migrate_max_bandwidth(void); uint64_t migrate_max_bandwidth(void);
@ -92,14 +85,8 @@ const char *migrate_tls_hostname(void);
uint64_t migrate_xbzrle_cache_size(void); uint64_t migrate_xbzrle_cache_size(void);
ZeroPageDetection migrate_zero_page_detection(void); ZeroPageDetection migrate_zero_page_detection(void);
/* parameters setters */
void migrate_set_block_incremental(bool value);
/* parameters helpers */ /* parameters helpers */
bool migrate_params_check(MigrationParameters *params, Error **errp); bool migrate_params_check(MigrationParameters *params, Error **errp);
void migrate_params_init(MigrationParameters *params); void migrate_params_init(MigrationParameters *params);
void block_cleanup_parameters(void);
#endif #endif

View File

@ -778,84 +778,6 @@ uint64_t qemu_get_be64(QEMUFile *f)
return v; return v;
} }
/* return the size after compression, or negative value on error */
static int qemu_compress_data(z_stream *stream, uint8_t *dest, size_t dest_len,
const uint8_t *source, size_t source_len)
{
int err;
err = deflateReset(stream);
if (err != Z_OK) {
return -1;
}
stream->avail_in = source_len;
stream->next_in = (uint8_t *)source;
stream->avail_out = dest_len;
stream->next_out = dest;
err = deflate(stream, Z_FINISH);
if (err != Z_STREAM_END) {
return -1;
}
return stream->next_out - dest;
}
/* Compress size bytes of data start at p and store the compressed
* data to the buffer of f.
*
* Since the file is dummy file with empty_ops, return -1 if f has no space to
* save the compressed data.
*/
ssize_t qemu_put_compression_data(QEMUFile *f, z_stream *stream,
const uint8_t *p, size_t size)
{
ssize_t blen = IO_BUF_SIZE - f->buf_index - sizeof(int32_t);
if (blen < compressBound(size)) {
return -1;
}
blen = qemu_compress_data(stream, f->buf + f->buf_index + sizeof(int32_t),
blen, p, size);
if (blen < 0) {
return -1;
}
qemu_put_be32(f, blen);
add_buf_to_iovec(f, blen);
return blen + sizeof(int32_t);
}
/* Put the data in the buffer of f_src to the buffer of f_des, and
* then reset the buf_index of f_src to 0.
*/
int qemu_put_qemu_file(QEMUFile *f_des, QEMUFile *f_src)
{
int len = 0;
if (f_src->buf_index > 0) {
len = f_src->buf_index;
qemu_put_buffer(f_des, f_src->buf, f_src->buf_index);
f_src->buf_index = 0;
f_src->iovcnt = 0;
}
return len;
}
/*
* Check if the writable buffer is empty
*/
bool qemu_file_buffer_empty(QEMUFile *file)
{
assert(qemu_file_is_writable(file));
return !file->iovcnt;
}
/* /*
* Get a string whose length is determined by a single preceding byte * Get a string whose length is determined by a single preceding byte
* A preallocated 256 byte buffer must be passed in. * A preallocated 256 byte buffer must be passed in.

View File

@ -54,10 +54,6 @@ void qemu_put_buffer_async(QEMUFile *f, const uint8_t *buf, size_t size,
size_t coroutine_mixed_fn qemu_peek_buffer(QEMUFile *f, uint8_t **buf, size_t size, size_t offset); size_t coroutine_mixed_fn qemu_peek_buffer(QEMUFile *f, uint8_t **buf, size_t size, size_t offset);
size_t coroutine_mixed_fn qemu_get_buffer_in_place(QEMUFile *f, uint8_t **buf, size_t size); size_t coroutine_mixed_fn qemu_get_buffer_in_place(QEMUFile *f, uint8_t **buf, size_t size);
ssize_t qemu_put_compression_data(QEMUFile *f, z_stream *stream,
const uint8_t *p, size_t size);
int qemu_put_qemu_file(QEMUFile *f_des, QEMUFile *f_src);
bool qemu_file_buffer_empty(QEMUFile *file);
/* /*
* Note that you can only peek continuous bytes from where the current pointer * Note that you can only peek continuous bytes from where the current pointer

View File

@ -1,564 +0,0 @@
/*
* QEMU System Emulator
*
* Copyright (c) 2003-2008 Fabrice Bellard
* Copyright (c) 2011-2015 Red Hat Inc
*
* Authors:
* Juan Quintela <quintela@redhat.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "qemu/osdep.h"
#include "qemu/cutils.h"
#include "ram-compress.h"
#include "qemu/error-report.h"
#include "qemu/stats64.h"
#include "migration.h"
#include "options.h"
#include "io/channel-null.h"
#include "exec/target_page.h"
#include "exec/ramblock.h"
#include "ram.h"
#include "migration-stats.h"
static struct {
int64_t pages;
int64_t busy;
double busy_rate;
int64_t compressed_size;
double compression_rate;
/* compression statistics since the beginning of the period */
/* amount of count that no free thread to compress data */
uint64_t compress_thread_busy_prev;
/* amount bytes after compression */
uint64_t compressed_size_prev;
/* amount of compressed pages */
uint64_t compress_pages_prev;
} compression_counters;
static CompressParam *comp_param;
static QemuThread *compress_threads;
/* comp_done_cond is used to wake up the migration thread when
* one of the compression threads has finished the compression.
* comp_done_lock is used to co-work with comp_done_cond.
*/
static QemuMutex comp_done_lock;
static QemuCond comp_done_cond;
struct DecompressParam {
bool done;
bool quit;
QemuMutex mutex;
QemuCond cond;
void *des;
uint8_t *compbuf;
int len;
z_stream stream;
};
typedef struct DecompressParam DecompressParam;
static QEMUFile *decomp_file;
static DecompressParam *decomp_param;
static QemuThread *decompress_threads;
static QemuMutex decomp_done_lock;
static QemuCond decomp_done_cond;
static CompressResult do_compress_ram_page(QEMUFile *f, z_stream *stream,
RAMBlock *block, ram_addr_t offset,
uint8_t *source_buf);
static void *do_data_compress(void *opaque)
{
CompressParam *param = opaque;
RAMBlock *block;
ram_addr_t offset;
CompressResult result;
qemu_mutex_lock(&param->mutex);
while (!param->quit) {
if (param->trigger) {
block = param->block;
offset = param->offset;
param->trigger = false;
qemu_mutex_unlock(&param->mutex);
result = do_compress_ram_page(param->file, &param->stream,
block, offset, param->originbuf);
qemu_mutex_lock(&comp_done_lock);
param->done = true;
param->result = result;
qemu_cond_signal(&comp_done_cond);
qemu_mutex_unlock(&comp_done_lock);
qemu_mutex_lock(&param->mutex);
} else {
qemu_cond_wait(&param->cond, &param->mutex);
}
}
qemu_mutex_unlock(&param->mutex);
return NULL;
}
void compress_threads_save_cleanup(void)
{
int i, thread_count;
if (!migrate_compress() || !comp_param) {
return;
}
thread_count = migrate_compress_threads();
for (i = 0; i < thread_count; i++) {
/*
* we use it as a indicator which shows if the thread is
* properly init'd or not
*/
if (!comp_param[i].file) {
break;
}
qemu_mutex_lock(&comp_param[i].mutex);
comp_param[i].quit = true;
qemu_cond_signal(&comp_param[i].cond);
qemu_mutex_unlock(&comp_param[i].mutex);
qemu_thread_join(compress_threads + i);
qemu_mutex_destroy(&comp_param[i].mutex);
qemu_cond_destroy(&comp_param[i].cond);
deflateEnd(&comp_param[i].stream);
g_free(comp_param[i].originbuf);
qemu_fclose(comp_param[i].file);
comp_param[i].file = NULL;
}
qemu_mutex_destroy(&comp_done_lock);
qemu_cond_destroy(&comp_done_cond);
g_free(compress_threads);
g_free(comp_param);
compress_threads = NULL;
comp_param = NULL;
}
int compress_threads_save_setup(void)
{
int i, thread_count;
if (!migrate_compress()) {
return 0;
}
thread_count = migrate_compress_threads();
compress_threads = g_new0(QemuThread, thread_count);
comp_param = g_new0(CompressParam, thread_count);
qemu_cond_init(&comp_done_cond);
qemu_mutex_init(&comp_done_lock);
for (i = 0; i < thread_count; i++) {
comp_param[i].originbuf = g_try_malloc(qemu_target_page_size());
if (!comp_param[i].originbuf) {
goto exit;
}
if (deflateInit(&comp_param[i].stream,
migrate_compress_level()) != Z_OK) {
g_free(comp_param[i].originbuf);
goto exit;
}
/* comp_param[i].file is just used as a dummy buffer to save data,
* set its ops to empty.
*/
comp_param[i].file = qemu_file_new_output(
QIO_CHANNEL(qio_channel_null_new()));
comp_param[i].done = true;
comp_param[i].quit = false;
qemu_mutex_init(&comp_param[i].mutex);
qemu_cond_init(&comp_param[i].cond);
qemu_thread_create(compress_threads + i, "compress",
do_data_compress, comp_param + i,
QEMU_THREAD_JOINABLE);
}
return 0;
exit:
compress_threads_save_cleanup();
return -1;
}
static CompressResult do_compress_ram_page(QEMUFile *f, z_stream *stream,
RAMBlock *block, ram_addr_t offset,
uint8_t *source_buf)
{
uint8_t *p = block->host + offset;
size_t page_size = qemu_target_page_size();
int ret;
assert(qemu_file_buffer_empty(f));
if (buffer_is_zero(p, page_size)) {
return RES_ZEROPAGE;
}
/*
* copy it to a internal buffer to avoid it being modified by VM
* so that we can catch up the error during compression and
* decompression
*/
memcpy(source_buf, p, page_size);
ret = qemu_put_compression_data(f, stream, source_buf, page_size);
if (ret < 0) {
qemu_file_set_error(migrate_get_current()->to_dst_file, ret);
error_report("compressed data failed!");
qemu_fflush(f);
return RES_NONE;
}
return RES_COMPRESS;
}
static inline void compress_reset_result(CompressParam *param)
{
param->result = RES_NONE;
param->block = NULL;
param->offset = 0;
}
void compress_flush_data(void)
{
int thread_count = migrate_compress_threads();
if (!migrate_compress()) {
return;
}
qemu_mutex_lock(&comp_done_lock);
for (int i = 0; i < thread_count; i++) {
while (!comp_param[i].done) {
qemu_cond_wait(&comp_done_cond, &comp_done_lock);
}
}
qemu_mutex_unlock(&comp_done_lock);
for (int i = 0; i < thread_count; i++) {
qemu_mutex_lock(&comp_param[i].mutex);
if (!comp_param[i].quit) {
CompressParam *param = &comp_param[i];
compress_send_queued_data(param);
assert(qemu_file_buffer_empty(param->file));
compress_reset_result(param);
}
qemu_mutex_unlock(&comp_param[i].mutex);
}
}
static inline void set_compress_params(CompressParam *param, RAMBlock *block,
ram_addr_t offset)
{
param->block = block;
param->offset = offset;
param->trigger = true;
}
/*
* Return true when it compress a page
*/
bool compress_page_with_multi_thread(RAMBlock *block, ram_addr_t offset,
int (send_queued_data(CompressParam *)))
{
int thread_count;
bool wait = migrate_compress_wait_thread();
thread_count = migrate_compress_threads();
qemu_mutex_lock(&comp_done_lock);
while (true) {
for (int i = 0; i < thread_count; i++) {
if (comp_param[i].done) {
CompressParam *param = &comp_param[i];
qemu_mutex_lock(&param->mutex);
param->done = false;
send_queued_data(param);
assert(qemu_file_buffer_empty(param->file));
compress_reset_result(param);
set_compress_params(param, block, offset);
qemu_cond_signal(&param->cond);
qemu_mutex_unlock(&param->mutex);
qemu_mutex_unlock(&comp_done_lock);
return true;
}
}
if (!wait) {
qemu_mutex_unlock(&comp_done_lock);
compression_counters.busy++;
return false;
}
/*
* wait for a free thread if the user specifies
* 'compress-wait-thread', otherwise we will post the page out
* in the main thread as normal page.
*/
qemu_cond_wait(&comp_done_cond, &comp_done_lock);
}
}
/* return the size after decompression, or negative value on error */
static int
qemu_uncompress_data(z_stream *stream, uint8_t *dest, size_t dest_len,
const uint8_t *source, size_t source_len)
{
int err;
err = inflateReset(stream);
if (err != Z_OK) {
return -1;
}
stream->avail_in = source_len;
stream->next_in = (uint8_t *)source;
stream->avail_out = dest_len;
stream->next_out = dest;
err = inflate(stream, Z_NO_FLUSH);
if (err != Z_STREAM_END) {
return -1;
}
return stream->total_out;
}
static void *do_data_decompress(void *opaque)
{
DecompressParam *param = opaque;
unsigned long pagesize;
uint8_t *des;
int len, ret;
qemu_mutex_lock(&param->mutex);
while (!param->quit) {
if (param->des) {
des = param->des;
len = param->len;
param->des = 0;
qemu_mutex_unlock(&param->mutex);
pagesize = qemu_target_page_size();
ret = qemu_uncompress_data(&param->stream, des, pagesize,
param->compbuf, len);
if (ret < 0 && migrate_get_current()->decompress_error_check) {
error_report("decompress data failed");
qemu_file_set_error(decomp_file, ret);
}
qemu_mutex_lock(&decomp_done_lock);
param->done = true;
qemu_cond_signal(&decomp_done_cond);
qemu_mutex_unlock(&decomp_done_lock);
qemu_mutex_lock(&param->mutex);
} else {
qemu_cond_wait(&param->cond, &param->mutex);
}
}
qemu_mutex_unlock(&param->mutex);
return NULL;
}
int wait_for_decompress_done(void)
{
if (!migrate_compress()) {
return 0;
}
int thread_count = migrate_decompress_threads();
qemu_mutex_lock(&decomp_done_lock);
for (int i = 0; i < thread_count; i++) {
while (!decomp_param[i].done) {
qemu_cond_wait(&decomp_done_cond, &decomp_done_lock);
}
}
qemu_mutex_unlock(&decomp_done_lock);
return qemu_file_get_error(decomp_file);
}
void compress_threads_load_cleanup(void)
{
int i, thread_count;
if (!migrate_compress()) {
return;
}
thread_count = migrate_decompress_threads();
for (i = 0; i < thread_count; i++) {
/*
* we use it as a indicator which shows if the thread is
* properly init'd or not
*/
if (!decomp_param[i].compbuf) {
break;
}
qemu_mutex_lock(&decomp_param[i].mutex);
decomp_param[i].quit = true;
qemu_cond_signal(&decomp_param[i].cond);
qemu_mutex_unlock(&decomp_param[i].mutex);
}
for (i = 0; i < thread_count; i++) {
if (!decomp_param[i].compbuf) {
break;
}
qemu_thread_join(decompress_threads + i);
qemu_mutex_destroy(&decomp_param[i].mutex);
qemu_cond_destroy(&decomp_param[i].cond);
inflateEnd(&decomp_param[i].stream);
g_free(decomp_param[i].compbuf);
decomp_param[i].compbuf = NULL;
}
g_free(decompress_threads);
g_free(decomp_param);
decompress_threads = NULL;
decomp_param = NULL;
decomp_file = NULL;
}
int compress_threads_load_setup(QEMUFile *f)
{
int i, thread_count;
if (!migrate_compress()) {
return 0;
}
/*
* set compression_counters memory to zero for a new migration
*/
memset(&compression_counters, 0, sizeof(compression_counters));
thread_count = migrate_decompress_threads();
decompress_threads = g_new0(QemuThread, thread_count);
decomp_param = g_new0(DecompressParam, thread_count);
qemu_mutex_init(&decomp_done_lock);
qemu_cond_init(&decomp_done_cond);
decomp_file = f;
for (i = 0; i < thread_count; i++) {
if (inflateInit(&decomp_param[i].stream) != Z_OK) {
goto exit;
}
size_t compbuf_size = compressBound(qemu_target_page_size());
decomp_param[i].compbuf = g_malloc0(compbuf_size);
qemu_mutex_init(&decomp_param[i].mutex);
qemu_cond_init(&decomp_param[i].cond);
decomp_param[i].done = true;
decomp_param[i].quit = false;
qemu_thread_create(decompress_threads + i, "decompress",
do_data_decompress, decomp_param + i,
QEMU_THREAD_JOINABLE);
}
return 0;
exit:
compress_threads_load_cleanup();
return -1;
}
void decompress_data_with_multi_threads(QEMUFile *f, void *host, int len)
{
int thread_count = migrate_decompress_threads();
QEMU_LOCK_GUARD(&decomp_done_lock);
while (true) {
for (int i = 0; i < thread_count; i++) {
if (decomp_param[i].done) {
decomp_param[i].done = false;
qemu_mutex_lock(&decomp_param[i].mutex);
qemu_get_buffer(f, decomp_param[i].compbuf, len);
decomp_param[i].des = host;
decomp_param[i].len = len;
qemu_cond_signal(&decomp_param[i].cond);
qemu_mutex_unlock(&decomp_param[i].mutex);
return;
}
}
qemu_cond_wait(&decomp_done_cond, &decomp_done_lock);
}
}
void populate_compress(MigrationInfo *info)
{
if (!migrate_compress()) {
return;
}
info->compression = g_malloc0(sizeof(*info->compression));
info->compression->pages = compression_counters.pages;
info->compression->busy = compression_counters.busy;
info->compression->busy_rate = compression_counters.busy_rate;
info->compression->compressed_size = compression_counters.compressed_size;
info->compression->compression_rate = compression_counters.compression_rate;
}
uint64_t compress_ram_pages(void)
{
return compression_counters.pages;
}
void update_compress_thread_counts(const CompressParam *param, int bytes_xmit)
{
ram_transferred_add(bytes_xmit);
if (param->result == RES_ZEROPAGE) {
stat64_add(&mig_stats.zero_pages, 1);
return;
}
/* 8 means a header with RAM_SAVE_FLAG_CONTINUE. */
compression_counters.compressed_size += bytes_xmit - 8;
compression_counters.pages++;
}
void compress_update_rates(uint64_t page_count)
{
if (!migrate_compress()) {
return;
}
compression_counters.busy_rate = (double)(compression_counters.busy -
compression_counters.compress_thread_busy_prev) / page_count;
compression_counters.compress_thread_busy_prev =
compression_counters.busy;
double compressed_size = compression_counters.compressed_size -
compression_counters.compressed_size_prev;
if (compressed_size) {
double uncompressed_size = (compression_counters.pages -
compression_counters.compress_pages_prev) *
qemu_target_page_size();
/* Compression-Ratio = Uncompressed-size / Compressed-size */
compression_counters.compression_rate =
uncompressed_size / compressed_size;
compression_counters.compress_pages_prev =
compression_counters.pages;
compression_counters.compressed_size_prev =
compression_counters.compressed_size;
}
}

View File

@ -1,77 +0,0 @@
/*
* QEMU System Emulator
*
* Copyright (c) 2003-2008 Fabrice Bellard
* Copyright (c) 2011-2015 Red Hat Inc
*
* Authors:
* Juan Quintela <quintela@redhat.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef QEMU_MIGRATION_COMPRESS_H
#define QEMU_MIGRATION_COMPRESS_H
#include "qemu-file.h"
#include "qapi/qapi-types-migration.h"
enum CompressResult {
RES_NONE = 0,
RES_ZEROPAGE = 1,
RES_COMPRESS = 2
};
typedef enum CompressResult CompressResult;
struct CompressParam {
bool done;
bool quit;
bool trigger;
CompressResult result;
QEMUFile *file;
QemuMutex mutex;
QemuCond cond;
RAMBlock *block;
ram_addr_t offset;
/* internally used fields */
z_stream stream;
uint8_t *originbuf;
};
typedef struct CompressParam CompressParam;
void compress_threads_save_cleanup(void);
int compress_threads_save_setup(void);
bool compress_page_with_multi_thread(RAMBlock *block, ram_addr_t offset,
int (send_queued_data(CompressParam *)));
int wait_for_decompress_done(void);
void compress_threads_load_cleanup(void);
int compress_threads_load_setup(QEMUFile *f);
void decompress_data_with_multi_threads(QEMUFile *f, void *host, int len);
void populate_compress(MigrationInfo *info);
uint64_t compress_ram_pages(void);
void update_compress_thread_counts(const CompressParam *param, int bytes_xmit);
void compress_update_rates(uint64_t page_count);
int compress_send_queued_data(CompressParam *param);
void compress_flush_data(void);
#endif

View File

@ -33,7 +33,6 @@
#include "qemu/madvise.h" #include "qemu/madvise.h"
#include "qemu/main-loop.h" #include "qemu/main-loop.h"
#include "xbzrle.h" #include "xbzrle.h"
#include "ram-compress.h"
#include "ram.h" #include "ram.h"
#include "migration.h" #include "migration.h"
#include "migration-stats.h" #include "migration-stats.h"
@ -53,7 +52,6 @@
#include "exec/target_page.h" #include "exec/target_page.h"
#include "qemu/rcu_queue.h" #include "qemu/rcu_queue.h"
#include "migration/colo.h" #include "migration/colo.h"
#include "block.h"
#include "sysemu/cpu-throttle.h" #include "sysemu/cpu-throttle.h"
#include "savevm.h" #include "savevm.h"
#include "qemu/iov.h" #include "qemu/iov.h"
@ -78,9 +76,10 @@
* worked for pages that were filled with the same char. We switched * worked for pages that were filled with the same char. We switched
* it to only search for the zero value. And to avoid confusion with * it to only search for the zero value. And to avoid confusion with
* RAM_SAVE_FLAG_COMPRESS_PAGE just rename it. * RAM_SAVE_FLAG_COMPRESS_PAGE just rename it.
*/ *
/* * RAM_SAVE_FLAG_FULL was obsoleted in 2009.
* RAM_SAVE_FLAG_FULL was obsoleted in 2009, it can be reused now *
* RAM_SAVE_FLAG_COMPRESS_PAGE (0x100) was removed in QEMU 9.1.
*/ */
#define RAM_SAVE_FLAG_FULL 0x01 #define RAM_SAVE_FLAG_FULL 0x01
#define RAM_SAVE_FLAG_ZERO 0x02 #define RAM_SAVE_FLAG_ZERO 0x02
@ -90,7 +89,6 @@
#define RAM_SAVE_FLAG_CONTINUE 0x20 #define RAM_SAVE_FLAG_CONTINUE 0x20
#define RAM_SAVE_FLAG_XBZRLE 0x40 #define RAM_SAVE_FLAG_XBZRLE 0x40
/* 0x80 is reserved in rdma.h for RAM_SAVE_FLAG_HOOK */ /* 0x80 is reserved in rdma.h for RAM_SAVE_FLAG_HOOK */
#define RAM_SAVE_FLAG_COMPRESS_PAGE 0x100
#define RAM_SAVE_FLAG_MULTIFD_FLUSH 0x200 #define RAM_SAVE_FLAG_MULTIFD_FLUSH 0x200
/* We can't use any flag that is bigger than 0x200 */ /* We can't use any flag that is bigger than 0x200 */
@ -691,8 +689,7 @@ static int save_xbzrle_page(RAMState *rs, PageSearchStatus *pss,
qemu_put_buffer(file, XBZRLE.encoded_buf, encoded_len); qemu_put_buffer(file, XBZRLE.encoded_buf, encoded_len);
bytes_xbzrle += encoded_len + 1 + 2; bytes_xbzrle += encoded_len + 1 + 2;
/* /*
* Like compressed_size (please see update_compress_thread_counts), * The xbzrle encoded bytes don't count the 8 byte header with
* the xbzrle encoded bytes don't count the 8 byte header with
* RAM_SAVE_FLAG_CONTINUE. * RAM_SAVE_FLAG_CONTINUE.
*/ */
xbzrle_counters.bytes += bytes_xbzrle - 8; xbzrle_counters.bytes += bytes_xbzrle - 8;
@ -950,7 +947,7 @@ uint64_t ram_get_total_transferred_pages(void)
{ {
return stat64_get(&mig_stats.normal_pages) + return stat64_get(&mig_stats.normal_pages) +
stat64_get(&mig_stats.zero_pages) + stat64_get(&mig_stats.zero_pages) +
compress_ram_pages() + xbzrle_counters.pages; xbzrle_counters.pages;
} }
static void migration_update_rates(RAMState *rs, int64_t end_time) static void migration_update_rates(RAMState *rs, int64_t end_time)
@ -983,7 +980,6 @@ static void migration_update_rates(RAMState *rs, int64_t end_time)
rs->xbzrle_pages_prev = xbzrle_counters.pages; rs->xbzrle_pages_prev = xbzrle_counters.pages;
rs->xbzrle_bytes_prev = xbzrle_counters.bytes; rs->xbzrle_bytes_prev = xbzrle_counters.bytes;
} }
compress_update_rates(page_count);
} }
/* /*
@ -1025,13 +1021,6 @@ static void migration_trigger_throttle(RAMState *rs)
uint64_t bytes_dirty_period = rs->num_dirty_pages_period * TARGET_PAGE_SIZE; uint64_t bytes_dirty_period = rs->num_dirty_pages_period * TARGET_PAGE_SIZE;
uint64_t bytes_dirty_threshold = bytes_xfer_period * threshold / 100; uint64_t bytes_dirty_threshold = bytes_xfer_period * threshold / 100;
/* During block migration the auto-converge logic incorrectly detects
* that ram migration makes no progress. Avoid this by disabling the
* throttling logic during the bulk phase of block migration. */
if (blk_mig_bulk_active()) {
return;
}
/* /*
* The following detection logic can be refined later. For now: * The following detection logic can be refined later. For now:
* Check to see if the ratio between dirtied bytes and the approx. * Check to see if the ratio between dirtied bytes and the approx.
@ -1066,14 +1055,14 @@ static void migration_bitmap_sync(RAMState *rs, bool last_stage)
trace_migration_bitmap_sync_start(); trace_migration_bitmap_sync_start();
memory_global_dirty_log_sync(last_stage); memory_global_dirty_log_sync(last_stage);
qemu_mutex_lock(&rs->bitmap_mutex); WITH_QEMU_LOCK_GUARD(&rs->bitmap_mutex) {
WITH_RCU_READ_LOCK_GUARD() { WITH_RCU_READ_LOCK_GUARD() {
RAMBLOCK_FOREACH_NOT_IGNORED(block) { RAMBLOCK_FOREACH_NOT_IGNORED(block) {
ramblock_sync_dirty_bitmap(rs, block); ramblock_sync_dirty_bitmap(rs, block);
} }
stat64_set(&mig_stats.dirty_bytes_last_sync, ram_bytes_remaining()); stat64_set(&mig_stats.dirty_bytes_last_sync, ram_bytes_remaining());
} }
qemu_mutex_unlock(&rs->bitmap_mutex); }
memory_global_after_dirty_log_sync(); memory_global_after_dirty_log_sync();
trace_migration_bitmap_sync_end(rs->num_dirty_pages_period); trace_migration_bitmap_sync_end(rs->num_dirty_pages_period);
@ -1296,41 +1285,6 @@ static int ram_save_multifd_page(RAMBlock *block, ram_addr_t offset)
return 1; return 1;
} }
int compress_send_queued_data(CompressParam *param)
{
PageSearchStatus *pss = &ram_state->pss[RAM_CHANNEL_PRECOPY];
MigrationState *ms = migrate_get_current();
QEMUFile *file = ms->to_dst_file;
int len = 0;
RAMBlock *block = param->block;
ram_addr_t offset = param->offset;
if (param->result == RES_NONE) {
return 0;
}
assert(block == pss->last_sent_block);
if (param->result == RES_ZEROPAGE) {
assert(qemu_file_buffer_empty(param->file));
len += save_page_header(pss, file, block, offset | RAM_SAVE_FLAG_ZERO);
qemu_put_byte(file, 0);
len += 1;
ram_release_page(block->idstr, offset);
} else if (param->result == RES_COMPRESS) {
assert(!qemu_file_buffer_empty(param->file));
len += save_page_header(pss, file, block,
offset | RAM_SAVE_FLAG_COMPRESS_PAGE);
len += qemu_put_qemu_file(file, param->file);
} else {
abort();
}
update_compress_thread_counts(param, len);
return len;
}
#define PAGE_ALL_CLEAN 0 #define PAGE_ALL_CLEAN 0
#define PAGE_TRY_AGAIN 1 #define PAGE_TRY_AGAIN 1
@ -1382,16 +1336,6 @@ static int find_dirty_block(RAMState *rs, PageSearchStatus *pss)
qemu_fflush(f); qemu_fflush(f);
} }
} }
/*
* If memory migration starts over, we will meet a dirtied page
* which may still exists in compression threads's ring, so we
* should flush the compressed data to make sure the new page
* is not overwritten by the old one in the destination.
*
* Also If xbzrle is on, stop using the data compression at this
* point. In theory, xbzrle can do better than compression.
*/
compress_flush_data();
/* Hit the end of the list */ /* Hit the end of the list */
pss->block = QLIST_FIRST_RCU(&ram_list.blocks); pss->block = QLIST_FIRST_RCU(&ram_list.blocks);
@ -2042,37 +1986,6 @@ int ram_save_queue_pages(const char *rbname, ram_addr_t start, ram_addr_t len,
return 0; return 0;
} }
/*
* try to compress the page before posting it out, return true if the page
* has been properly handled by compression, otherwise needs other
* paths to handle it
*/
static bool save_compress_page(RAMState *rs, PageSearchStatus *pss,
ram_addr_t offset)
{
if (!migrate_compress()) {
return false;
}
/*
* When starting the process of a new block, the first page of
* the block should be sent out before other pages in the same
* block, and all the pages in last block should have been sent
* out, keeping this order is important, because the 'cont' flag
* is used to avoid resending the block name.
*
* We post the fist page as normal page as compression will take
* much CPU resource.
*/
if (pss->block != pss->last_sent_block) {
compress_flush_data();
return false;
}
return compress_page_with_multi_thread(pss->block, offset,
compress_send_queued_data);
}
/** /**
* ram_save_target_page_legacy: save one target page * ram_save_target_page_legacy: save one target page
* *
@ -2090,10 +2003,6 @@ static int ram_save_target_page_legacy(RAMState *rs, PageSearchStatus *pss)
return res; return res;
} }
if (save_compress_page(rs, pss, offset)) {
return 1;
}
if (save_zero_page(rs, pss, offset)) { if (save_zero_page(rs, pss, offset)) {
return 1; return 1;
} }
@ -2478,7 +2387,6 @@ static void ram_save_cleanup(void *opaque)
ram_bitmaps_destroy(); ram_bitmaps_destroy();
xbzrle_cleanup(); xbzrle_cleanup();
compress_threads_save_cleanup();
ram_state_cleanup(rsp); ram_state_cleanup(rsp);
g_free(migration_ops); g_free(migration_ops);
migration_ops = NULL; migration_ops = NULL;
@ -3097,15 +3005,9 @@ static int ram_save_setup(QEMUFile *f, void *opaque, Error **errp)
RAMBlock *block; RAMBlock *block;
int ret, max_hg_page_size; int ret, max_hg_page_size;
if (compress_threads_save_setup()) {
error_setg(errp, "%s: failed to start compress threads", __func__);
return -1;
}
/* migration has already setup the bitmap, reuse it. */ /* migration has already setup the bitmap, reuse it. */
if (!migration_in_colo_state()) { if (!migration_in_colo_state()) {
if (ram_init_all(rsp, errp) != 0) { if (ram_init_all(rsp, errp) != 0) {
compress_threads_save_cleanup();
return -1; return -1;
} }
} }
@ -3230,13 +3132,6 @@ static int ram_save_iterate(QEMUFile *f, void *opaque)
int64_t t0; int64_t t0;
int done = 0; int done = 0;
if (blk_mig_bulk_active()) {
/* Avoid transferring ram during bulk phase of block migration as
* the bulk phase will usually take a long time and transferring
* ram updates during that time is pointless. */
goto out;
}
/* /*
* We'll take this lock a little bit long, but it's okay for two reasons. * We'll take this lock a little bit long, but it's okay for two reasons.
* Firstly, the only possible other thread to take it is who calls * Firstly, the only possible other thread to take it is who calls
@ -3283,14 +3178,6 @@ static int ram_save_iterate(QEMUFile *f, void *opaque)
rs->target_page_count += pages; rs->target_page_count += pages;
/*
* During postcopy, it is necessary to make sure one whole host
* page is sent in one chunk.
*/
if (migrate_postcopy_ram()) {
compress_flush_data();
}
/* /*
* we want to check in the 1st loop, just in case it was the 1st * we want to check in the 1st loop, just in case it was the 1st
* time and we had to sync the dirty bitmap. * time and we had to sync the dirty bitmap.
@ -3389,8 +3276,6 @@ static int ram_save_complete(QEMUFile *f, void *opaque)
} }
qemu_mutex_unlock(&rs->bitmap_mutex); qemu_mutex_unlock(&rs->bitmap_mutex);
compress_flush_data();
ret = rdma_registration_stop(f, RAM_CONTROL_FINISH); ret = rdma_registration_stop(f, RAM_CONTROL_FINISH);
if (ret < 0) { if (ret < 0) {
qemu_file_set_error(f, ret); qemu_file_set_error(f, ret);
@ -3804,7 +3689,6 @@ int ram_load_postcopy(QEMUFile *f, int channel)
void *place_source = NULL; void *place_source = NULL;
RAMBlock *block = NULL; RAMBlock *block = NULL;
uint8_t ch; uint8_t ch;
int len;
addr = qemu_get_be64(f); addr = qemu_get_be64(f);
@ -3821,8 +3705,7 @@ int ram_load_postcopy(QEMUFile *f, int channel)
addr &= TARGET_PAGE_MASK; addr &= TARGET_PAGE_MASK;
trace_ram_load_postcopy_loop(channel, (uint64_t)addr, flags); trace_ram_load_postcopy_loop(channel, (uint64_t)addr, flags);
if (flags & (RAM_SAVE_FLAG_ZERO | RAM_SAVE_FLAG_PAGE | if (flags & (RAM_SAVE_FLAG_ZERO | RAM_SAVE_FLAG_PAGE)) {
RAM_SAVE_FLAG_COMPRESS_PAGE)) {
block = ram_block_from_stream(mis, f, flags, channel); block = ram_block_from_stream(mis, f, flags, channel);
if (!block) { if (!block) {
ret = -EINVAL; ret = -EINVAL;
@ -3917,16 +3800,6 @@ int ram_load_postcopy(QEMUFile *f, int channel)
TARGET_PAGE_SIZE); TARGET_PAGE_SIZE);
} }
break; break;
case RAM_SAVE_FLAG_COMPRESS_PAGE:
tmp_page->all_zero = false;
len = qemu_get_be32(f);
if (len < 0 || len > compressBound(TARGET_PAGE_SIZE)) {
error_report("Invalid compressed data length: %d", len);
ret = -EINVAL;
break;
}
decompress_data_with_multi_threads(f, page_buffer, len);
break;
case RAM_SAVE_FLAG_MULTIFD_FLUSH: case RAM_SAVE_FLAG_MULTIFD_FLUSH:
multifd_recv_sync_main(); multifd_recv_sync_main();
break; break;
@ -3944,11 +3817,6 @@ int ram_load_postcopy(QEMUFile *f, int channel)
break; break;
} }
/* Got the whole host page, wait for decompress before placing. */
if (place_needed) {
ret |= wait_for_decompress_done();
}
/* Detect for any possible file errors */ /* Detect for any possible file errors */
if (!ret && qemu_file_get_error(f)) { if (!ret && qemu_file_get_error(f)) {
ret = qemu_file_get_error(f); ret = qemu_file_get_error(f);
@ -4253,11 +4121,7 @@ static int parse_ramblocks(QEMUFile *f, ram_addr_t total_ram_bytes)
static int ram_load_precopy(QEMUFile *f) static int ram_load_precopy(QEMUFile *f)
{ {
MigrationIncomingState *mis = migration_incoming_get_current(); MigrationIncomingState *mis = migration_incoming_get_current();
int flags = 0, ret = 0, invalid_flags = 0, len = 0, i = 0; int flags = 0, ret = 0, invalid_flags = 0, i = 0;
if (!migrate_compress()) {
invalid_flags |= RAM_SAVE_FLAG_COMPRESS_PAGE;
}
if (migrate_mapped_ram()) { if (migrate_mapped_ram()) {
invalid_flags |= (RAM_SAVE_FLAG_HOOK | RAM_SAVE_FLAG_MULTIFD_FLUSH | invalid_flags |= (RAM_SAVE_FLAG_HOOK | RAM_SAVE_FLAG_MULTIFD_FLUSH |
@ -4294,16 +4158,12 @@ static int ram_load_precopy(QEMUFile *f)
if (flags & invalid_flags) { if (flags & invalid_flags) {
error_report("Unexpected RAM flags: %d", flags & invalid_flags); error_report("Unexpected RAM flags: %d", flags & invalid_flags);
if (flags & invalid_flags & RAM_SAVE_FLAG_COMPRESS_PAGE) {
error_report("Received an unexpected compressed page");
}
ret = -EINVAL; ret = -EINVAL;
break; break;
} }
if (flags & (RAM_SAVE_FLAG_ZERO | RAM_SAVE_FLAG_PAGE | if (flags & (RAM_SAVE_FLAG_ZERO | RAM_SAVE_FLAG_PAGE |
RAM_SAVE_FLAG_COMPRESS_PAGE | RAM_SAVE_FLAG_XBZRLE)) { RAM_SAVE_FLAG_XBZRLE)) {
RAMBlock *block = ram_block_from_stream(mis, f, flags, RAMBlock *block = ram_block_from_stream(mis, f, flags,
RAM_CHANNEL_PRECOPY); RAM_CHANNEL_PRECOPY);
@ -4372,16 +4232,6 @@ static int ram_load_precopy(QEMUFile *f)
qemu_get_buffer(f, host, TARGET_PAGE_SIZE); qemu_get_buffer(f, host, TARGET_PAGE_SIZE);
break; break;
case RAM_SAVE_FLAG_COMPRESS_PAGE:
len = qemu_get_be32(f);
if (len < 0 || len > compressBound(TARGET_PAGE_SIZE)) {
error_report("Invalid compressed data length: %d", len);
ret = -EINVAL;
break;
}
decompress_data_with_multi_threads(f, host, len);
break;
case RAM_SAVE_FLAG_XBZRLE: case RAM_SAVE_FLAG_XBZRLE:
if (load_xbzrle(f, addr, host) < 0) { if (load_xbzrle(f, addr, host) < 0) {
error_report("Failed to decompress XBZRLE page at " error_report("Failed to decompress XBZRLE page at "
@ -4423,7 +4273,6 @@ static int ram_load_precopy(QEMUFile *f)
} }
} }
ret |= wait_for_decompress_done();
return ret; return ret;
} }

View File

@ -1711,11 +1711,6 @@ static int qemu_savevm_state(QEMUFile *f, Error **errp)
return -EINVAL; return -EINVAL;
} }
if (migrate_block()) {
error_setg(errp, "Block migration and snapshots are incompatible");
return -EINVAL;
}
ret = migrate_init(ms, errp); ret = migrate_init(ms, errp);
if (ret) { if (ret) {
return ret; return ret;

View File

@ -152,7 +152,7 @@ multifd_set_outgoing_channel(void *ioc, const char *ioctype, const char *hostnam
# migration.c # migration.c
migrate_set_state(const char *new_state) "new state %s" migrate_set_state(const char *new_state) "new state %s"
migrate_fd_cleanup(void) "" migrate_fd_cleanup(void) ""
migrate_fd_error(const char *error_desc) "error=%s" migrate_error(const char *error_desc) "error=%s"
migrate_fd_cancel(void) "" migrate_fd_cancel(void) ""
migrate_handle_rp_req_pages(const char *rbname, size_t start, size_t len) "in %s at 0x%zx len 0x%zx" migrate_handle_rp_req_pages(const char *rbname, size_t start, size_t len) "in %s at 0x%zx len 0x%zx"
migrate_pending_exact(uint64_t size, uint64_t pre, uint64_t post) "exact pending size %" PRIu64 " (pre = %" PRIu64 " post=%" PRIu64 ")" migrate_pending_exact(uint64_t size, uint64_t pre, uint64_t post) "exact pending size %" PRIu64 " (pre = %" PRIu64 " post=%" PRIu64 ")"

View File

@ -23,9 +23,6 @@
# #
# @duplicate: number of duplicate (zero) pages (since 1.2) # @duplicate: number of duplicate (zero) pages (since 1.2)
# #
# @skipped: number of skipped zero pages. Always zero, only provided
# for compatibility (since 1.5)
#
# @normal: number of normal pages (since 1.2) # @normal: number of normal pages (since 1.2)
# #
# @normal-bytes: number of normal bytes sent (since 1.2) # @normal-bytes: number of normal bytes sent (since 1.2)
@ -63,16 +60,11 @@
# between 0 and @dirty-sync-count * @multifd-channels. (since # between 0 and @dirty-sync-count * @multifd-channels. (since
# 7.1) # 7.1)
# #
# Features:
#
# @deprecated: Member @skipped is always zero since 1.5.3
#
# Since: 0.14 # Since: 0.14
## ##
{ 'struct': 'MigrationStats', { 'struct': 'MigrationStats',
'data': {'transferred': 'int', 'remaining': 'int', 'total': 'int' , 'data': {'transferred': 'int', 'remaining': 'int', 'total': 'int' ,
'duplicate': 'int', 'duplicate': 'int',
'skipped': { 'type': 'int', 'features': [ 'deprecated' ] },
'normal': 'int', 'normal': 'int',
'normal-bytes': 'int', 'dirty-pages-rate': 'int', 'normal-bytes': 'int', 'dirty-pages-rate': 'int',
'mbps': 'number', 'dirty-sync-count': 'int', 'mbps': 'number', 'dirty-sync-count': 'int',
@ -201,9 +193,6 @@
# @ram: @MigrationStats containing detailed migration status, only # @ram: @MigrationStats containing detailed migration status, only
# returned if status is 'active' or 'completed'(since 1.2) # returned if status is 'active' or 'completed'(since 1.2)
# #
# @disk: @MigrationStats containing detailed disk migration status,
# only returned if status is 'active' and it is a block migration
#
# @xbzrle-cache: @XBZRLECacheStats containing detailed XBZRLE # @xbzrle-cache: @XBZRLECacheStats containing detailed XBZRLE
# migration statistics, only returned if XBZRLE feature is on and # migration statistics, only returned if XBZRLE feature is on and
# status is 'active' or 'completed' (since 1.2) # status is 'active' or 'completed' (since 1.2)
@ -240,10 +229,6 @@
# This is only present when the postcopy-blocktime migration # This is only present when the postcopy-blocktime migration
# capability is enabled. (Since 3.0) # capability is enabled. (Since 3.0)
# #
# @compression: migration compression statistics, only returned if
# compression feature is on and status is 'active' or 'completed'
# (Since 3.1)
#
# @socket-address: Only used for tcp, to know what the real port is # @socket-address: Only used for tcp, to know what the real port is
# (Since 4.0) # (Since 4.0)
# #
@ -268,19 +253,10 @@
# average memory load of the virtual CPU indirectly. Note that # average memory load of the virtual CPU indirectly. Note that
# zero means guest doesn't dirty memory. (Since 8.1) # zero means guest doesn't dirty memory. (Since 8.1)
# #
# Features:
#
# @deprecated: Member @disk is deprecated because block migration is.
# Member @compression is deprecated because it is unreliable and
# untested. It is recommended to use multifd migration, which
# offers an alternative compression implementation that is
# reliable and tested.
#
# Since: 0.14 # Since: 0.14
## ##
{ 'struct': 'MigrationInfo', { 'struct': 'MigrationInfo',
'data': {'*status': 'MigrationStatus', '*ram': 'MigrationStats', 'data': {'*status': 'MigrationStatus', '*ram': 'MigrationStats',
'*disk': { 'type': 'MigrationStats', 'features': [ 'deprecated' ] },
'*vfio': 'VfioStats', '*vfio': 'VfioStats',
'*xbzrle-cache': 'XBZRLECacheStats', '*xbzrle-cache': 'XBZRLECacheStats',
'*total-time': 'int', '*total-time': 'int',
@ -292,7 +268,6 @@
'*blocked-reasons': ['str'], '*blocked-reasons': ['str'],
'*postcopy-blocktime': 'uint32', '*postcopy-blocktime': 'uint32',
'*postcopy-vcpu-blocktime': ['uint32'], '*postcopy-vcpu-blocktime': ['uint32'],
'*compression': { 'type': 'CompressionStats', 'features': [ 'deprecated' ] },
'*socket-address': ['SocketAddress'], '*socket-address': ['SocketAddress'],
'*dirty-limit-throttle-time-per-round': 'uint64', '*dirty-limit-throttle-time-per-round': 'uint64',
'*dirty-limit-ring-full-time': 'uint64'} } '*dirty-limit-ring-full-time': 'uint64'} }
@ -302,8 +277,7 @@
# #
# Returns information about current migration process. If migration # Returns information about current migration process. If migration
# is active there will be another json-object with RAM migration # is active there will be another json-object with RAM migration
# status and if block migration is active another one with block # status.
# migration status.
# #
# Returns: @MigrationInfo # Returns: @MigrationInfo
# #
@ -341,7 +315,7 @@
# -> { "execute": "query-migrate" } # -> { "execute": "query-migrate" }
# <- { "return": { "status": "failed" } } # <- { "return": { "status": "failed" } }
# #
# 4. Migration is being performed and is not a block migration: # 4. Migration is being performed:
# #
# -> { "execute": "query-migrate" } # -> { "execute": "query-migrate" }
# <- { # <- {
@ -362,33 +336,7 @@
# } # }
# } # }
# #
# 5. Migration is being performed and is a block migration: # 5. Migration is being performed and XBZRLE is active:
#
# -> { "execute": "query-migrate" }
# <- {
# "return":{
# "status":"active",
# "total-time":12345,
# "setup-time":12345,
# "expected-downtime":12345,
# "ram":{
# "total":1057024,
# "remaining":1053304,
# "transferred":3720,
# "duplicate":123,
# "normal":123,
# "normal-bytes":123456,
# "dirty-sync-count":15
# },
# "disk":{
# "total":20971520,
# "remaining":20880384,
# "transferred":91136
# }
# }
# }
#
# 6. Migration is being performed and XBZRLE is active:
# #
# -> { "execute": "query-migrate" } # -> { "execute": "query-migrate" }
# <- { # <- {
@ -441,14 +389,6 @@
# capability on the source VM. The feature is disabled by default. # capability on the source VM. The feature is disabled by default.
# (since 1.6) # (since 1.6)
# #
# @compress: Use multiple compression threads to accelerate live
# migration. This feature can help to reduce the migration
# traffic, by sending compressed pages. Please note that if
# compress and xbzrle are both on, compress only takes effect in
# the ram bulk stage, after that, it will be disabled and only
# xbzrle takes effect, this can help to minimize migration
# traffic. The feature is disabled by default. (since 2.4)
#
# @events: generate events for each migration state change (since 2.4) # @events: generate events for each migration state change (since 2.4)
# #
# @auto-converge: If enabled, QEMU will automatically throttle down # @auto-converge: If enabled, QEMU will automatically throttle down
@ -468,11 +408,6 @@
# @release-ram: if enabled, qemu will free the migrated ram pages on # @release-ram: if enabled, qemu will free the migrated ram pages on
# the source during postcopy-ram migration. (since 2.9) # the source during postcopy-ram migration. (since 2.9)
# #
# @block: If enabled, QEMU will also migrate the contents of all block
# devices. Default is disabled. A possible alternative uses
# mirror jobs to a builtin NBD server on the destination, which
# offers more flexibility. (Since 2.10)
#
# @return-path: If enabled, migration will use the return path even # @return-path: If enabled, migration will use the return path even
# for precopy. (since 2.10) # for precopy. (since 2.10)
# #
@ -536,23 +471,15 @@
# #
# Features: # Features:
# #
# @deprecated: Member @block is deprecated. Use blockdev-mirror with
# NBD instead. Member @compress is deprecated because it is
# unreliable and untested. It is recommended to use multifd
# migration, which offers an alternative compression
# implementation that is reliable and tested.
#
# @unstable: Members @x-colo and @x-ignore-shared are experimental. # @unstable: Members @x-colo and @x-ignore-shared are experimental.
# #
# Since: 1.2 # Since: 1.2
## ##
{ 'enum': 'MigrationCapability', { 'enum': 'MigrationCapability',
'data': ['xbzrle', 'rdma-pin-all', 'auto-converge', 'zero-blocks', 'data': ['xbzrle', 'rdma-pin-all', 'auto-converge', 'zero-blocks',
{ 'name': 'compress', 'features': [ 'deprecated' ] },
'events', 'postcopy-ram', 'events', 'postcopy-ram',
{ 'name': 'x-colo', 'features': [ 'unstable' ] }, { 'name': 'x-colo', 'features': [ 'unstable' ] },
'release-ram', 'release-ram',
{ 'name': 'block', 'features': [ 'deprecated' ] },
'return-path', 'pause-before-switchover', 'multifd', 'return-path', 'pause-before-switchover', 'multifd',
'dirty-bitmaps', 'postcopy-blocktime', 'late-block-activate', 'dirty-bitmaps', 'postcopy-blocktime', 'late-block-activate',
{ 'name': 'x-ignore-shared', 'features': [ 'unstable' ] }, { 'name': 'x-ignore-shared', 'features': [ 'unstable' ] },
@ -609,7 +536,6 @@
# {"state": false, "capability": "rdma-pin-all"}, # {"state": false, "capability": "rdma-pin-all"},
# {"state": false, "capability": "auto-converge"}, # {"state": false, "capability": "auto-converge"},
# {"state": false, "capability": "zero-blocks"}, # {"state": false, "capability": "zero-blocks"},
# {"state": false, "capability": "compress"},
# {"state": true, "capability": "events"}, # {"state": true, "capability": "events"},
# {"state": false, "capability": "postcopy-ram"}, # {"state": false, "capability": "postcopy-ram"},
# {"state": false, "capability": "x-colo"} # {"state": false, "capability": "x-colo"}
@ -757,27 +683,6 @@
# @announce-step: Increase in delay (in milliseconds) between # @announce-step: Increase in delay (in milliseconds) between
# subsequent packets in the announcement (Since 4.0) # subsequent packets in the announcement (Since 4.0)
# #
# @compress-level: Set the compression level to be used in live
# migration, the compression level is an integer between 0 and 9,
# where 0 means no compression, 1 means the best compression
# speed, and 9 means best compression ratio which will consume
# more CPU.
#
# @compress-threads: Set compression thread count to be used in live
# migration, the compression thread count is an integer between 1
# and 255.
#
# @compress-wait-thread: Controls behavior when all compression
# threads are currently busy. If true (default), wait for a free
# compression thread to become available; otherwise, send the page
# uncompressed. (Since 3.1)
#
# @decompress-threads: Set decompression thread count to be used in
# live migration, the decompression thread count is an integer
# between 1 and 255. Usually, decompression is at least 4 times as
# fast as compression, so set the decompress-threads to the number
# about 1/4 of compress-threads is adequate.
#
# @throttle-trigger-threshold: The ratio of bytes_dirty_period and # @throttle-trigger-threshold: The ratio of bytes_dirty_period and
# bytes_xfer_period to trigger throttling. It is expressed as # bytes_xfer_period to trigger throttling. It is expressed as
# percentage. The default value is 50. (Since 5.0) # percentage. The default value is 50. (Since 5.0)
@ -847,13 +752,6 @@
# @x-checkpoint-delay: The delay time (in ms) between two COLO # @x-checkpoint-delay: The delay time (in ms) between two COLO
# checkpoints in periodic mode. (Since 2.8) # checkpoints in periodic mode. (Since 2.8)
# #
# @block-incremental: Affects how much storage is migrated when the
# block migration capability is enabled. When false, the entire
# storage backing chain is migrated into a flattened image at the
# destination; when true, only the active qcow2 layer is migrated
# and the destination must already have access to the same backing
# chain as was used on the source. (since 2.10)
#
# @multifd-channels: Number of channels used to migrate data in # @multifd-channels: Number of channels used to migrate data in
# parallel. This is the same number that the number of sockets # parallel. This is the same number that the number of sockets
# used for migration. The default value is 2 (since 4.0) # used for migration. The default value is 2 (since 4.0)
@ -916,11 +814,6 @@
# #
# Features: # Features:
# #
# @deprecated: Member @block-incremental is deprecated. Use
# blockdev-mirror with NBD instead. Members @compress-level,
# @compress-threads, @decompress-threads and @compress-wait-thread
# are deprecated because @compression is deprecated.
#
# @unstable: Members @x-checkpoint-delay and # @unstable: Members @x-checkpoint-delay and
# @x-vcpu-dirty-limit-period are experimental. # @x-vcpu-dirty-limit-period are experimental.
# #
@ -929,17 +822,12 @@
{ 'enum': 'MigrationParameter', { 'enum': 'MigrationParameter',
'data': ['announce-initial', 'announce-max', 'data': ['announce-initial', 'announce-max',
'announce-rounds', 'announce-step', 'announce-rounds', 'announce-step',
{ 'name': 'compress-level', 'features': [ 'deprecated' ] },
{ 'name': 'compress-threads', 'features': [ 'deprecated' ] },
{ 'name': 'decompress-threads', 'features': [ 'deprecated' ] },
{ 'name': 'compress-wait-thread', 'features': [ 'deprecated' ] },
'throttle-trigger-threshold', 'throttle-trigger-threshold',
'cpu-throttle-initial', 'cpu-throttle-increment', 'cpu-throttle-initial', 'cpu-throttle-increment',
'cpu-throttle-tailslow', 'cpu-throttle-tailslow',
'tls-creds', 'tls-hostname', 'tls-authz', 'max-bandwidth', 'tls-creds', 'tls-hostname', 'tls-authz', 'max-bandwidth',
'avail-switchover-bandwidth', 'downtime-limit', 'avail-switchover-bandwidth', 'downtime-limit',
{ 'name': 'x-checkpoint-delay', 'features': [ 'unstable' ] }, { 'name': 'x-checkpoint-delay', 'features': [ 'unstable' ] },
{ 'name': 'block-incremental', 'features': [ 'deprecated' ] },
'multifd-channels', 'multifd-channels',
'xbzrle-cache-size', 'max-postcopy-bandwidth', 'xbzrle-cache-size', 'max-postcopy-bandwidth',
'max-cpu-throttle', 'multifd-compression', 'max-cpu-throttle', 'multifd-compression',
@ -965,27 +853,6 @@
# @announce-step: Increase in delay (in milliseconds) between # @announce-step: Increase in delay (in milliseconds) between
# subsequent packets in the announcement (Since 4.0) # subsequent packets in the announcement (Since 4.0)
# #
# @compress-level: Set the compression level to be used in live
# migration, the compression level is an integer between 0 and 9,
# where 0 means no compression, 1 means the best compression
# speed, and 9 means best compression ratio which will consume
# more CPU.
#
# @compress-threads: Set compression thread count to be used in live
# migration, the compression thread count is an integer between 1
# and 255.
#
# @compress-wait-thread: Controls behavior when all compression
# threads are currently busy. If true (default), wait for a free
# compression thread to become available; otherwise, send the page
# uncompressed. (Since 3.1)
#
# @decompress-threads: Set decompression thread count to be used in
# live migration, the decompression thread count is an integer
# between 1 and 255. Usually, decompression is at least 4 times as
# fast as compression, so set the decompress-threads to the number
# about 1/4 of compress-threads is adequate.
#
# @throttle-trigger-threshold: The ratio of bytes_dirty_period and # @throttle-trigger-threshold: The ratio of bytes_dirty_period and
# bytes_xfer_period to trigger throttling. It is expressed as # bytes_xfer_period to trigger throttling. It is expressed as
# percentage. The default value is 50. (Since 5.0) # percentage. The default value is 50. (Since 5.0)
@ -1055,13 +922,6 @@
# @x-checkpoint-delay: The delay time (in ms) between two COLO # @x-checkpoint-delay: The delay time (in ms) between two COLO
# checkpoints in periodic mode. (Since 2.8) # checkpoints in periodic mode. (Since 2.8)
# #
# @block-incremental: Affects how much storage is migrated when the
# block migration capability is enabled. When false, the entire
# storage backing chain is migrated into a flattened image at the
# destination; when true, only the active qcow2 layer is migrated
# and the destination must already have access to the same backing
# chain as was used on the source. (since 2.10)
#
# @multifd-channels: Number of channels used to migrate data in # @multifd-channels: Number of channels used to migrate data in
# parallel. This is the same number that the number of sockets # parallel. This is the same number that the number of sockets
# used for migration. The default value is 2 (since 4.0) # used for migration. The default value is 2 (since 4.0)
@ -1124,11 +984,6 @@
# #
# Features: # Features:
# #
# @deprecated: Member @block-incremental is deprecated. Use
# blockdev-mirror with NBD instead. Members @compress-level,
# @compress-threads, @decompress-threads and @compress-wait-thread
# are deprecated because @compression is deprecated.
#
# @unstable: Members @x-checkpoint-delay and # @unstable: Members @x-checkpoint-delay and
# @x-vcpu-dirty-limit-period are experimental. # @x-vcpu-dirty-limit-period are experimental.
# #
@ -1142,14 +997,6 @@
'*announce-max': 'size', '*announce-max': 'size',
'*announce-rounds': 'size', '*announce-rounds': 'size',
'*announce-step': 'size', '*announce-step': 'size',
'*compress-level': { 'type': 'uint8',
'features': [ 'deprecated' ] },
'*compress-threads': { 'type': 'uint8',
'features': [ 'deprecated' ] },
'*compress-wait-thread': { 'type': 'bool',
'features': [ 'deprecated' ] },
'*decompress-threads': { 'type': 'uint8',
'features': [ 'deprecated' ] },
'*throttle-trigger-threshold': 'uint8', '*throttle-trigger-threshold': 'uint8',
'*cpu-throttle-initial': 'uint8', '*cpu-throttle-initial': 'uint8',
'*cpu-throttle-increment': 'uint8', '*cpu-throttle-increment': 'uint8',
@ -1162,8 +1009,6 @@
'*downtime-limit': 'uint64', '*downtime-limit': 'uint64',
'*x-checkpoint-delay': { 'type': 'uint32', '*x-checkpoint-delay': { 'type': 'uint32',
'features': [ 'unstable' ] }, 'features': [ 'unstable' ] },
'*block-incremental': { 'type': 'bool',
'features': [ 'deprecated' ] },
'*multifd-channels': 'uint8', '*multifd-channels': 'uint8',
'*xbzrle-cache-size': 'size', '*xbzrle-cache-size': 'size',
'*max-postcopy-bandwidth': 'size', '*max-postcopy-bandwidth': 'size',
@ -1211,17 +1056,6 @@
# @announce-step: Increase in delay (in milliseconds) between # @announce-step: Increase in delay (in milliseconds) between
# subsequent packets in the announcement (Since 4.0) # subsequent packets in the announcement (Since 4.0)
# #
# @compress-level: compression level
#
# @compress-threads: compression thread count
#
# @compress-wait-thread: Controls behavior when all compression
# threads are currently busy. If true (default), wait for a free
# compression thread to become available; otherwise, send the page
# uncompressed. (Since 3.1)
#
# @decompress-threads: decompression thread count
#
# @throttle-trigger-threshold: The ratio of bytes_dirty_period and # @throttle-trigger-threshold: The ratio of bytes_dirty_period and
# bytes_xfer_period to trigger throttling. It is expressed as # bytes_xfer_period to trigger throttling. It is expressed as
# percentage. The default value is 50. (Since 5.0) # percentage. The default value is 50. (Since 5.0)
@ -1287,13 +1121,6 @@
# @x-checkpoint-delay: the delay time between two COLO checkpoints. # @x-checkpoint-delay: the delay time between two COLO checkpoints.
# (Since 2.8) # (Since 2.8)
# #
# @block-incremental: Affects how much storage is migrated when the
# block migration capability is enabled. When false, the entire
# storage backing chain is migrated into a flattened image at the
# destination; when true, only the active qcow2 layer is migrated
# and the destination must already have access to the same backing
# chain as was used on the source. (since 2.10)
#
# @multifd-channels: Number of channels used to migrate data in # @multifd-channels: Number of channels used to migrate data in
# parallel. This is the same number that the number of sockets # parallel. This is the same number that the number of sockets
# used for migration. The default value is 2 (since 4.0) # used for migration. The default value is 2 (since 4.0)
@ -1356,11 +1183,6 @@
# #
# Features: # Features:
# #
# @deprecated: Member @block-incremental is deprecated. Use
# blockdev-mirror with NBD instead. Members @compress-level,
# @compress-threads, @decompress-threads and @compress-wait-thread
# are deprecated because @compression is deprecated.
#
# @unstable: Members @x-checkpoint-delay and # @unstable: Members @x-checkpoint-delay and
# @x-vcpu-dirty-limit-period are experimental. # @x-vcpu-dirty-limit-period are experimental.
# #
@ -1371,14 +1193,6 @@
'*announce-max': 'size', '*announce-max': 'size',
'*announce-rounds': 'size', '*announce-rounds': 'size',
'*announce-step': 'size', '*announce-step': 'size',
'*compress-level': { 'type': 'uint8',
'features': [ 'deprecated' ] },
'*compress-threads': { 'type': 'uint8',
'features': [ 'deprecated' ] },
'*compress-wait-thread': { 'type': 'bool',
'features': [ 'deprecated' ] },
'*decompress-threads': { 'type': 'uint8',
'features': [ 'deprecated' ] },
'*throttle-trigger-threshold': 'uint8', '*throttle-trigger-threshold': 'uint8',
'*cpu-throttle-initial': 'uint8', '*cpu-throttle-initial': 'uint8',
'*cpu-throttle-increment': 'uint8', '*cpu-throttle-increment': 'uint8',
@ -1391,8 +1205,6 @@
'*downtime-limit': 'uint64', '*downtime-limit': 'uint64',
'*x-checkpoint-delay': { 'type': 'uint32', '*x-checkpoint-delay': { 'type': 'uint32',
'features': [ 'unstable' ] }, 'features': [ 'unstable' ] },
'*block-incremental': { 'type': 'bool',
'features': [ 'deprecated' ] },
'*multifd-channels': 'uint8', '*multifd-channels': 'uint8',
'*xbzrle-cache-size': 'size', '*xbzrle-cache-size': 'size',
'*max-postcopy-bandwidth': 'size', '*max-postcopy-bandwidth': 'size',
@ -1742,20 +1554,11 @@
# @channels: list of migration stream channels with each stream in the # @channels: list of migration stream channels with each stream in the
# list connected to a destination interface endpoint. # list connected to a destination interface endpoint.
# #
# @blk: do block migration (full disk copy)
#
# @inc: incremental disk copy migration
#
# @detach: this argument exists only for compatibility reasons and is # @detach: this argument exists only for compatibility reasons and is
# ignored by QEMU # ignored by QEMU
# #
# @resume: resume one paused migration, default "off". (since 3.0) # @resume: resume one paused migration, default "off". (since 3.0)
# #
# Features:
#
# @deprecated: Members @inc and @blk are deprecated. Use
# blockdev-mirror with NBD instead.
#
# Since: 0.14 # Since: 0.14
# #
# Notes: # Notes:
@ -1821,8 +1624,6 @@
{ 'command': 'migrate', { 'command': 'migrate',
'data': {'*uri': 'str', 'data': {'*uri': 'str',
'*channels': [ 'MigrationChannel' ], '*channels': [ 'MigrationChannel' ],
'*blk': { 'type': 'bool', 'features': [ 'deprecated' ] },
'*inc': { 'type': 'bool', 'features': [ 'deprecated' ] },
'*detach': 'bool', '*resume': 'bool' } } '*detach': 'bool', '*resume': 'bool' } }
## ##
@ -1837,6 +1638,10 @@
# @channels: list of migration stream channels with each stream in the # @channels: list of migration stream channels with each stream in the
# list connected to a destination interface endpoint. # list connected to a destination interface endpoint.
# #
# @exit-on-error: Exit on incoming migration failure. Default true.
# When set to false, the failure triggers a MIGRATION event, and
# error details could be retrieved with query-migrate. (since 9.1)
#
# Since: 2.3 # Since: 2.3
# #
# Notes: # Notes:
@ -1889,7 +1694,8 @@
## ##
{ 'command': 'migrate-incoming', { 'command': 'migrate-incoming',
'data': {'*uri': 'str', 'data': {'*uri': 'str',
'*channels': [ 'MigrationChannel' ] } } '*channels': [ 'MigrationChannel' ],
'*exit-on-error': 'bool' } }
## ##
# @xen-save-devices-state: # @xen-save-devices-state:

View File

@ -143,8 +143,6 @@ meson_options_help() {
printf "%s\n" ' libvduse build VDUSE Library' printf "%s\n" ' libvduse build VDUSE Library'
printf "%s\n" ' linux-aio Linux AIO support' printf "%s\n" ' linux-aio Linux AIO support'
printf "%s\n" ' linux-io-uring Linux io_uring support' printf "%s\n" ' linux-io-uring Linux io_uring support'
printf "%s\n" ' live-block-migration'
printf "%s\n" ' block migration in the main migration stream'
printf "%s\n" ' lzfse lzfse support for DMG images' printf "%s\n" ' lzfse lzfse support for DMG images'
printf "%s\n" ' lzo lzo compression support' printf "%s\n" ' lzo lzo compression support'
printf "%s\n" ' malloc-trim enable libc malloc_trim() for memory optimization' printf "%s\n" ' malloc-trim enable libc malloc_trim() for memory optimization'
@ -382,8 +380,6 @@ _meson_option_parse() {
--disable-linux-aio) printf "%s" -Dlinux_aio=disabled ;; --disable-linux-aio) printf "%s" -Dlinux_aio=disabled ;;
--enable-linux-io-uring) printf "%s" -Dlinux_io_uring=enabled ;; --enable-linux-io-uring) printf "%s" -Dlinux_io_uring=enabled ;;
--disable-linux-io-uring) printf "%s" -Dlinux_io_uring=disabled ;; --disable-linux-io-uring) printf "%s" -Dlinux_io_uring=disabled ;;
--enable-live-block-migration) printf "%s" -Dlive_block_migration=enabled ;;
--disable-live-block-migration) printf "%s" -Dlive_block_migration=disabled ;;
--localedir=*) quote_sh "-Dlocaledir=$2" ;; --localedir=*) quote_sh "-Dlocaledir=$2" ;;
--localstatedir=*) quote_sh "-Dlocalstatedir=$2" ;; --localstatedir=*) quote_sh "-Dlocalstatedir=$2" ;;
--enable-lzfse) printf "%s" -Dlzfse=enabled ;; --enable-lzfse) printf "%s" -Dlzfse=enabled ;;

View File

@ -2723,7 +2723,8 @@ void qmp_x_exit_preconfig(Error **errp)
if (incoming) { if (incoming) {
Error *local_err = NULL; Error *local_err = NULL;
if (strcmp(incoming, "defer") != 0) { if (strcmp(incoming, "defer") != 0) {
qmp_migrate_incoming(incoming, false, NULL, &local_err); qmp_migrate_incoming(incoming, false, NULL, true, true,
&local_err);
if (local_err) { if (local_err) {
error_reportf_err(local_err, "-incoming %s: ", incoming); error_reportf_err(local_err, "-incoming %s: ", incoming);
exit(1); exit(1);

View File

@ -1,147 +0,0 @@
#!/usr/bin/env bash
# group: rw migration quick
#
# Test old-style block migration (migrate -b)
#
# Copyright (C) 2017 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/>.
#
# creator
owner=kwolf@redhat.com
seq=`basename $0`
echo "QA output created by $seq"
status=1 # failure is the default!
MIG_SOCKET="${SOCK_DIR}/migrate"
_cleanup()
{
rm -f "${MIG_SOCKET}"
_rm_test_img "${TEST_IMG}.dest"
_cleanup_test_img
_cleanup_qemu
}
trap "_cleanup; exit \$status" 0 1 2 3 15
# get standard environment, filters and checks
. ./common.rc
. ./common.filter
. ./common.qemu
_supported_os Linux FreeBSD NetBSD
_supported_fmt qcow2 raw qed quorum
_supported_proto file fuse
size=64M
_make_test_img $size
TEST_IMG="${TEST_IMG}.dest" _make_test_img $size
echo
echo === Starting VMs ===
echo
qemu_comm_method="qmp"
_launch_qemu \
-drive file="${TEST_IMG}",cache=$CACHEMODE,aio=$AIOMODE,driver=$IMGFMT,id=disk
src=$QEMU_HANDLE
_send_qemu_cmd $src "{ 'execute': 'qmp_capabilities' }" 'return'
_launch_qemu \
-drive file="${TEST_IMG}.dest",cache=$CACHEMODE,aio=$AIOMODE,driver=$IMGFMT,id=disk \
-incoming "unix:${MIG_SOCKET}"
dest=$QEMU_HANDLE
_send_qemu_cmd $dest "{ 'execute': 'qmp_capabilities' }" 'return'
echo
echo === Write something on the source ===
echo
_send_qemu_cmd $src \
"{ 'execute': 'human-monitor-command',
'arguments': { 'command-line':
'qemu-io disk \"write -P 0x55 0 64k\"' } }" \
'return'
_send_qemu_cmd $src \
"{ 'execute': 'human-monitor-command',
'arguments': { 'command-line':
'qemu-io disk \"read -P 0x55 0 64k\"' } }" \
'return'
echo
echo === Do block migration to destination ===
echo
reply="$(_send_qemu_cmd $src \
"{ 'execute': 'migrate',
'arguments': { 'uri': 'unix:${MIG_SOCKET}', 'blk': true } }" \
'return\|error' | _filter_migration_block_deprecated)"
echo "$reply"
if echo "$reply" | grep "compiled without old-style" > /dev/null; then
_notrun "migrate -b support not compiled in"
fi
timeout_comm=$QEMU_COMM_TIMEOUT
if [ "${VALGRIND_QEMU}" == "y" ]; then
QEMU_COMM_TIMEOUT=4
else
QEMU_COMM_TIMEOUT=0.1
fi
qemu_cmd_repeat=50 silent=yes \
_send_qemu_cmd $src "{ 'execute': 'query-migrate' }" '"status": "completed"'
QEMU_COMM_TIMEOUT=$timeout_comm
_send_qemu_cmd $src "{ 'execute': 'query-status' }" "return"
echo
echo === Do some I/O on the destination ===
echo
# It is important that we use the BlockBackend of the guest device here instead
# of the node name, which would create a new BlockBackend and not test whether
# the guest has the necessary permissions to access the image now
silent=yes _send_qemu_cmd $dest "" "100 %"
_send_qemu_cmd $dest "{ 'execute': 'query-status' }" "return"
_send_qemu_cmd $dest \
"{ 'execute': 'human-monitor-command',
'arguments': { 'command-line':
'qemu-io disk \"read -P 0x55 0 64k\"' } }" \
'return'
_send_qemu_cmd $dest \
"{ 'execute': 'human-monitor-command',
'arguments': { 'command-line':
'qemu-io disk \"write -P 0x66 1M 64k\"' } }" \
'return'
echo
echo === Shut down and check image ===
echo
_send_qemu_cmd $src '{"execute":"quit"}' 'return'
_send_qemu_cmd $dest '{"execute":"quit"}' 'return'
wait=1 _cleanup_qemu
_check_test_img
TEST_IMG="${TEST_IMG}.dest" _check_test_img
$QEMU_IO -c 'write -P 0x66 1M 64k' "$TEST_IMG" | _filter_qemu_io
$QEMU_IMG compare "$TEST_IMG.dest" "$TEST_IMG"
# success, all done
echo "*** done"
rm -f $seq.full
status=0

View File

@ -1,66 +0,0 @@
QA output created by 183
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
Formatting 'TEST_DIR/t.IMGFMT.dest', fmt=IMGFMT size=67108864
=== Starting VMs ===
{ 'execute': 'qmp_capabilities' }
{"return": {}}
{ 'execute': 'qmp_capabilities' }
{"return": {}}
=== Write something on the source ===
{ 'execute': 'human-monitor-command',
'arguments': { 'command-line':
'qemu-io disk "write -P 0x55 0 64k"' } }
wrote 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{"return": ""}
{ 'execute': 'human-monitor-command',
'arguments': { 'command-line':
'qemu-io disk "read -P 0x55 0 64k"' } }
read 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{"return": ""}
=== Do block migration to destination ===
{ 'execute': 'migrate',
'arguments': { 'uri': 'unix:SOCK_DIR/migrate', 'blk': true } }
{"return": {}}
{ 'execute': 'query-status' }
{"return": {"status": "postmigrate", "running": false}}
=== Do some I/O on the destination ===
{ 'execute': 'query-status' }
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "RESUME"}
{"return": {"status": "running", "running": true}}
{ 'execute': 'human-monitor-command',
'arguments': { 'command-line':
'qemu-io disk "read -P 0x55 0 64k"' } }
read 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{"return": ""}
{ 'execute': 'human-monitor-command',
'arguments': { 'command-line':
'qemu-io disk "write -P 0x66 1M 64k"' } }
wrote 65536/65536 bytes at offset 1048576
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{"return": ""}
=== Shut down and check image ===
{"execute":"quit"}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
{"return": {}}
{"execute":"quit"}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
{"return": {}}
No errors were found on the image.
No errors were found on the image.
wrote 65536/65536 bytes at offset 1048576
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
Images are identical.
*** done

View File

@ -359,12 +359,5 @@ _filter_qcow2_compression_type_bit()
-e 's/\(incompatible_features.*\), 3\(,.*\)/\1\2/' -e 's/\(incompatible_features.*\), 3\(,.*\)/\1\2/'
} }
# filter warnings caused for block migration deprecation
_filter_migration_block_deprecated()
{
gsed -e '/warning: parameter .blk. is deprecated; use blockdev-mirror with NBD instead/d' \
-e '/warning: block migration is deprecated; use blockdev-mirror with NBD instead/d'
}
# make sure this script returns success # make sure this script returns success
true true

View File

@ -427,38 +427,6 @@ static void migrate_set_parameter_str(QTestState *who, const char *parameter,
migrate_check_parameter_str(who, parameter, value); migrate_check_parameter_str(who, parameter, value);
} }
static long long migrate_get_parameter_bool(QTestState *who,
const char *parameter)
{
QDict *rsp;
int result;
rsp = qtest_qmp_assert_success_ref(
who, "{ 'execute': 'query-migrate-parameters' }");
result = qdict_get_bool(rsp, parameter);
qobject_unref(rsp);
return !!result;
}
static void migrate_check_parameter_bool(QTestState *who, const char *parameter,
int value)
{
int result;
result = migrate_get_parameter_bool(who, parameter);
g_assert_cmpint(result, ==, value);
}
static void migrate_set_parameter_bool(QTestState *who, const char *parameter,
int value)
{
qtest_qmp_assert_success(who,
"{ 'execute': 'migrate-set-parameters',"
"'arguments': { %s: %i } }",
parameter, value);
migrate_check_parameter_bool(who, parameter, value);
}
static void migrate_ensure_non_converge(QTestState *who) static void migrate_ensure_non_converge(QTestState *who)
{ {
/* Can't converge with 1ms downtime + 3 mbs bandwidth limit */ /* Can't converge with 1ms downtime + 3 mbs bandwidth limit */
@ -1240,36 +1208,6 @@ test_migrate_tls_x509_finish(QTestState *from,
#endif /* CONFIG_TASN1 */ #endif /* CONFIG_TASN1 */
#endif /* CONFIG_GNUTLS */ #endif /* CONFIG_GNUTLS */
static void *
test_migrate_compress_start(QTestState *from,
QTestState *to)
{
migrate_set_parameter_int(from, "compress-level", 1);
migrate_set_parameter_int(from, "compress-threads", 4);
migrate_set_parameter_bool(from, "compress-wait-thread", true);
migrate_set_parameter_int(to, "decompress-threads", 4);
migrate_set_capability(from, "compress", true);
migrate_set_capability(to, "compress", true);
return NULL;
}
static void *
test_migrate_compress_nowait_start(QTestState *from,
QTestState *to)
{
migrate_set_parameter_int(from, "compress-level", 9);
migrate_set_parameter_int(from, "compress-threads", 1);
migrate_set_parameter_bool(from, "compress-wait-thread", false);
migrate_set_parameter_int(to, "decompress-threads", 1);
migrate_set_capability(from, "compress", true);
migrate_set_capability(to, "compress", true);
return NULL;
}
static int migrate_postcopy_prepare(QTestState **from_ptr, static int migrate_postcopy_prepare(QTestState **from_ptr,
QTestState **to_ptr, QTestState **to_ptr,
MigrateCommon *args) MigrateCommon *args)
@ -1370,15 +1308,6 @@ static void test_postcopy_suspend(void)
test_postcopy_common(&args); test_postcopy_common(&args);
} }
static void test_postcopy_compress(void)
{
MigrateCommon args = {
.start_hook = test_migrate_compress_start
};
test_postcopy_common(&args);
}
static void test_postcopy_preempt(void) static void test_postcopy_preempt(void)
{ {
MigrateCommon args = { MigrateCommon args = {
@ -1561,15 +1490,6 @@ static void test_postcopy_recovery(void)
test_postcopy_recovery_common(&args); test_postcopy_recovery_common(&args);
} }
static void test_postcopy_recovery_compress(void)
{
MigrateCommon args = {
.start_hook = test_migrate_compress_start
};
test_postcopy_recovery_common(&args);
}
#ifndef _WIN32 #ifndef _WIN32
static void test_postcopy_recovery_double_fail(void) static void test_postcopy_recovery_double_fail(void)
{ {
@ -2027,48 +1947,6 @@ static void test_precopy_unix_xbzrle(void)
test_precopy_common(&args); test_precopy_common(&args);
} }
static void test_precopy_unix_compress(void)
{
g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
MigrateCommon args = {
.connect_uri = uri,
.listen_uri = uri,
.start_hook = test_migrate_compress_start,
/*
* Test that no invalid thread state is left over from
* the previous iteration.
*/
.iterations = 2,
/*
* We make sure the compressor can always work well even if guest
* memory is changing. See commit 34ab9e9743 where we used to fix
* a bug when only trigger-able with guest memory changing.
*/
.live = true,
};
test_precopy_common(&args);
}
static void test_precopy_unix_compress_nowait(void)
{
g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
MigrateCommon args = {
.connect_uri = uri,
.listen_uri = uri,
.start_hook = test_migrate_compress_nowait_start,
/*
* Test that no invalid thread state is left over from
* the previous iteration.
*/
.iterations = 2,
/* Same reason for the wait version of precopy compress test */
.live = true,
};
test_precopy_common(&args);
}
static void test_precopy_file(void) static void test_precopy_file(void)
{ {
g_autofree char *uri = g_strdup_printf("file:%s/%s", tmpfs, g_autofree char *uri = g_strdup_printf("file:%s/%s", tmpfs,
@ -3597,12 +3475,6 @@ int main(int argc, char **argv)
test_postcopy_preempt); test_postcopy_preempt);
migration_test_add("/migration/postcopy/preempt/recovery/plain", migration_test_add("/migration/postcopy/preempt/recovery/plain",
test_postcopy_preempt_recovery); test_postcopy_preempt_recovery);
if (getenv("QEMU_TEST_FLAKY_TESTS")) {
migration_test_add("/migration/postcopy/compress/plain",
test_postcopy_compress);
migration_test_add("/migration/postcopy/recovery/compress/plain",
test_postcopy_recovery_compress);
}
#ifndef _WIN32 #ifndef _WIN32
migration_test_add("/migration/postcopy/recovery/double-failures", migration_test_add("/migration/postcopy/recovery/double-failures",
test_postcopy_recovery_double_fail); test_postcopy_recovery_double_fail);
@ -3623,17 +3495,6 @@ int main(int argc, char **argv)
test_precopy_unix_plain); test_precopy_unix_plain);
migration_test_add("/migration/precopy/unix/xbzrle", migration_test_add("/migration/precopy/unix/xbzrle",
test_precopy_unix_xbzrle); test_precopy_unix_xbzrle);
/*
* Compression fails from time to time.
* Put test here but don't enable it until everything is fixed.
*/
if (getenv("QEMU_TEST_FLAKY_TESTS")) {
migration_test_add("/migration/precopy/unix/compress/wait",
test_precopy_unix_compress);
migration_test_add("/migration/precopy/unix/compress/nowait",
test_precopy_unix_compress_nowait);
}
migration_test_add("/migration/precopy/file", migration_test_add("/migration/precopy/file",
test_precopy_file); test_precopy_file);
migration_test_add("/migration/precopy/file/offset", migration_test_add("/migration/precopy/file/offset",