|
@@ -2079,7 +2079,6 @@ static bool save_compress_page(RAMState *rs, PageSearchStatus *pss,
|
|
*/
|
|
*/
|
|
static int ram_save_target_page_legacy(RAMState *rs, PageSearchStatus *pss)
|
|
static int ram_save_target_page_legacy(RAMState *rs, PageSearchStatus *pss)
|
|
{
|
|
{
|
|
- RAMBlock *block = pss->block;
|
|
|
|
ram_addr_t offset = ((ram_addr_t)pss->page) << TARGET_PAGE_BITS;
|
|
ram_addr_t offset = ((ram_addr_t)pss->page) << TARGET_PAGE_BITS;
|
|
int res;
|
|
int res;
|
|
|
|
|
|
@@ -2095,17 +2094,33 @@ static int ram_save_target_page_legacy(RAMState *rs, PageSearchStatus *pss)
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ return ram_save_page(rs, pss);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * ram_save_target_page_multifd: send one target page to multifd workers
|
|
|
|
+ *
|
|
|
|
+ * Returns 1 if the page was queued, -1 otherwise.
|
|
|
|
+ *
|
|
|
|
+ * @rs: current RAM state
|
|
|
|
+ * @pss: data about the page we want to send
|
|
|
|
+ */
|
|
|
|
+static int ram_save_target_page_multifd(RAMState *rs, PageSearchStatus *pss)
|
|
|
|
+{
|
|
|
|
+ RAMBlock *block = pss->block;
|
|
|
|
+ ram_addr_t offset = ((ram_addr_t)pss->page) << TARGET_PAGE_BITS;
|
|
|
|
+
|
|
/*
|
|
/*
|
|
- * Do not use multifd in postcopy as one whole host page should be
|
|
|
|
- * placed. Meanwhile postcopy requires atomic update of pages, so even
|
|
|
|
- * if host page size == guest page size the dest guest during run may
|
|
|
|
- * still see partially copied pages which is data corruption.
|
|
|
|
|
|
+ * While using multifd live migration, we still need to handle zero
|
|
|
|
+ * page checking on the migration main thread.
|
|
*/
|
|
*/
|
|
- if (migrate_multifd() && !migration_in_postcopy()) {
|
|
|
|
- return ram_save_multifd_page(block, offset);
|
|
|
|
|
|
+ if (migrate_zero_page_detection() == ZERO_PAGE_DETECTION_LEGACY) {
|
|
|
|
+ if (save_zero_page(rs, pss, offset)) {
|
|
|
|
+ return 1;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
- return ram_save_page(rs, pss);
|
|
|
|
|
|
+ return ram_save_multifd_page(block, offset);
|
|
}
|
|
}
|
|
|
|
|
|
/* Should be called before sending a host page */
|
|
/* Should be called before sending a host page */
|
|
@@ -3112,7 +3127,12 @@ static int ram_save_setup(QEMUFile *f, void *opaque)
|
|
}
|
|
}
|
|
|
|
|
|
migration_ops = g_malloc0(sizeof(MigrationOps));
|
|
migration_ops = g_malloc0(sizeof(MigrationOps));
|
|
- migration_ops->ram_save_target_page = ram_save_target_page_legacy;
|
|
|
|
|
|
+
|
|
|
|
+ if (migrate_multifd()) {
|
|
|
|
+ migration_ops->ram_save_target_page = ram_save_target_page_multifd;
|
|
|
|
+ } else {
|
|
|
|
+ migration_ops->ram_save_target_page = ram_save_target_page_legacy;
|
|
|
|
+ }
|
|
|
|
|
|
bql_unlock();
|
|
bql_unlock();
|
|
ret = multifd_send_sync_main();
|
|
ret = multifd_send_sync_main();
|