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);

Reply via email to