Expand Up
@@ -67,19 +67,10 @@
#define MAX_THROTTLE (128 << 20) /* Migration transfer speed throttling */
/* Amount of time to allocate to each "chunk" of bandwidth-throttled
* data. */
#define BUFFER_DELAY 100
#define XFER_LIMIT_RATIO (1000 / BUFFER_DELAY)
/* Time in milliseconds we are allowed to stop the source,
* for sending the last part */
#define DEFAULT_MIGRATE_SET_DOWNTIME 300
/* Maximum migrate downtime set to 2000 seconds */
#define MAX_MIGRATE_DOWNTIME_SECONDS 2000
#define MAX_MIGRATE_DOWNTIME (MAX_MIGRATE_DOWNTIME_SECONDS * 1000)
/* Default compression thread count */
#define DEFAULT_MIGRATE_COMPRESS_THREAD_COUNT 8
/* Default decompression thread count, usually decompression is at
Expand Down
Expand Up
@@ -1140,417 +1131,6 @@ MigrationInfo *qmp_query_migrate(Error **errp)
return info ;
}
/*
* Check whether the parameters are valid. Error will be put into errp
* (if provided). Return true if valid, otherwise false.
*/
static bool migrate_params_check (MigrationParameters * params , Error * * errp )
{
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 &&
(params -> throttle_trigger_threshold < 1 ||
params -> throttle_trigger_threshold > 100 )) {
error_setg (errp , QERR_INVALID_PARAMETER_VALUE ,
"throttle_trigger_threshold" ,
"an integer in the range of 1 to 100" );
return false;
}
if (params -> has_cpu_throttle_initial &&
(params -> cpu_throttle_initial < 1 ||
params -> cpu_throttle_initial > 99 )) {
error_setg (errp , QERR_INVALID_PARAMETER_VALUE ,
"cpu_throttle_initial" ,
"an integer in the range of 1 to 99" );
return false;
}
if (params -> has_cpu_throttle_increment &&
(params -> cpu_throttle_increment < 1 ||
params -> cpu_throttle_increment > 99 )) {
error_setg (errp , QERR_INVALID_PARAMETER_VALUE ,
"cpu_throttle_increment" ,
"an integer in the range of 1 to 99" );
return false;
}
if (params -> has_max_bandwidth && (params -> max_bandwidth > SIZE_MAX )) {
error_setg (errp , QERR_INVALID_PARAMETER_VALUE ,
"max_bandwidth" ,
"an integer in the range of 0 to " stringify (SIZE_MAX )
" bytes/second" );
return false;
}
if (params -> has_downtime_limit &&
(params -> downtime_limit > MAX_MIGRATE_DOWNTIME )) {
error_setg (errp , QERR_INVALID_PARAMETER_VALUE ,
"downtime_limit" ,
"an integer in the range of 0 to "
stringify (MAX_MIGRATE_DOWNTIME )" ms" );
return false;
}
/* x_checkpoint_delay is now always positive */
if (params -> has_multifd_channels && (params -> multifd_channels < 1 )) {
error_setg (errp , QERR_INVALID_PARAMETER_VALUE ,
"multifd_channels" ,
"a value between 1 and 255" );
return false;
}
if (params -> has_multifd_zlib_level &&
(params -> multifd_zlib_level > 9 )) {
error_setg (errp , QERR_INVALID_PARAMETER_VALUE , "multifd_zlib_level" ,
"a value between 0 and 9" );
return false;
}
if (params -> has_multifd_zstd_level &&
(params -> multifd_zstd_level > 20 )) {
error_setg (errp , QERR_INVALID_PARAMETER_VALUE , "multifd_zstd_level" ,
"a value between 0 and 20" );
return false;
}
if (params -> has_xbzrle_cache_size &&
(params -> xbzrle_cache_size < qemu_target_page_size () ||
!is_power_of_2 (params -> xbzrle_cache_size ))) {
error_setg (errp , QERR_INVALID_PARAMETER_VALUE ,
"xbzrle_cache_size" ,
"a power of two no less than the target page size" );
return false;
}
if (params -> has_max_cpu_throttle &&
(params -> max_cpu_throttle < params -> cpu_throttle_initial ||
params -> max_cpu_throttle > 99 )) {
error_setg (errp , QERR_INVALID_PARAMETER_VALUE ,
"max_cpu_throttle" ,
"an integer in the range of cpu_throttle_initial to 99" );
return false;
}
if (params -> has_announce_initial &&
params -> announce_initial > 100000 ) {
error_setg (errp , QERR_INVALID_PARAMETER_VALUE ,
"announce_initial" ,
"a value between 0 and 100000" );
return false;
}
if (params -> has_announce_max &&
params -> announce_max > 100000 ) {
error_setg (errp , QERR_INVALID_PARAMETER_VALUE ,
"announce_max" ,
"a value between 0 and 100000" );
return false;
}
if (params -> has_announce_rounds &&
params -> announce_rounds > 1000 ) {
error_setg (errp , QERR_INVALID_PARAMETER_VALUE ,
"announce_rounds" ,
"a value between 0 and 1000" );
return false;
}
if (params -> has_announce_step &&
(params -> announce_step < 1 ||
params -> announce_step > 10000 )) {
error_setg (errp , QERR_INVALID_PARAMETER_VALUE ,
"announce_step" ,
"a value between 0 and 10000" );
return false;
}
if (params -> has_block_bitmap_mapping &&
!check_dirty_bitmap_mig_alias_map (params -> block_bitmap_mapping , errp )) {
error_prepend (errp , "Invalid mapping given for block-bitmap-mapping: " );
return false;
}
#ifdef CONFIG_LINUX
if (migrate_zero_copy_send () &&
((params -> has_multifd_compression && params -> multifd_compression ) ||
(params -> tls_creds && * params -> tls_creds ))) {
error_setg (errp ,
"Zero copy only available for non-compressed non-TLS multifd migration" );
return false;
}
#endif
return true;
}
static void migrate_params_test_apply (MigrateSetParameters * params ,
MigrationParameters * dest )
{
* dest = migrate_get_current ()-> parameters ;
/* 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 ) {
dest -> throttle_trigger_threshold = params -> throttle_trigger_threshold ;
}
if (params -> has_cpu_throttle_initial ) {
dest -> cpu_throttle_initial = params -> cpu_throttle_initial ;
}
if (params -> has_cpu_throttle_increment ) {
dest -> cpu_throttle_increment = params -> cpu_throttle_increment ;
}
if (params -> has_cpu_throttle_tailslow ) {
dest -> cpu_throttle_tailslow = params -> cpu_throttle_tailslow ;
}
if (params -> tls_creds ) {
assert (params -> tls_creds -> type == QTYPE_QSTRING );
dest -> tls_creds = params -> tls_creds -> u .s ;
}
if (params -> tls_hostname ) {
assert (params -> tls_hostname -> type == QTYPE_QSTRING );
dest -> tls_hostname = params -> tls_hostname -> u .s ;
}
if (params -> has_max_bandwidth ) {
dest -> max_bandwidth = params -> max_bandwidth ;
}
if (params -> has_downtime_limit ) {
dest -> downtime_limit = params -> downtime_limit ;
}
if (params -> has_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 ) {
dest -> multifd_channels = params -> multifd_channels ;
}
if (params -> has_multifd_compression ) {
dest -> multifd_compression = params -> multifd_compression ;
}
if (params -> has_xbzrle_cache_size ) {
dest -> xbzrle_cache_size = params -> xbzrle_cache_size ;
}
if (params -> has_max_postcopy_bandwidth ) {
dest -> max_postcopy_bandwidth = params -> max_postcopy_bandwidth ;
}
if (params -> has_max_cpu_throttle ) {
dest -> max_cpu_throttle = params -> max_cpu_throttle ;
}
if (params -> has_announce_initial ) {
dest -> announce_initial = params -> announce_initial ;
}
if (params -> has_announce_max ) {
dest -> announce_max = params -> announce_max ;
}
if (params -> has_announce_rounds ) {
dest -> announce_rounds = params -> announce_rounds ;
}
if (params -> has_announce_step ) {
dest -> announce_step = params -> announce_step ;
}
if (params -> has_block_bitmap_mapping ) {
dest -> has_block_bitmap_mapping = true;
dest -> block_bitmap_mapping = params -> block_bitmap_mapping ;
}
}
static void migrate_params_apply (MigrateSetParameters * params , Error * * errp )
{
MigrationState * s = migrate_get_current ();
/* TODO use QAPI_CLONE() instead of duplicating it inline */
if (params -> has_compress_level ) {
s -> parameters .compress_level = params -> compress_level ;
}
if (params -> has_compress_threads ) {
s -> parameters .compress_threads = params -> compress_threads ;
}
if (params -> has_compress_wait_thread ) {
s -> parameters .compress_wait_thread = params -> compress_wait_thread ;
}
if (params -> has_decompress_threads ) {
s -> parameters .decompress_threads = params -> decompress_threads ;
}
if (params -> has_throttle_trigger_threshold ) {
s -> parameters .throttle_trigger_threshold = params -> throttle_trigger_threshold ;
}
if (params -> has_cpu_throttle_initial ) {
s -> parameters .cpu_throttle_initial = params -> cpu_throttle_initial ;
}
if (params -> has_cpu_throttle_increment ) {
s -> parameters .cpu_throttle_increment = params -> cpu_throttle_increment ;
}
if (params -> has_cpu_throttle_tailslow ) {
s -> parameters .cpu_throttle_tailslow = params -> cpu_throttle_tailslow ;
}
if (params -> tls_creds ) {
g_free (s -> parameters .tls_creds );
assert (params -> tls_creds -> type == QTYPE_QSTRING );
s -> parameters .tls_creds = g_strdup (params -> tls_creds -> u .s );
}
if (params -> tls_hostname ) {
g_free (s -> parameters .tls_hostname );
assert (params -> tls_hostname -> type == QTYPE_QSTRING );
s -> parameters .tls_hostname = g_strdup (params -> tls_hostname -> u .s );
}
if (params -> tls_authz ) {
g_free (s -> parameters .tls_authz );
assert (params -> tls_authz -> type == QTYPE_QSTRING );
s -> parameters .tls_authz = g_strdup (params -> tls_authz -> u .s );
}
if (params -> has_max_bandwidth ) {
s -> parameters .max_bandwidth = params -> max_bandwidth ;
if (s -> to_dst_file && !migration_in_postcopy ()) {
qemu_file_set_rate_limit (s -> to_dst_file ,
s -> parameters .max_bandwidth / XFER_LIMIT_RATIO );
}
}
if (params -> has_downtime_limit ) {
s -> parameters .downtime_limit = params -> downtime_limit ;
}
if (params -> has_x_checkpoint_delay ) {
s -> parameters .x_checkpoint_delay = params -> x_checkpoint_delay ;
if (migration_in_colo_state ()) {
colo_checkpoint_notify (s );
}
}
if (params -> has_block_incremental ) {
s -> parameters .block_incremental = params -> block_incremental ;
}
if (params -> has_multifd_channels ) {
s -> parameters .multifd_channels = params -> multifd_channels ;
}
if (params -> has_multifd_compression ) {
s -> parameters .multifd_compression = params -> multifd_compression ;
}
if (params -> has_xbzrle_cache_size ) {
s -> parameters .xbzrle_cache_size = params -> xbzrle_cache_size ;
xbzrle_cache_resize (params -> xbzrle_cache_size , errp );
}
if (params -> has_max_postcopy_bandwidth ) {
s -> parameters .max_postcopy_bandwidth = params -> max_postcopy_bandwidth ;
if (s -> to_dst_file && migration_in_postcopy ()) {
qemu_file_set_rate_limit (s -> to_dst_file ,
s -> parameters .max_postcopy_bandwidth / XFER_LIMIT_RATIO );
}
}
if (params -> has_max_cpu_throttle ) {
s -> parameters .max_cpu_throttle = params -> max_cpu_throttle ;
}
if (params -> has_announce_initial ) {
s -> parameters .announce_initial = params -> announce_initial ;
}
if (params -> has_announce_max ) {
s -> parameters .announce_max = params -> announce_max ;
}
if (params -> has_announce_rounds ) {
s -> parameters .announce_rounds = params -> announce_rounds ;
}
if (params -> has_announce_step ) {
s -> parameters .announce_step = params -> announce_step ;
}
if (params -> has_block_bitmap_mapping ) {
qapi_free_BitmapMigrationNodeAliasList (
s -> parameters .block_bitmap_mapping );
s -> parameters .has_block_bitmap_mapping = true;
s -> parameters .block_bitmap_mapping =
QAPI_CLONE (BitmapMigrationNodeAliasList ,
params -> block_bitmap_mapping );
}
}
void qmp_migrate_set_parameters (MigrateSetParameters * params , Error * * errp )
{
MigrationParameters tmp ;
/* TODO Rewrite "" to null instead */
if (params -> tls_creds
&& params -> tls_creds -> type == QTYPE_QNULL ) {
qobject_unref (params -> tls_creds -> u .n );
params -> tls_creds -> type = QTYPE_QSTRING ;
params -> tls_creds -> u .s = strdup ("" );
}
/* TODO Rewrite "" to null instead */
if (params -> tls_hostname
&& params -> tls_hostname -> type == QTYPE_QNULL ) {
qobject_unref (params -> tls_hostname -> u .n );
params -> tls_hostname -> type = QTYPE_QSTRING ;
params -> tls_hostname -> u .s = strdup ("" );
}
migrate_params_test_apply (params , & tmp );
if (!migrate_params_check (& tmp , errp )) {
/* Invalid parameter */
return ;
}
migrate_params_apply (params , errp );
}
void qmp_migrate_start_postcopy (Error * * errp )
{
MigrationState * s = migrate_get_current ();
Expand Down