diff --git a/MAINTAINERS b/MAINTAINERS index df78865809..d8dc4c8d7b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3883,6 +3883,7 @@ COLO Framework M: Lukas Straub S: Maintained F: migration/colo* +F: migration/multifd-colo.* F: include/migration/colo.h F: include/migration/failover.h F: docs/COLO-FT.txt diff --git a/migration/meson.build b/migration/meson.build index c7f39bdb55..c9f0f5f9f2 100644 --- a/migration/meson.build +++ b/migration/meson.build @@ -39,7 +39,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 0000000000..fb13e38b9b --- /dev/null +++ b/migration/multifd-colo.c @@ -0,0 +1,41 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * + * multifd colo implementation + * + * Copyright (c) Lukas Straub + */ + +#include "qemu/osdep.h" +#include "multifd.h" +#include "multifd-colo.h" +#include "migration/colo.h" +#include "system/ramblock.h" + +void multifd_colo_prepare_recv(MultiFDRecvParams *p) +{ + /* + * 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); + colo_record_bitmap(p->block, p->zero, p->zero_num); + } +} + +void multifd_colo_process_recv(MultiFDRecvParams *p) +{ + 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()); + } + for (int i = 0; i < p->zero_num; i++) { + void *guest = p->block->host + p->zero[i]; + memset(guest, 0, multifd_ram_page_size()); + } + } +} diff --git a/migration/multifd-colo.h b/migration/multifd-colo.h new file mode 100644 index 0000000000..1011c5a1da --- /dev/null +++ b/migration/multifd-colo.h @@ -0,0 +1,23 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * + * multifd colo header + * + * Copyright (c) Lukas Straub + */ + +#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-nocomp.c b/migration/multifd-nocomp.c index 9be79b3b8e..9f7a792fa7 100644 --- a/migration/multifd-nocomp.c +++ b/migration/multifd-nocomp.c @@ -16,6 +16,7 @@ #include "file.h" #include "migration-stats.h" #include "multifd.h" +#include "multifd-colo.h" #include "options.h" #include "migration.h" #include "qapi/error.h" @@ -269,7 +270,6 @@ int multifd_ram_unfill_packet(MultiFDRecvParams *p, Error **errp) return -1; } - p->host = p->block->host; for (i = 0; i < p->normal_num; i++) { uint64_t offset = be64_to_cpu(packet->offset[i]); @@ -294,6 +294,14 @@ int multifd_ram_unfill_packet(MultiFDRecvParams *p, Error **errp) p->zero[i] = offset; } + if (migrate_colo()) { + multifd_colo_prepare_recv(p); + assert(p->block->colo_cache); + p->host = p->block->colo_cache; + } else { + p->host = p->block->host; + } + return 0; } diff --git a/migration/multifd.c b/migration/multifd.c index 4259ab2628..2193088996 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 "options.h" #include "qemu/yank.h" #include "io/channel-file.h" @@ -1258,6 +1259,13 @@ static int multifd_ram_state_recv(MultiFDRecvParams *p, Error **errp) int ret; ret = multifd_recv_state->ops->recv(p, errp); + if (ret != 0) { + return ret; + } + + if (migrate_colo()) { + multifd_colo_process_recv(p); + } return ret; } diff --git a/migration/multifd.h b/migration/multifd.h index 89a395aef2..fbc35702b0 100644 --- a/migration/multifd.h +++ b/migration/multifd.h @@ -279,7 +279,10 @@ typedef struct { uint64_t packets_recved; /* ramblock */ RAMBlock *block; - /* ramblock host address */ + /* + * Normally, it points to ramblock's host address. When COLO + * is enabled, it points to the mirror cache for the ramblock. + */ uint8_t *host; /* buffers to recv */ struct iovec *iov;