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 <[email protected]> Signed-off-by: Lukas Straub <[email protected]> --- migration/meson.build | 2 +- migration/multifd-colo.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++ migration/multifd-colo.h | 26 ++++++++++++++++++++++ migration/multifd.c | 14 +++++++++--- 4 files changed, 95 insertions(+), 4 deletions(-) diff --git a/migration/meson.build b/migration/meson.build index 16909d54c5110fc5d8187fd3a68c4a5b08b59ea7..1e59fe4f1f0bbfffed90df38e8f39fa87bceb9b9 100644 --- a/migration/meson.build +++ b/migration/meson.build @@ -40,7 +40,7 @@ system_ss.add(files( ), gnutls, zlib) if get_option('replication').allowed() - system_ss.add(files('colo-failover.c', 'colo.c')) + system_ss.add(files('colo-failover.c', 'colo.c', 'multifd-colo.c')) else system_ss.add(files('colo-stubs.c')) endif diff --git a/migration/multifd-colo.c b/migration/multifd-colo.c new file mode 100644 index 0000000000000000000000000000000000000000..05a81e57b2bda517cbc0844b4f03dc78453f6af8 --- /dev/null +++ b/migration/multifd-colo.c @@ -0,0 +1,57 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * + * multifd colo implementation + * + * Copyright (c) Lukas Straub <[email protected]> + * + * 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 "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" +#include "system/ramblock.h" + +void multifd_colo_prepare_recv(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(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, multifd_ram_page_size()); + } + } + p->host = p->block->host; +} diff --git a/migration/multifd-colo.h b/migration/multifd-colo.h new file mode 100644 index 0000000000000000000000000000000000000000..82eaf3f48c47de2f090f9de52f9d57a337d4754a --- /dev/null +++ b/migration/multifd-colo.h @@ -0,0 +1,26 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * + * multifd colo header + * + * Copyright (c) Lukas Straub <[email protected]> + * + * 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(MultiFDRecvParams *p); +void multifd_colo_process_recv(MultiFDRecvParams *p); + +#else + +static inline void multifd_colo_prepare_recv(MultiFDRecvParams *p) {} +static inline void multifd_colo_process_recv(MultiFDRecvParams *p) {} + +#endif +#endif diff --git a/migration/multifd.c b/migration/multifd.c index bf6da85af8a1e207235ce06b8dbace33beded6d8..9006f73cc5b52e8814da107c0b5c867ee6d03a95 100644 --- a/migration/multifd.c +++ b/migration/multifd.c @@ -29,6 +29,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" @@ -1398,11 +1399,18 @@ static void *multifd_recv_thread(void *opaque) if (is_device_state) { assert(use_packets); ret = multifd_device_state_recv(p, &local_err); + if (ret != 0) { + break; + } } else { + multifd_colo_prepare_recv(p); + ret = multifd_recv_state->ops->recv(p, &local_err); - } - if (ret != 0) { - break; + if (ret != 0) { + break; + } + + multifd_colo_process_recv(p); } } else if (is_device_state) { error_setg(&local_err, -- 2.39.5
