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
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 <quintela@redhat.com>
Signed-off-by: Lukas Straub <lukasstraub2@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 <lukasstraub2@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 <lukasstraub2@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
copy hailiang. On Thu, Jun 22, 2023 at 01:18:46PM +0200, Lukas Straub wrote: > 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 <quintela@redhat.com> > Signed-off-by: Lukas Straub <lukasstraub2@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 <lukasstraub2@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 <lukasstraub2@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 -- Peter Xu
© 2016 - 2024 Red Hat, Inc.