Like in the normal ram_load() path, put the received pages into the colo cache and mark the pages in the bitmap so that they will be flushed to the guest later.
Signed-off-by: Juan Quintela <quint...@redhat.com> Signed-off-by: Lukas Straub <lukasstra...@web.de> --- migration/meson.build | 1 + migration/multifd-colo.c | 53 ++++++++++++++++++++++++++++++++++++++++ migration/multifd-colo.h | 24 ++++++++++++++++++ migration/multifd.c | 5 ++++ 4 files changed, 83 insertions(+) create mode 100644 migration/multifd-colo.c create mode 100644 migration/multifd-colo.h diff --git a/migration/meson.build b/migration/meson.build index 1ae28523a1..063e0e0a8c 100644 --- a/migration/meson.build +++ b/migration/meson.build @@ -21,6 +21,7 @@ system_ss.add(files( 'migration.c', 'multifd.c', 'multifd-zlib.c', + 'multifd-colo.c', 'ram-compress.c', 'options.c', 'postcopy-ram.c', diff --git a/migration/multifd-colo.c b/migration/multifd-colo.c new file mode 100644 index 0000000000..4872dc6d01 --- /dev/null +++ b/migration/multifd-colo.c @@ -0,0 +1,53 @@ +/* + * multifd colo implementation + * + * Copyright (c) Lukas Straub <lukasstra...@web.de> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "exec/target_page.h" +#include "exec/ramblock.h" +#include "qemu/error-report.h" +#include "qapi/error.h" +#include "ram.h" +#include "multifd.h" +#include "options.h" +#include "io/channel-socket.h" +#include "migration/colo.h" +#include "multifd-colo.h" + +void multifd_colo_prepare_recv_pages(MultiFDRecvParams *p) +{ + if (!migrate_colo()) + return; + + assert(p->block->colo_cache); + + /* + * While we're still in precopy state (not yet in colo state), we copy + * received pages to both guest and cache. No need to set dirty bits, + * since guest and cache memory are in sync. + */ + if (migration_incoming_in_colo_state()) { + colo_record_bitmap(p->block, p->normal, p->normal_num); + } + p->host = p->block->colo_cache; +} + +void multifd_colo_process_recv_pages(MultiFDRecvParams *p) +{ + if (!migrate_colo()) + return; + + if (!migration_incoming_in_colo_state()) { + for (int i = 0; i < p->normal_num; i++) { + void *guest = p->block->host + p->normal[i]; + void *cache = p->host + p->normal[i]; + memcpy(guest, cache, p->page_size); + } + } + p->host = p->block->host; +} diff --git a/migration/multifd-colo.h b/migration/multifd-colo.h new file mode 100644 index 0000000000..58920a0583 --- /dev/null +++ b/migration/multifd-colo.h @@ -0,0 +1,24 @@ +/* + * multifd colo header + * + * Copyright (c) Lukas Straub <lukasstra...@web.de> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef QEMU_MIGRATION_MULTIFD_COLO_H +#define QEMU_MIGRATION_MULTIFD_COLO_H + +#ifdef CONFIG_REPLICATION + +void multifd_colo_prepare_recv_pages(MultiFDRecvParams *p); +void multifd_colo_process_recv_pages(MultiFDRecvParams *p); + +#else + +static inline void multifd_colo_prepare_recv_pages(MultiFDRecvParams *p) {} +static inline void multifd_colo_process_recv_pages(MultiFDRecvParams *p) {} + +#endif +#endif diff --git a/migration/multifd.c b/migration/multifd.c index 3387d8277f..6b031c1fd2 100644 --- a/migration/multifd.c +++ b/migration/multifd.c @@ -25,6 +25,7 @@ #include "qemu-file.h" #include "trace.h" #include "multifd.h" +#include "multifd-colo.h" #include "threadinfo.h" #include "options.h" #include "qemu/yank.h" @@ -1134,10 +1135,14 @@ static void *multifd_recv_thread(void *opaque) qemu_mutex_unlock(&p->mutex); if (p->normal_num) { + multifd_colo_prepare_recv_pages(p); + ret = multifd_recv_state->ops->recv_pages(p, &local_err); if (ret != 0) { break; } + + multifd_colo_process_recv_pages(p); } if (flags & MULTIFD_FLAG_SYNC) { -- 2.39.2
pgpF_Xz8KX6Oc.pgp
Description: OpenPGP digital signature