migration: Calculate expected downtime on demand
This value does not need to be calculated as frequent. Only calculate it on demand when query-migrate happened. With that we can remove the variable in MigrationState. This paves way for fixing this value to include all modules (not only RAM but others too). Reviewed-by: Juraj Marcin <jmarcin@redhat.com> Link: https://lore.kernel.org/r/20260421202110.306051-12-peterx@redhat.com Signed-off-by: Peter Xu <peterx@redhat.com>
Peter Xu committed
Apr 21, 2026 at 16:21 UTC
dd4fe8844b52b986fa19e7c03ddec11680f76b9b
2 files changed
+13
-14
migration/migration.c
+12
-13
@@ -1041,6 +1041,17 @@ static bool migrate_show_downtime(MigrationState *s)
1041
return (s->state == MIGRATION_STATUS_COMPLETED) || migration_in_postcopy();
1042
}
1043
1044
+/* Return expected downtime (unit: milliseconds) */
1045
+int64_t migration_downtime_calc_expected(MigrationState *s)
1046
+{
1047
+ if (mig_stats.dirty_sync_count <= 1) {
1048
+ return migrate_downtime_limit();
1049
+ }
1050
+
1051
+ return mig_stats.dirty_bytes_last_sync /
1052
+ migration_get_switchover_bw(s) * 1000;
1053
+}
1054
+
1055
static void populate_time_info(MigrationInfo *info, MigrationState *s)
1056
{
1057
info->has_status = true;
@@ -1061,7 +1072,7 @@ static void populate_time_info(MigrationInfo *info, MigrationState *s)
1072
info->downtime = s->downtime;
1073
} else {
1074
info->has_expected_downtime = true;
1064
- info->expected_downtime = s->expected_downtime;
1075
+ info->expected_downtime = migration_downtime_calc_expected(s);
1076
}
1077
}
1078
@@ -1649,7 +1660,6 @@ int migrate_init(MigrationState *s, Error **errp)
1660
s->mbps = 0.0;
1661
s->pages_per_second = 0.0;
1662
s->downtime = 0;
1652
- s->expected_downtime = 0;
1663
s->setup_time = 0;
1664
s->start_postcopy = false;
1665
s->migration_thread_running = false;
@@ -3166,15 +3176,6 @@ static void migration_update_counters(MigrationState *s,
3176
s->pages_per_second = (double) transferred_pages /
3177
(((double) time_spent / 1000.0));
3178
3169
- /*
3170
- * if we haven't sent anything, we don't want to
3171
- * recalculate. 10000 is a small enough number for our purposes
3172
- */
3173
- if (mig_stats.dirty_pages_rate && transferred > 10000) {
3174
- s->expected_downtime =
3175
- mig_stats.dirty_bytes_last_sync / switchover_bw_per_ms;
3176
- }
3177
-
3179
migration_rate_reset();
3180
3181
update_iteration_initial_status(s);
@@ -3841,8 +3842,6 @@ void migration_start_outgoing(MigrationState *s)
3842
bool resume = (s->state == MIGRATION_STATUS_POSTCOPY_RECOVER_SETUP);
3843
int ret;
3844
3844
- s->expected_downtime = migrate_downtime_limit();
3845
-
3845
if (resume) {
3846
/* This is a resumed migration */
3847
rate_limit = migrate_max_postcopy_bandwidth();
migration/migration.h
+1
-1
@@ -359,7 +359,6 @@ struct MigrationState {
359
/* Timestamp when VM is down (ms) to migrate the last stuff */
360
int64_t downtime_start;
361
int64_t downtime;
362
- int64_t expected_downtime;
362
bool capabilities[MIGRATION_CAPABILITY__MAX];
363
int64_t setup_time;
364
@@ -585,6 +584,7 @@ void migration_cancel(void);
584
void migration_populate_vfio_info(MigrationInfo *info);
585
void migration_reset_vfio_bytes_transferred(void);
586
void postcopy_temp_page_reset(PostcopyTmpPage *tmp_page);
587
+int64_t migration_downtime_calc_expected(MigrationState *s);
588
589
/*
590
* Migration thread waiting for return path thread. Return non-zero if an