@@ -348,7 +348,7 @@ retry:
return true;
}
-int multifd_ram_flush_and_sync(void)
+int multifd_ram_flush(void)
{
if (!migrate_multifd()) {
return 0;
@@ -361,6 +361,22 @@ int multifd_ram_flush_and_sync(void)
}
}
+ return 0;
+}
+
+int multifd_ram_flush_and_sync(void)
+{
+ int ret;
+
+ if (!migrate_multifd()) {
+ return 0;
+ }
+
+ ret = multifd_ram_flush();
+ if (ret) {
+ return ret;
+ }
+
return multifd_send_sync_main();
}
@@ -376,6 +376,7 @@ static inline uint32_t multifd_ram_page_count(void)
void multifd_ram_save_setup(void);
void multifd_ram_save_cleanup(void);
+int multifd_ram_flush(void);
int multifd_ram_flush_and_sync(void);
void multifd_ram_payload_alloc(MultiFDPages_t *pages);
void multifd_ram_payload_free(MultiFDPages_t *pages);
@@ -3283,7 +3283,15 @@ static int ram_save_complete(QEMUFile *f, void *opaque)
}
}
- ret = multifd_ram_flush_and_sync();
+ if (migration_has_device_state_support()) {
+ /*
+ * Can't do the final SYNC here since device state might still
+ * be transferring via multifd channels.
+ */
+ ret = multifd_ram_flush();
+ } else {
+ ret = multifd_ram_flush_and_sync();
+ }
if (ret < 0) {
return ret;
}
@@ -37,6 +37,7 @@
#include "migration/register.h"
#include "migration/global_state.h"
#include "migration/channel-block.h"
+#include "multifd.h"
#include "ram.h"
#include "qemu-file.h"
#include "savevm.h"
@@ -1496,6 +1497,7 @@ int qemu_savevm_state_complete_precopy_iterable(QEMUFile *f, bool in_postcopy)
int64_t start_ts_each, end_ts_each;
SaveStateEntry *se;
int ret;
+ bool multifd_device_state = migration_has_device_state_support();
QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
if (!se->ops ||
@@ -1528,6 +1530,15 @@ int qemu_savevm_state_complete_precopy_iterable(QEMUFile *f, bool in_postcopy)
end_ts_each - start_ts_each);
}
+ if (multifd_device_state) {
+ /* Send the final SYNC */
+ ret = multifd_send_sync_main();
+ if (ret) {
+ qemu_file_set_error(f, ret);
+ return -1;
+ }
+ }
+
trace_vmstate_downtime_checkpoint("src-iterable-saved");
return 0;