aboutsummaryrefslogtreecommitdiff
path: root/migration
diff options
context:
space:
mode:
Diffstat (limited to 'migration')
-rw-r--r--migration/migration-hmp-cmds.c14
-rw-r--r--migration/migration.c24
-rw-r--r--migration/migration.h2
-rw-r--r--migration/options.c28
-rw-r--r--migration/options.h1
-rw-r--r--migration/trace-events2
6 files changed, 66 insertions, 5 deletions
diff --git a/migration/migration-hmp-cmds.c b/migration/migration-hmp-cmds.c
index 5b25ba24f7..d206700a43 100644
--- a/migration/migration-hmp-cmds.c
+++ b/migration/migration-hmp-cmds.c
@@ -321,6 +321,10 @@ void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict)
monitor_printf(mon, "%s: %" PRIu64 " bytes/second\n",
MigrationParameter_str(MIGRATION_PARAMETER_MAX_BANDWIDTH),
params->max_bandwidth);
+ assert(params->has_avail_switchover_bandwidth);
+ monitor_printf(mon, "%s: %" PRIu64 " bytes/second\n",
+ MigrationParameter_str(MIGRATION_PARAMETER_AVAIL_SWITCHOVER_BANDWIDTH),
+ params->avail_switchover_bandwidth);
assert(params->has_downtime_limit);
monitor_printf(mon, "%s: %" PRIu64 " ms\n",
MigrationParameter_str(MIGRATION_PARAMETER_DOWNTIME_LIMIT),
@@ -574,6 +578,16 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
}
p->max_bandwidth = valuebw;
break;
+ case MIGRATION_PARAMETER_AVAIL_SWITCHOVER_BANDWIDTH:
+ p->has_avail_switchover_bandwidth = true;
+ ret = qemu_strtosz_MiB(valuestr, NULL, &valuebw);
+ if (ret < 0 || valuebw > INT64_MAX
+ || (size_t)valuebw != valuebw) {
+ error_setg(&err, "Invalid size %s", valuestr);
+ break;
+ }
+ p->avail_switchover_bandwidth = valuebw;
+ break;
case MIGRATION_PARAMETER_DOWNTIME_LIMIT:
p->has_downtime_limit = true;
visit_type_size(v, param, &p->downtime_limit, &err);
diff --git a/migration/migration.c b/migration/migration.c
index 0e1002d017..ed04ca3b1c 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -2710,17 +2710,33 @@ static void migration_update_counters(MigrationState *s,
{
uint64_t transferred, transferred_pages, time_spent;
uint64_t current_bytes; /* bytes transferred since the beginning */
+ uint64_t switchover_bw;
+ /* Expected bandwidth when switching over to destination QEMU */
+ double expected_bw_per_ms;
double bandwidth;
if (current_time < s->iteration_start_time + BUFFER_DELAY) {
return;
}
+ switchover_bw = migrate_avail_switchover_bandwidth();
current_bytes = migration_transferred_bytes(s->to_dst_file);
transferred = current_bytes - s->iteration_initial_bytes;
time_spent = current_time - s->iteration_start_time;
bandwidth = (double)transferred / time_spent;
- s->threshold_size = bandwidth * migrate_downtime_limit();
+
+ if (switchover_bw) {
+ /*
+ * If the user specified a switchover bandwidth, let's trust the
+ * user so that can be more accurate than what we estimated.
+ */
+ expected_bw_per_ms = switchover_bw / 1000;
+ } else {
+ /* If the user doesn't specify bandwidth, we use the estimated */
+ expected_bw_per_ms = bandwidth;
+ }
+
+ s->threshold_size = expected_bw_per_ms * migrate_downtime_limit();
s->mbps = (((double) transferred * 8.0) /
((double) time_spent / 1000.0)) / 1000.0 / 1000.0;
@@ -2737,7 +2753,7 @@ static void migration_update_counters(MigrationState *s,
if (stat64_get(&mig_stats.dirty_pages_rate) &&
transferred > 10000) {
s->expected_downtime =
- stat64_get(&mig_stats.dirty_bytes_last_sync) / bandwidth;
+ stat64_get(&mig_stats.dirty_bytes_last_sync) / expected_bw_per_ms;
}
migration_rate_reset(s->to_dst_file);
@@ -2745,7 +2761,9 @@ static void migration_update_counters(MigrationState *s,
update_iteration_initial_status(s);
trace_migrate_transferred(transferred, time_spent,
- bandwidth, s->threshold_size);
+ /* Both in unit bytes/ms */
+ bandwidth, switchover_bw / 1000,
+ s->threshold_size);
}
static bool migration_can_switchover(MigrationState *s)
diff --git a/migration/migration.h b/migration/migration.h
index cd5534337c..974897a8d0 100644
--- a/migration/migration.h
+++ b/migration/migration.h
@@ -294,7 +294,7 @@ struct MigrationState {
/*
* The final stage happens when the remaining data is smaller than
* this threshold; it's calculated from the requested downtime and
- * measured bandwidth
+ * measured bandwidth, or avail-switchover-bandwidth if specified.
*/
int64_t threshold_size;
diff --git a/migration/options.c b/migration/options.c
index 6bbfd4853d..546cbe3106 100644
--- a/migration/options.c
+++ b/migration/options.c
@@ -125,6 +125,8 @@ Property migration_properties[] = {
parameters.cpu_throttle_tailslow, false),
DEFINE_PROP_SIZE("x-max-bandwidth", MigrationState,
parameters.max_bandwidth, MAX_THROTTLE),
+ DEFINE_PROP_SIZE("avail-switchover-bandwidth", MigrationState,
+ parameters.avail_switchover_bandwidth, 0),
DEFINE_PROP_UINT64("x-downtime-limit", MigrationState,
parameters.downtime_limit,
DEFAULT_MIGRATE_SET_DOWNTIME),
@@ -780,6 +782,13 @@ uint64_t migrate_max_bandwidth(void)
return s->parameters.max_bandwidth;
}
+uint64_t migrate_avail_switchover_bandwidth(void)
+{
+ MigrationState *s = migrate_get_current();
+
+ return s->parameters.avail_switchover_bandwidth;
+}
+
uint64_t migrate_max_postcopy_bandwidth(void)
{
MigrationState *s = migrate_get_current();
@@ -917,6 +926,8 @@ MigrationParameters *qmp_query_migrate_parameters(Error **errp)
s->parameters.tls_authz : "");
params->has_max_bandwidth = true;
params->max_bandwidth = s->parameters.max_bandwidth;
+ params->has_avail_switchover_bandwidth = true;
+ params->avail_switchover_bandwidth = s->parameters.avail_switchover_bandwidth;
params->has_downtime_limit = true;
params->downtime_limit = s->parameters.downtime_limit;
params->has_x_checkpoint_delay = true;
@@ -1056,6 +1067,15 @@ bool migrate_params_check(MigrationParameters *params, Error **errp)
return false;
}
+ if (params->has_avail_switchover_bandwidth &&
+ (params->avail_switchover_bandwidth > SIZE_MAX)) {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
+ "avail_switchover_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,
@@ -1225,6 +1245,10 @@ static void migrate_params_test_apply(MigrateSetParameters *params,
dest->max_bandwidth = params->max_bandwidth;
}
+ if (params->has_avail_switchover_bandwidth) {
+ dest->avail_switchover_bandwidth = params->avail_switchover_bandwidth;
+ }
+
if (params->has_downtime_limit) {
dest->downtime_limit = params->downtime_limit;
}
@@ -1341,6 +1365,10 @@ static void migrate_params_apply(MigrateSetParameters *params, Error **errp)
}
}
+ if (params->has_avail_switchover_bandwidth) {
+ s->parameters.avail_switchover_bandwidth = params->avail_switchover_bandwidth;
+ }
+
if (params->has_downtime_limit) {
s->parameters.downtime_limit = params->downtime_limit;
}
diff --git a/migration/options.h b/migration/options.h
index 045e2a41a2..93ee938ab8 100644
--- a/migration/options.h
+++ b/migration/options.h
@@ -80,6 +80,7 @@ int migrate_decompress_threads(void);
uint64_t migrate_downtime_limit(void);
uint8_t migrate_max_cpu_throttle(void);
uint64_t migrate_max_bandwidth(void);
+uint64_t migrate_avail_switchover_bandwidth(void);
uint64_t migrate_max_postcopy_bandwidth(void);
int migrate_multifd_channels(void);
MultiFDCompression migrate_multifd_compression(void);
diff --git a/migration/trace-events b/migration/trace-events
index ee9c8f4d63..d8c2aa846d 100644
--- a/migration/trace-events
+++ b/migration/trace-events
@@ -186,7 +186,7 @@ source_return_path_thread_shut(uint32_t val) "0x%x"
source_return_path_thread_resume_ack(uint32_t v) "%"PRIu32
source_return_path_thread_switchover_acked(void) ""
migration_thread_low_pending(uint64_t pending) "%" PRIu64
-migrate_transferred(uint64_t transferred, uint64_t time_spent, uint64_t bandwidth, uint64_t size) "transferred %" PRIu64 " time_spent %" PRIu64 " bandwidth %" PRIu64 " max_size %" PRId64
+migrate_transferred(uint64_t transferred, uint64_t time_spent, uint64_t bandwidth, uint64_t avail_bw, uint64_t size) "transferred %" PRIu64 " time_spent %" PRIu64 " bandwidth %" PRIu64 " switchover_bw %" PRIu64 " max_size %" PRId64
process_incoming_migration_co_end(int ret, int ps) "ret=%d postcopy-state=%d"
process_incoming_migration_co_postcopy_end_main(void) ""
postcopy_preempt_enabled(bool value) "%d"