@samitouri / QOSamiQemu / commits / f267196712

migration: Replace switchover_ack_needed SaveVMHandler

A new switchover-ack mechanism that will replace the existing one will be added in the following patches. The new mechanism will not use switchover_ack_needed SaveVMHandler, however, the old mechanism must still be kept for backward compatibility. To keep things clear and decrease API surface of old code, replace switchover_ack_needed SaveVMHandler with a regular function migration_request_switchover_ack(). No functional changes intended. Acked-by: Peter Xu <peterx@redhat.com> Signed-off-by: Avihai Horon <avihaih@nvidia.com> Link: https://lore.kernel.org/qemu-devel/20260706085211.13905-6-avihaih@nvidia.com Signed-off-by: Cédric Le Goater <clg@redhat.com>

Avihai Horon committed Jul 6, 2026 at 11:52 UTC f267196712d530c473f94f8ec83c07f4fe78aba4
7 files changed +28 -46
docs/devel/migration/vfio.rst
-3
@@ -59,9 +59,6 @@ VFIO implements the device hooks for the iterative approach as follows:
59 * A ``save_live_iterate`` function that reads the VFIO device's data from the
60 vendor driver during iterative pre-copy phase.
61
62 -* A ``switchover_ack_needed`` function that checks if the VFIO device uses
63 - "switchover-ack" migration capability when this capability is enabled.
64 -
62 * A ``switchover_start`` function that in the multifd mode starts a thread that
63 reassembles the multifd received data and loads it in-order into the device.
64 In the non-multifd mode this function is a NOP.
hw/vfio/migration.c
+10 -8
@@ -487,6 +487,14 @@ static bool vfio_precopy_supported(VFIODevice *vbasedev)
487 return migration->mig_flags & VFIO_MIGRATION_PRE_COPY;
488 }
489
490 +static void vfio_request_switchover_ack(VFIODevice *vbasedev)
491 +{
492 + if (vfio_precopy_supported(vbasedev)) {
493 + /* Precopy support implies switchover-ack is needed */
494 + migration_request_switchover_ack(vbasedev->name);
495 + }
496 +}
497 +
498 /* ---------------------------------------------------------------------- */
499
500 static int vfio_save_prepare(void *opaque, Error **errp)
@@ -776,6 +784,8 @@ static int vfio_load_setup(QEMUFile *f, void *opaque, Error **errp)
784 return ret;
785 }
786
787 + vfio_request_switchover_ack(vbasedev);
788 +
789 return 0;
790 }
791
@@ -874,13 +884,6 @@ static int vfio_load_state(QEMUFile *f, void *opaque, int version_id)
884 return ret;
885 }
886
877 -static bool vfio_switchover_ack_needed(void *opaque)
878 -{
879 - VFIODevice *vbasedev = opaque;
880 -
881 - return vfio_precopy_supported(vbasedev);
882 -}
883 -
887 static int vfio_switchover_start(void *opaque)
888 {
889 VFIODevice *vbasedev = opaque;
@@ -904,7 +907,6 @@ static const SaveVMHandlers savevm_vfio_handlers = {
907 .load_setup = vfio_load_setup,
908 .load_cleanup = vfio_load_cleanup,
909 .load_state = vfio_load_state,
907 - .switchover_ack_needed = vfio_switchover_ack_needed,
910 /*
911 * Multifd support
912 */
include/migration/misc.h
+2
@@ -159,4 +159,6 @@ bool multifd_device_state_save_thread_should_exit(void);
159 void multifd_abort_device_state_save_threads(void);
160 bool multifd_join_device_state_save_threads(void);
161
162 +void migration_request_switchover_ack(const char *requester);
163 +
164 #endif
include/migration/register.h
-13
@@ -302,19 +302,6 @@ typedef struct SaveVMHandlers {
302 */
303 int (*resume_prepare)(MigrationState *s, void *opaque);
304
305 - /**
306 - * @switchover_ack_needed
307 - *
308 - * Checks if switchover ack should be used. Called only on
309 - * destination.
310 - *
311 - * @opaque: data pointer passed to register_savevm_live()
312 - *
313 - * Returns true if switchover ack should be used and false
314 - * otherwise
315 - */
316 - bool (*switchover_ack_needed)(void *opaque);
317 -
305 /**
306 * @switchover_start
307 *
migration/migration.c
+15
@@ -2202,6 +2202,21 @@ void migration_rp_kick(MigrationState *s)
2202 qemu_sem_post(&s->rp_state.rp_sem);
2203 }
2204
2205 +/* This is called only on destination side */
2206 +void migration_request_switchover_ack(const char *requester)
2207 +{
2208 + MigrationIncomingState *mis = migration_incoming_get_current();
2209 +
2210 + if (!migrate_switchover_ack()) {
2211 + return;
2212 + }
2213 +
2214 + mis->switchover_ack_pending_num++;
2215 +
2216 + trace_migration_request_switchover_ack(requester,
2217 + mis->switchover_ack_pending_num);
2218 +}
2219 +
2220 static struct rp_cmd_args {
2221 ssize_t len; /* -1 = variable */
2222 const char *name;
migration/savevm.c
-21
@@ -2800,23 +2800,6 @@ static int qemu_loadvm_state_header(QEMUFile *f, Error **errp)
2800 return 0;
2801 }
2802
2803 -static void qemu_loadvm_state_switchover_ack_needed(MigrationIncomingState *mis)
2804 -{
2805 - SaveStateEntry *se;
2806 -
2807 - QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
2808 - if (!se->ops || !se->ops->switchover_ack_needed) {
2809 - continue;
2810 - }
2811 -
2812 - if (se->ops->switchover_ack_needed(se->opaque)) {
2813 - mis->switchover_ack_pending_num++;
2814 - }
2815 - }
2816 -
2817 - trace_loadvm_state_switchover_ack_needed(mis->switchover_ack_pending_num);
2818 -}
2819 -
2803 static int qemu_loadvm_state_setup(QEMUFile *f, Error **errp)
2804 {
2805 ERRP_GUARD();
@@ -3078,10 +3061,6 @@ int qemu_loadvm_state(QEMUFile *f, Error **errp)
3061 return -EINVAL;
3062 }
3063
3081 - if (migrate_switchover_ack()) {
3082 - qemu_loadvm_state_switchover_ack_needed(mis);
3083 - }
3084 -
3064 cpu_synchronize_all_pre_loadvm();
3065
3066 ret = qemu_loadvm_state_main(f, mis, errp);
migration/trace-events
+1 -1
@@ -8,7 +8,6 @@ qemu_loadvm_state_post_main(int ret) "%d"
8 qemu_loadvm_state_section_startfull(uint32_t section_id, const char *idstr, uint32_t instance_id, uint32_t version_id) "%u(%s) %u %u"
9 qemu_savevm_send_packaged(void) ""
10 qemu_savevm_query_pending(bool exact, bool final, uint64_t precopy, uint64_t stopcopy, uint64_t postcopy, uint64_t total) "exact=%d, final=%d, precopy=%"PRIu64", stopcopy=%"PRIu64", postcopy=%"PRIu64", total=%"PRIu64
11 -loadvm_state_switchover_ack_needed(unsigned int switchover_ack_pending_num) "Switchover ack pending num=%u"
11 loadvm_state_setup(void) ""
12 loadvm_state_cleanup(void) ""
13 loadvm_handle_cmd_packaged(unsigned int length) "%u"
@@ -199,6 +198,7 @@ process_incoming_migration_co_postcopy_end_main(void) ""
198 postcopy_preempt_enabled(bool value) "%d"
199 migration_precopy_complete(void) ""
200 migration_call_notifiers(int type) "type=%d"
201 +migration_request_switchover_ack(const char *requester, unsigned int switchover_ack_pending_num) "Requester %s, switchover_ack_pending_num %u"
202
203 # migration-stats
204 migration_transferred_bytes(uint64_t qemu_file, uint64_t multifd, uint64_t rdma) "qemu_file %" PRIu64 " multifd %" PRIu64 " RDMA %" PRIu64