@samitouri / QOSamiQemu / commits / 8757d5155f

migration: Fail migration if switchover-ack is requested after switchover decision

Switchover ACK is checked only during precopy while the guest is still running. The last migration_can_switchover() decision and guest stop are not atomic, so a device may want to request another switchover ACK in the gap after switchover decision has been made but before the guest is stopped. Migration would then miss that request, which can increase downtime. Cover this case by failing the migration if a switchover-ack was requested during that time. Ideally, precopy iterations should be resumed in this case, however, VFIO doesn't support going back to precopy after being stopped, so implementing such logic would require non-trivial changes to the guest start/stop flow. Given the above and that this case should be rare, failing the migration seems reasonable. Signed-off-by: Avihai Horon <avihaih@nvidia.com> Link: https://lore.kernel.org/qemu-devel/20260706085211.13905-9-avihaih@nvidia.com Signed-off-by: Cédric Le Goater <clg@redhat.com>

Avihai Horon committed Jul 6, 2026 at 11:52 UTC 8757d5155f3be29bf1186ccadf70cbd76054a75a
4 files changed +28 -5
migration/colo.c
+5 -1
@@ -473,7 +473,11 @@ static int colo_do_checkpoint_transaction(MigrationState *s,
473 * state is saved. Unlike a regular switchover, COLO reaches completion
474 * repeatedly for every checkpoint, so this must be done on each one.
475 */
476 - qemu_savevm_query_pending_final(s, &pending);
476 + if (!qemu_savevm_query_pending_final(s, &pending, &local_err)) {
477 + ret = -1;
478 + bql_unlock();
479 + goto out;
480 + }
481
482 /*
483 * Only save VM's live state, which not including device state.
migration/migration.c
+3 -1
@@ -2833,7 +2833,9 @@ static bool migration_switchover_start(MigrationState *s, Error **errp)
2833 * properly update all the dirty bitmaps to finally generate the
2834 * correct discard bitmaps; see ram_postcopy_send_discard_bitmap().
2835 */
2836 - qemu_savevm_query_pending_final(s, &pending);
2836 + if (!qemu_savevm_query_pending_final(s, &pending, errp)) {
2837 + return false;
2838 + }
2839
2840 /* Inactivate disks except in COLO */
2841 if (!migrate_colo()) {
migration/savevm.c
+18 -1
@@ -1852,11 +1852,28 @@ void qemu_savevm_query_pending_iter(MigrationState *s, MigPendingData *pending,
1852 qemu_savevm_query_pending(s, pending, exact, false);
1853 }
1854
1855 -void qemu_savevm_query_pending_final(MigrationState *s, MigPendingData *pending)
1855 +bool qemu_savevm_query_pending_final(MigrationState *s, MigPendingData *pending,
1856 + Error **errp)
1857 {
1858 g_assert(bql_locked());
1859
1860 qemu_savevm_query_pending(s, pending, true, true);
1861 +
1862 + /*
1863 + * Switchover-ack requests done after switchover decision are not allowed.
1864 + * Fail the migration in this case since we currently don't support going
1865 + * back to precopy.
1866 + */
1867 + if (migrate_switchover_ack() && !migrate_switchover_ack_legacy() &&
1868 + pending->switchover_ack_pending > 0) {
1869 + error_setg(errp,
1870 + "Switchover ACK was requested by %" PRIu32
1871 + " devices during switchover",
1872 + pending->switchover_ack_pending);
1873 + return false;
1874 + }
1875 +
1876 + return true;
1877 }
1878
1879 void qemu_savevm_state_cleanup(void)
migration/savevm.h
+2 -2
@@ -47,8 +47,8 @@ void qemu_savevm_state_complete_postcopy(QEMUFile *f);
47 int qemu_savevm_state_complete_precopy(MigrationState *s, Error **errp);
48 void qemu_savevm_query_pending_iter(MigrationState *s, MigPendingData *pending,
49 bool exact);
50 -void qemu_savevm_query_pending_final(MigrationState *s,
51 - MigPendingData *pending);
50 +bool qemu_savevm_query_pending_final(MigrationState *s,
51 + MigPendingData *pending, Error **errp);
52 int qemu_savevm_state_complete_precopy_iterable(QEMUFile *f, bool in_postcopy);
53 bool qemu_savevm_state_postcopy_prepare(QEMUFile *f, Error **errp);
54 void qemu_savevm_state_end(QEMUFile *f);