From 6983d1657dc1784288eb299f5f001fb56af705d8 Mon Sep 17 00:00:00 2001 From: Wei Wang Date: Fri, 5 Apr 2024 11:40:56 +0800 Subject: [PATCH] migration/postcopy: ensure preempt channel is ready before loading states Before loading the guest states, ensure that the preempt channel has been ready to use, as some of the states (e.g. via virtio_load) might trigger page faults that will be handled through the preempt channel. So yield to the main thread in the case that the channel create event hasn't been dispatched. Cc: qemu-stable Fixes: 9358982744 ("migration: Send requested page directly in rp-return thread") Originally-by: Lei Wang Link: https://lore.kernel.org/all/9aa5d1be-7801-40dd-83fd-f7e041ced249@intel.com/T/ Signed-off-by: Lei Wang Signed-off-by: Wei Wang Link: https://lore.kernel.org/r/20240405034056.23933-1-wei.w.wang@intel.com [peterx: add a todo section, add Fixes and copy stable for 8.0+] Signed-off-by: Peter Xu (cherry picked from commit 7afbdada7effbc2b97281bfbce0c6df351a3cf88) Signed-off-by: Michael Tokarev --- migration/savevm.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/migration/savevm.c b/migration/savevm.c index eec5503a42..f374da85b9 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -2343,6 +2343,27 @@ static int loadvm_handle_cmd_packaged(MigrationIncomingState *mis) QEMUFile *packf = qemu_file_new_input(QIO_CHANNEL(bioc)); + /* + * Before loading the guest states, ensure that the preempt channel has + * been ready to use, as some of the states (e.g. via virtio_load) might + * trigger page faults that will be handled through the preempt channel. + * So yield to the main thread in the case that the channel create event + * hasn't been dispatched. + * + * TODO: if we can move migration loadvm out of main thread, then we + * won't block main thread from polling the accept() fds. We can drop + * this as a whole when that is done. + */ + do { + if (!migrate_postcopy_preempt() || !qemu_in_coroutine() || + mis->postcopy_qemufile_dst) { + break; + } + + aio_co_schedule(qemu_get_current_aio_context(), qemu_coroutine_self()); + qemu_coroutine_yield(); + } while (1); + ret = qemu_loadvm_state_main(packf, mis); trace_loadvm_handle_cmd_packaged_main(ret); qemu_fclose(packf);