@@ -21,6 +21,7 @@
#include "qemu_socket.h"
#include "block-migration.h"
#include "qemu-objects.h"
+#include "event-tap.h"
//#define DEBUG_MIGRATION
@@ -375,6 +376,49 @@ void migrate_fd_connect(FdMigrationState *s)
migrate_fd_put_ready(s);
}
+static int ft_tranx_ready(void)
+{
+ FdMigrationState *s = migrate_to_fms(current_migration);
+ int ret = -1;
+
+ if (ft_mode != FT_TRANSACTION && ft_mode != FT_INIT) {
+ return ret;
+ }
+
+ if (qemu_transaction_begin(s->file) < 0) {
+ fprintf(stderr, "tranx_begin failed\n");
+ goto error_out;
+ }
+
+ /* make the VM state consistent by flushing outstanding requests. */
+ vm_stop(0);
+ qemu_aio_flush();
+ bdrv_flush_all();
+
+ if (qemu_savevm_state_all(s->mon, s->file) < 0) {
+ fprintf(stderr, "savevm_state_all failed\n");
+ goto error_out;
+ }
+
+ if (qemu_transaction_commit(s->file) < 0) {
+ fprintf(stderr, "tranx_commit failed\n");
+ goto error_out;
+ }
+
+ ret = 0;
+ goto unpause_out;
+
+error_out:
+ ft_mode = FT_OFF;
+ qemu_savevm_state_cancel(s->mon, s->file);
+ migrate_fd_cleanup(s);
+ event_tap_unregister();
+
+unpause_out:
+ vm_start();
+ return ret;
+}
+
void migrate_fd_put_ready(void *opaque)
{
FdMigrationState *s = opaque;
@@ -402,8 +446,30 @@ void migrate_fd_put_ready(void *opaque)
} else {
state = MIG_STATE_COMPLETED;
}
- migrate_fd_cleanup(s);
- s->state = state;
+
+ if (ft_mode && state == MIG_STATE_COMPLETED) {
+ /* close buffered_file and open ft_transaction.
+ * Note: file discriptor won't get closed,
+ * but reused by ft_transaction. */
+ socket_set_block(s->fd);
+ socket_set_nodelay(s->fd);
+ qemu_fclose(s->file);
+ s->file = qemu_fopen_ops_ft_tranx(s,
+ migrate_fd_put_buffer,
+ migrate_fd_get_buffer,
+ migrate_fd_close,
+ 1);
+
+ /* events are tapped from now. */
+ event_tap_register(ft_tranx_ready);
+
+ if (old_vm_running) {
+ vm_start();
+ }
+ } else {
+ migrate_fd_cleanup(s);
+ s->state = state;
+ }
}
}
@@ -423,8 +489,14 @@ void migrate_fd_cancel(MigrationState *mig_state)
DPRINTF("cancelling migration\n");
s->state = MIG_STATE_CANCELLED;
- qemu_savevm_state_cancel(s->mon, s->file);
+ if (ft_mode == FT_TRANSACTION) {
+ qemu_transaction_cancel(s->file);
+ ft_mode = FT_OFF;
+ event_tap_unregister();
+ }
+
+ qemu_savevm_state_cancel(s->mon, s->file);
migrate_fd_cleanup(s);
}