Prasad Pandit <ppan...@redhat.com> writes: > From: Prasad Pandit <p...@fedoraproject.org> > > Enable Multifd and Postcopy migration together. > The migration_ioc_process_incoming() routine > checks magic value sent on each channel and > helps to properly setup multifd and postcopy > channels. > > The Precopy and Multifd threads work during the > initial guest RAM transfer. When migration moves > to the Postcopy phase, the multifd threads cease > to send data on multifd channels and Postcopy > threads on the destination request/pull data from > the source side. > > Signed-off-by: Prasad Pandit <p...@fedoraproject.org> > --- > migration/multifd-nocomp.c | 3 ++- > migration/multifd.c | 7 +++++++ > migration/options.c | 5 ----- > migration/ram.c | 7 +++---- > 4 files changed, 12 insertions(+), 10 deletions(-) > > v8: > - Separate this patch out from earlier patch-2. > > v7: > - > https://lore.kernel.org/qemu-devel/20250228121749.553184-1-ppan...@redhat.com/T/#t > > diff --git a/migration/multifd-nocomp.c b/migration/multifd-nocomp.c > index ffe75256c9..02f8bf8ce8 100644 > --- a/migration/multifd-nocomp.c > +++ b/migration/multifd-nocomp.c > @@ -17,6 +17,7 @@ > #include "migration-stats.h" > #include "multifd.h" > #include "options.h" > +#include "migration.h" > #include "qapi/error.h" > #include "qemu/cutils.h" > #include "qemu/error-report.h" > @@ -399,7 +400,7 @@ int multifd_ram_flush_and_sync(QEMUFile *f) > MultiFDSyncReq req; > int ret; > > - if (!migrate_multifd()) { > + if (!migrate_multifd() || migration_in_postcopy()) { > return 0; > } > > diff --git a/migration/multifd.c b/migration/multifd.c > index 6139cabe44..074d16d07d 100644 > --- a/migration/multifd.c > +++ b/migration/multifd.c > @@ -1379,6 +1379,13 @@ static void *multifd_recv_thread(void *opaque) > } > > if (has_data) { > + /* > + * multifd thread should not be active and receive data > + * when migration is in the Postcopy phase. Two threads > + * writing the same memory area could easily corrupt > + * the guest state. > + */ > + assert(!migration_in_postcopy()); > if (is_device_state) { > assert(use_packets); > ret = multifd_device_state_recv(p, &local_err); > diff --git a/migration/options.c b/migration/options.c > index b0ac2ea408..48aa6076de 100644 > --- a/migration/options.c > +++ b/migration/options.c > @@ -491,11 +491,6 @@ bool migrate_caps_check(bool *old_caps, bool *new_caps, > Error **errp) > error_setg(errp, "Postcopy is not compatible with > ignore-shared"); > return false; > } > - > - if (new_caps[MIGRATION_CAPABILITY_MULTIFD]) { > - error_setg(errp, "Postcopy is not yet compatible with multifd"); > - return false; > - } > } > > if (new_caps[MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT]) { > diff --git a/migration/ram.c b/migration/ram.c > index 424df6d9f1..6fd88cbf2a 100644 > --- a/migration/ram.c > +++ b/migration/ram.c > @@ -1297,7 +1297,7 @@ static int find_dirty_block(RAMState *rs, > PageSearchStatus *pss) > pss->page = 0; > pss->block = QLIST_NEXT_RCU(pss->block, next); > if (!pss->block) { > - if (multifd_ram_sync_per_round()) { > + if (multifd_ram_sync_per_round() && !migration_in_postcopy()) {
I'd rather not put this check here. multifd_ram_flush_and_sync() will already return 0 if in postcopy. > QEMUFile *f = rs->pss[RAM_CHANNEL_PRECOPY].pss_channel; > int ret = multifd_ram_flush_and_sync(f); > if (ret < 0) { > @@ -1976,9 +1976,8 @@ static int ram_save_target_page(RAMState *rs, > PageSearchStatus *pss) > } > } > > - if (migrate_multifd()) { > - RAMBlock *block = pss->block; > - return ram_save_multifd_page(block, offset); > + if (migrate_multifd() && !migration_in_postcopy()) { > + return ram_save_multifd_page(pss->block, offset); > } > > return ram_save_page(rs, pss);