@@ -23,6 +23,7 @@ softmmu_ss.add(files(
'migration.c',
'multifd.c',
'multifd-zlib.c',
+ 'multifd-colo.c',
'options.c',
'postcopy-ram.c',
'savevm.c',
new file mode 100644
@@ -0,0 +1,39 @@
+/*
+ * 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 "io/channel-socket.h"
+
+#define MULTIFD_INTERNAL
+#include "multifd-internal.h"
+
+static int multifd_colo_recv_pages(MultiFDRecvParams *p, Error **errp)
+{
+ return multifd_recv_state->ops->recv_pages(p, errp);
+}
+
+int multifd_colo_load_setup(Error **errp)
+{
+ int ret;
+
+ ret = _multifd_load_setup(errp);
+ if (ret) {
+ return ret;
+ }
+
+ multifd_recv_state->recv_pages = multifd_colo_recv_pages;
+
+ return 0;
+}
@@ -29,6 +29,11 @@ struct MultiFDRecvState {
uint64_t packet_num;
/* multifd ops */
MultiFDMethods *ops;
+ /* overridable recv method */
+ int (*recv_pages)(MultiFDRecvParams *p, Error **errp);
};
extern struct MultiFDRecvState *multifd_recv_state;
+
+int _multifd_load_setup(Error **errp);
+int multifd_colo_load_setup(Error **errp);
@@ -1126,7 +1126,7 @@ static void *multifd_recv_thread(void *opaque)
qemu_mutex_unlock(&p->mutex);
if (p->normal_num) {
- ret = multifd_recv_state->ops->recv_pages(p, &local_err);
+ ret = multifd_recv_state->recv_pages(p, &local_err);
if (ret != 0) {
break;
}
@@ -1152,20 +1152,12 @@ static void *multifd_recv_thread(void *opaque)
return NULL;
}
-int multifd_load_setup(Error **errp)
+int _multifd_load_setup(Error **errp)
{
int thread_count;
uint32_t page_count = MULTIFD_PACKET_SIZE / qemu_target_page_size();
uint8_t i;
- /*
- * Return successfully if multiFD recv state is already initialised
- * or multiFD is not enabled.
- */
- if (multifd_recv_state || !migrate_multifd()) {
- return 0;
- }
-
thread_count = migrate_multifd_channels();
multifd_recv_state = g_malloc0(sizeof(*multifd_recv_state));
multifd_recv_state->params = g_new0(MultiFDRecvParams, thread_count);
@@ -1204,6 +1196,42 @@ int multifd_load_setup(Error **errp)
return 0;
}
+static int multifd_normal_recv_pages(MultiFDRecvParams *p, Error **errp)
+{
+ return multifd_recv_state->ops->recv_pages(p, errp);
+}
+
+static int multifd_normal_load_setup(Error **errp)
+{
+ int ret;
+
+ ret = _multifd_load_setup(errp);
+ if (ret) {
+ return ret;
+ }
+
+ multifd_recv_state->recv_pages = multifd_normal_recv_pages;
+
+ return 0;
+}
+
+int multifd_load_setup(Error **errp)
+{
+ /*
+ * Return successfully if multiFD recv state is already initialised
+ * or multiFD is not enabled.
+ */
+ if (multifd_recv_state || !migrate_multifd()) {
+ return 0;
+ }
+
+ if (migrate_colo()) {
+ return multifd_colo_load_setup(errp);
+ } else {
+ return multifd_normal_load_setup(errp);
+ }
+}
+
bool multifd_recv_all_channels_created(void)
{
int thread_count = migrate_multifd_channels();
This allows to override the behaviour around recv_pages. Think of it like a "multifd_colo" child class of multifd. This will be used in the next commits to add colo support to multifd. Signed-off-by: Lukas Straub <lukasstraub2@web.de> --- migration/meson.build | 1 + migration/multifd-colo.c | 39 +++++++++++++++++++++++++++++ migration/multifd-internal.h | 5 ++++ migration/multifd.c | 48 ++++++++++++++++++++++++++++-------- 4 files changed, 83 insertions(+), 10 deletions(-) create mode 100644 migration/multifd-colo.c