[PATCH 16/18] migration: introduce migrate_ft_trans_{put,get}_ready(), and modify migrate_fd_put_ready() when ft_mode is on.
From: Yoshiaki Tamura tamura.yoshi...@lab.ntt.co.jp Introduce migrate_ft_trans_put_ready() which kicks the FT transaction cycle. When ft_mode is on, migrate_fd_put_ready() would open ft_trans_file and turn on event_tap. To end or cancel FT transaction, ft_mode and event_tap is turned off. migrate_ft_trans_get_ready() is called to receive ack from the receiver. Signed-off-by: Yoshiaki Tamura tamura.yoshi...@lab.ntt.co.jp Signed-off-by: OHMURA Kei ohmura@lab.ntt.co.jp --- migration.c | 266 ++- 1 files changed, 265 insertions(+), 1 deletions(-) diff --git a/migration.c b/migration.c index 1c2d956..d536df0 100644 --- a/migration.c +++ b/migration.c @@ -21,6 +21,7 @@ #include qemu_socket.h #include block-migration.h #include qemu-objects.h +#include event-tap.h //#define DEBUG_MIGRATION @@ -283,6 +284,17 @@ void migrate_fd_error(FdMigrationState *s) migrate_fd_cleanup(s); } +static void migrate_ft_trans_error(FdMigrationState *s) +{ +ft_mode = FT_ERROR; +qemu_savevm_state_cancel(s-mon, s-file); +migrate_fd_error(s); +/* we need to set vm running to avoid assert in virtio-net */ +vm_start(); +event_tap_unregister(); +vm_stop(0); +} + int migrate_fd_cleanup(FdMigrationState *s) { int ret = 0; @@ -318,6 +330,17 @@ void migrate_fd_put_notify(void *opaque) qemu_file_put_notify(s-file); } +static void migrate_fd_get_notify(void *opaque) +{ +FdMigrationState *s = opaque; + +qemu_set_fd_handler2(s-fd, NULL, NULL, NULL, NULL); +qemu_file_get_notify(s-file); +if (qemu_file_has_error(s-file)) { +migrate_ft_trans_error(s); +} +} + ssize_t migrate_fd_put_buffer(void *opaque, const void *data, size_t size) { FdMigrationState *s = opaque; @@ -353,6 +376,10 @@ int migrate_fd_get_buffer(void *opaque, uint8_t *data, int64_t pos, size_t size) ret = -(s-get_error(s)); } +if (ret == -EAGAIN) { +qemu_set_fd_handler2(s-fd, NULL, migrate_fd_get_notify, NULL, s); +} + return ret; } @@ -379,6 +406,230 @@ void migrate_fd_connect(FdMigrationState *s) migrate_fd_put_ready(s); } +static int migrate_ft_trans_commit(void *opaque) +{ +FdMigrationState *s = opaque; +int ret = -1; + +if (ft_mode != FT_TRANSACTION_COMMIT ft_mode != FT_TRANSACTION_ATOMIC) { +fprintf(stderr, +migrate_ft_trans_commit: invalid ft_mode %d\n, ft_mode); +goto out; +} + +do { +if (ft_mode == FT_TRANSACTION_ATOMIC) { +if (qemu_ft_trans_begin(s-file) 0) { +fprintf(stderr, qemu_ft_trans_begin failed\n); +goto out; +} + +ret = qemu_savevm_trans_begin(s-mon, s-file, 0); +if (ret 0) { +fprintf(stderr, qemu_savevm_trans_begin failed\n); +goto out; +} + +ft_mode = FT_TRANSACTION_COMMIT; +if (ret) { +/* don't proceed until if fd isn't ready */ +goto out; +} +} + +/* make the VM state consistent by flushing outstanding events */ +vm_stop(0); + +/* send at full speed */ +qemu_file_set_rate_limit(s-file, 0); + +ret = qemu_savevm_trans_complete(s-mon, s-file); +if (ret 0) { +fprintf(stderr, qemu_savevm_trans_complete failed\n); +goto out; +} + +ret = qemu_ft_trans_commit(s-file); +if (ret 0) { +fprintf(stderr, qemu_ft_trans_commit failed\n); +goto out; +} + +if (ret) { +ft_mode = FT_TRANSACTION_RECV; +ret = 1; +goto out; +} + +/* flush and check if events are remaining */ +vm_start(); +ret = event_tap_flush_one(); +if (ret 0) { +fprintf(stderr, event_tap_flush_one failed\n); +goto out; +} + +ft_mode = ret ? FT_TRANSACTION_BEGIN : FT_TRANSACTION_ATOMIC; +} while (ft_mode != FT_TRANSACTION_BEGIN); + +vm_start(); +ret = 0; + +out: +return ret; +} + +static int migrate_ft_trans_get_ready(void *opaque) +{ +FdMigrationState *s = opaque; +int ret = -1; + +if (ft_mode != FT_TRANSACTION_RECV) { +fprintf(stderr, +migrate_ft_trans_get_ready: invalid ft_mode %d\n, ft_mode); +goto error_out; +} + +/* flush and check if events are remaining */ +vm_start(); +ret = event_tap_flush_one(); +if (ret 0) { +fprintf(stderr, event_tap_flush_one failed\n); +goto error_out; +} + +if (ret) { +ft_mode = FT_TRANSACTION_BEGIN; +} else { +ft_mode = FT_TRANSACTION_ATOMIC; + +ret = migrate_ft_trans_commit(s); +if (ret 0) { +goto error_out; +} +if (ret) { +goto out; +} +} + +vm_start(); +ret = 0; +
[PATCH 16/18] migration: introduce migrate_ft_trans_{put,get}_ready(), and modify migrate_fd_put_ready() when ft_mode is on.
Introduce migrate_ft_trans_put_ready() which kicks the FT transaction cycle. When ft_mode is on, migrate_fd_put_ready() would open ft_trans_file and turn on event_tap. To end or cancel FT transaction, ft_mode and event_tap is turned off. migrate_ft_trans_get_ready() is called to receive ack from the receiver. Signed-off-by: Yoshiaki Tamura tamura.yoshi...@lab.ntt.co.jp --- migration.c | 266 ++- 1 files changed, 265 insertions(+), 1 deletions(-) diff --git a/migration.c b/migration.c index 1c2d956..d536df0 100644 --- a/migration.c +++ b/migration.c @@ -21,6 +21,7 @@ #include qemu_socket.h #include block-migration.h #include qemu-objects.h +#include event-tap.h //#define DEBUG_MIGRATION @@ -283,6 +284,17 @@ void migrate_fd_error(FdMigrationState *s) migrate_fd_cleanup(s); } +static void migrate_ft_trans_error(FdMigrationState *s) +{ +ft_mode = FT_ERROR; +qemu_savevm_state_cancel(s-mon, s-file); +migrate_fd_error(s); +/* we need to set vm running to avoid assert in virtio-net */ +vm_start(); +event_tap_unregister(); +vm_stop(0); +} + int migrate_fd_cleanup(FdMigrationState *s) { int ret = 0; @@ -318,6 +330,17 @@ void migrate_fd_put_notify(void *opaque) qemu_file_put_notify(s-file); } +static void migrate_fd_get_notify(void *opaque) +{ +FdMigrationState *s = opaque; + +qemu_set_fd_handler2(s-fd, NULL, NULL, NULL, NULL); +qemu_file_get_notify(s-file); +if (qemu_file_has_error(s-file)) { +migrate_ft_trans_error(s); +} +} + ssize_t migrate_fd_put_buffer(void *opaque, const void *data, size_t size) { FdMigrationState *s = opaque; @@ -353,6 +376,10 @@ int migrate_fd_get_buffer(void *opaque, uint8_t *data, int64_t pos, size_t size) ret = -(s-get_error(s)); } +if (ret == -EAGAIN) { +qemu_set_fd_handler2(s-fd, NULL, migrate_fd_get_notify, NULL, s); +} + return ret; } @@ -379,6 +406,230 @@ void migrate_fd_connect(FdMigrationState *s) migrate_fd_put_ready(s); } +static int migrate_ft_trans_commit(void *opaque) +{ +FdMigrationState *s = opaque; +int ret = -1; + +if (ft_mode != FT_TRANSACTION_COMMIT ft_mode != FT_TRANSACTION_ATOMIC) { +fprintf(stderr, +migrate_ft_trans_commit: invalid ft_mode %d\n, ft_mode); +goto out; +} + +do { +if (ft_mode == FT_TRANSACTION_ATOMIC) { +if (qemu_ft_trans_begin(s-file) 0) { +fprintf(stderr, qemu_ft_trans_begin failed\n); +goto out; +} + +ret = qemu_savevm_trans_begin(s-mon, s-file, 0); +if (ret 0) { +fprintf(stderr, qemu_savevm_trans_begin failed\n); +goto out; +} + +ft_mode = FT_TRANSACTION_COMMIT; +if (ret) { +/* don't proceed until if fd isn't ready */ +goto out; +} +} + +/* make the VM state consistent by flushing outstanding events */ +vm_stop(0); + +/* send at full speed */ +qemu_file_set_rate_limit(s-file, 0); + +ret = qemu_savevm_trans_complete(s-mon, s-file); +if (ret 0) { +fprintf(stderr, qemu_savevm_trans_complete failed\n); +goto out; +} + +ret = qemu_ft_trans_commit(s-file); +if (ret 0) { +fprintf(stderr, qemu_ft_trans_commit failed\n); +goto out; +} + +if (ret) { +ft_mode = FT_TRANSACTION_RECV; +ret = 1; +goto out; +} + +/* flush and check if events are remaining */ +vm_start(); +ret = event_tap_flush_one(); +if (ret 0) { +fprintf(stderr, event_tap_flush_one failed\n); +goto out; +} + +ft_mode = ret ? FT_TRANSACTION_BEGIN : FT_TRANSACTION_ATOMIC; +} while (ft_mode != FT_TRANSACTION_BEGIN); + +vm_start(); +ret = 0; + +out: +return ret; +} + +static int migrate_ft_trans_get_ready(void *opaque) +{ +FdMigrationState *s = opaque; +int ret = -1; + +if (ft_mode != FT_TRANSACTION_RECV) { +fprintf(stderr, +migrate_ft_trans_get_ready: invalid ft_mode %d\n, ft_mode); +goto error_out; +} + +/* flush and check if events are remaining */ +vm_start(); +ret = event_tap_flush_one(); +if (ret 0) { +fprintf(stderr, event_tap_flush_one failed\n); +goto error_out; +} + +if (ret) { +ft_mode = FT_TRANSACTION_BEGIN; +} else { +ft_mode = FT_TRANSACTION_ATOMIC; + +ret = migrate_ft_trans_commit(s); +if (ret 0) { +goto error_out; +} +if (ret) { +goto out; +} +} + +vm_start(); +ret = 0; +goto out; + +error_out: +migrate_ft_trans_error(s); + +out: +return ret; +} + +static int
[PATCH 16/18] migration: introduce migrate_ft_trans_{put,get}_ready(), and modify migrate_fd_put_ready() when ft_mode is on.
Introduce migrate_ft_trans_put_ready() which kicks the FT transaction cycle. When ft_mode is on, migrate_fd_put_ready() would open ft_trans_file and turn on event_tap. To end or cancel FT transaction, ft_mode and event_tap is turned off. migrate_ft_trans_get_ready() is called to receive ack from the receiver. Signed-off-by: Yoshiaki Tamura tamura.yoshi...@lab.ntt.co.jp --- migration.c | 261 ++- 1 files changed, 260 insertions(+), 1 deletions(-) diff --git a/migration.c b/migration.c index 3be3554..82f4a4d 100644 --- a/migration.c +++ b/migration.c @@ -21,6 +21,7 @@ #include qemu_socket.h #include block-migration.h #include qemu-objects.h +#include event-tap.h //#define DEBUG_MIGRATION @@ -283,6 +284,14 @@ void migrate_fd_error(FdMigrationState *s) migrate_fd_cleanup(s); } +static void migrate_ft_trans_error(FdMigrationState *s) +{ +ft_mode = FT_ERROR; +qemu_savevm_state_cancel(s-mon, s-file); +migrate_fd_error(s); +event_tap_unregister(); +} + int migrate_fd_cleanup(FdMigrationState *s) { int ret = 0; @@ -318,6 +327,17 @@ void migrate_fd_put_notify(void *opaque) qemu_file_put_notify(s-file); } +static void migrate_fd_get_notify(void *opaque) +{ +FdMigrationState *s = opaque; + +qemu_set_fd_handler2(s-fd, NULL, NULL, NULL, NULL); +qemu_file_get_notify(s-file); +if (qemu_file_has_error(s-file)) { +migrate_ft_trans_error(s); +} +} + ssize_t migrate_fd_put_buffer(void *opaque, const void *data, size_t size) { FdMigrationState *s = opaque; @@ -353,6 +373,10 @@ int migrate_fd_get_buffer(void *opaque, uint8_t *data, int64_t pos, size_t size) ret = -(s-get_error(s)); } +if (ret == -EAGAIN) { +qemu_set_fd_handler2(s-fd, NULL, migrate_fd_get_notify, NULL, s); +} + return ret; } @@ -379,6 +403,230 @@ void migrate_fd_connect(FdMigrationState *s) migrate_fd_put_ready(s); } +static int migrate_ft_trans_commit(void *opaque) +{ +FdMigrationState *s = opaque; +int ret = -1; + +if (ft_mode != FT_TRANSACTION_COMMIT ft_mode != FT_TRANSACTION_ATOMIC) { +fprintf(stderr, +migrate_ft_trans_commit: invalid ft_mode %d\n, ft_mode); +goto out; +} + +do { +if (ft_mode == FT_TRANSACTION_ATOMIC) { +if (qemu_ft_trans_begin(s-file) 0) { +fprintf(stderr, qemu_ft_trans_begin failed\n); +goto out; +} + +ret = qemu_savevm_trans_begin(s-mon, s-file, 0); +if (ret 0) { +fprintf(stderr, qemu_savevm_trans_begin failed\n); +goto out; +} + +ft_mode = FT_TRANSACTION_COMMIT; +if (ret) { +/* don't proceed until if fd isn't ready */ +goto out; +} +} + +/* make the VM state consistent by flushing outstanding events */ +vm_stop(0); + +/* send at full speed */ +qemu_file_set_rate_limit(s-file, 0); + +ret = qemu_savevm_trans_complete(s-mon, s-file); +if (ret 0) { +fprintf(stderr, qemu_savevm_trans_complete failed\n); +goto out; +} + +ret = qemu_ft_trans_commit(s-file); +if (ret 0) { +fprintf(stderr, qemu_ft_trans_commit failed\n); +goto out; +} + +if (ret) { +ft_mode = FT_TRANSACTION_RECV; +ret = 1; +goto out; +} + +/* flush and check if events are remaining */ +vm_start(); +ret = event_tap_flush_one(); +if (ret 0) { +fprintf(stderr, event_tap_flush_one failed\n); +goto out; +} + +ft_mode = ret ? FT_TRANSACTION_BEGIN : FT_TRANSACTION_ATOMIC; +} while (ft_mode != FT_TRANSACTION_BEGIN); + +vm_start(); +ret = 0; + +out: +return ret; +} + +static int migrate_ft_trans_get_ready(void *opaque) +{ +FdMigrationState *s = opaque; +int ret = -1; + +if (ft_mode != FT_TRANSACTION_RECV) { +fprintf(stderr, +migrate_ft_trans_get_ready: invalid ft_mode %d\n, ft_mode); +goto error_out; +} + +/* flush and check if events are remaining */ +vm_start(); +ret = event_tap_flush_one(); +if (ret 0) { +fprintf(stderr, event_tap_flush_one failed\n); +goto error_out; +} + +if (ret) { +ft_mode = FT_TRANSACTION_BEGIN; +} else { +ft_mode = FT_TRANSACTION_ATOMIC; + +ret = migrate_ft_trans_commit(s); +if (ret 0) { +goto error_out; +} +if (ret) { +goto out; +} +} + +vm_start(); +ret = 0; +goto out; + +error_out: +migrate_ft_trans_error(s); + +out: +return ret; +} + +static int migrate_ft_trans_put_ready(void) +{ +FdMigrationState *s = migrate_to_fms(current_migration); +
[PATCH 16/18] migration: introduce migrate_ft_trans_{put,get}_ready(), and modify migrate_fd_put_ready() when ft_mode is on.
Introduce migrate_ft_trans_put_ready() which kicks the FT transaction cycle. When ft_mode is on, migrate_fd_put_ready() would open ft_trans_file and turn on event_tap. To end or cancel FT transaction, ft_mode and event_tap is turned off. migrate_ft_trans_get_ready() is called to receive ack from the receiver. Signed-off-by: Yoshiaki Tamura tamura.yoshi...@lab.ntt.co.jp --- migration.c | 261 ++- 1 files changed, 260 insertions(+), 1 deletions(-) diff --git a/migration.c b/migration.c index 1c2d956..cdea459 100644 --- a/migration.c +++ b/migration.c @@ -21,6 +21,7 @@ #include qemu_socket.h #include block-migration.h #include qemu-objects.h +#include event-tap.h //#define DEBUG_MIGRATION @@ -283,6 +284,14 @@ void migrate_fd_error(FdMigrationState *s) migrate_fd_cleanup(s); } +static void migrate_ft_trans_error(FdMigrationState *s) +{ +ft_mode = FT_ERROR; +qemu_savevm_state_cancel(s-mon, s-file); +migrate_fd_error(s); +event_tap_unregister(); +} + int migrate_fd_cleanup(FdMigrationState *s) { int ret = 0; @@ -318,6 +327,17 @@ void migrate_fd_put_notify(void *opaque) qemu_file_put_notify(s-file); } +static void migrate_fd_get_notify(void *opaque) +{ +FdMigrationState *s = opaque; + +qemu_set_fd_handler2(s-fd, NULL, NULL, NULL, NULL); +qemu_file_get_notify(s-file); +if (qemu_file_has_error(s-file)) { +migrate_ft_trans_error(s); +} +} + ssize_t migrate_fd_put_buffer(void *opaque, const void *data, size_t size) { FdMigrationState *s = opaque; @@ -353,6 +373,10 @@ int migrate_fd_get_buffer(void *opaque, uint8_t *data, int64_t pos, size_t size) ret = -(s-get_error(s)); } +if (ret == -EAGAIN) { +qemu_set_fd_handler2(s-fd, NULL, migrate_fd_get_notify, NULL, s); +} + return ret; } @@ -379,6 +403,230 @@ void migrate_fd_connect(FdMigrationState *s) migrate_fd_put_ready(s); } +static int migrate_ft_trans_commit(void *opaque) +{ +FdMigrationState *s = opaque; +int ret = -1; + +if (ft_mode != FT_TRANSACTION_COMMIT ft_mode != FT_TRANSACTION_ATOMIC) { +fprintf(stderr, +migrate_ft_trans_commit: invalid ft_mode %d\n, ft_mode); +goto out; +} + +do { +if (ft_mode == FT_TRANSACTION_ATOMIC) { +if (qemu_ft_trans_begin(s-file) 0) { +fprintf(stderr, qemu_ft_trans_begin failed\n); +goto out; +} + +ret = qemu_savevm_trans_begin(s-mon, s-file, 0); +if (ret 0) { +fprintf(stderr, qemu_savevm_trans_begin failed\n); +goto out; +} + +ft_mode = FT_TRANSACTION_COMMIT; +if (ret) { +/* don't proceed until if fd isn't ready */ +goto out; +} +} + +/* make the VM state consistent by flushing outstanding events */ +vm_stop(0); + +/* send at full speed */ +qemu_file_set_rate_limit(s-file, 0); + +ret = qemu_savevm_trans_complete(s-mon, s-file); +if (ret 0) { +fprintf(stderr, qemu_savevm_trans_complete failed\n); +goto out; +} + +ret = qemu_ft_trans_commit(s-file); +if (ret 0) { +fprintf(stderr, qemu_ft_trans_commit failed\n); +goto out; +} + +if (ret) { +ft_mode = FT_TRANSACTION_RECV; +ret = 1; +goto out; +} + +/* flush and check if events are remaining */ +vm_start(); +ret = event_tap_flush_one(); +if (ret 0) { +fprintf(stderr, event_tap_flush_one failed\n); +goto out; +} + +ft_mode = ret ? FT_TRANSACTION_BEGIN : FT_TRANSACTION_ATOMIC; +} while (ft_mode != FT_TRANSACTION_BEGIN); + +vm_start(); +ret = 0; + +out: +return ret; +} + +static int migrate_ft_trans_get_ready(void *opaque) +{ +FdMigrationState *s = opaque; +int ret = -1; + +if (ft_mode != FT_TRANSACTION_RECV) { +fprintf(stderr, +migrate_ft_trans_get_ready: invalid ft_mode %d\n, ft_mode); +goto error_out; +} + +/* flush and check if events are remaining */ +vm_start(); +ret = event_tap_flush_one(); +if (ret 0) { +fprintf(stderr, event_tap_flush_one failed\n); +goto error_out; +} + +if (ret) { +ft_mode = FT_TRANSACTION_BEGIN; +} else { +ft_mode = FT_TRANSACTION_ATOMIC; + +ret = migrate_ft_trans_commit(s); +if (ret 0) { +goto error_out; +} +if (ret) { +goto out; +} +} + +vm_start(); +ret = 0; +goto out; + +error_out: +migrate_ft_trans_error(s); + +out: +return ret; +} + +static int migrate_ft_trans_put_ready(void) +{ +FdMigrationState *s = migrate_to_fms(current_migration); +
[PATCH 16/18] migration: introduce migrate_ft_trans_{put,get}_ready(), and modify migrate_fd_put_ready() when ft_mode is on.
Introduce migrate_ft_trans_put_ready() which kicks the FT transaction cycle. When ft_mode is on, migrate_fd_put_ready() would open ft_trans_file and turn on event_tap. To end or cancel FT transaction, ft_mode and event_tap is turned off. migrate_ft_trans_get_ready() is called to receive ack from the receiver. Signed-off-by: Yoshiaki Tamura tamura.yoshi...@lab.ntt.co.jp --- migration.c | 261 ++- 1 files changed, 260 insertions(+), 1 deletions(-) diff --git a/migration.c b/migration.c index c5e0146..7837c55 100644 --- a/migration.c +++ b/migration.c @@ -21,6 +21,7 @@ #include qemu_socket.h #include block-migration.h #include qemu-objects.h +#include event-tap.h //#define DEBUG_MIGRATION @@ -283,6 +284,14 @@ void migrate_fd_error(FdMigrationState *s) migrate_fd_cleanup(s); } +static void migrate_ft_trans_error(FdMigrationState *s) +{ +ft_mode = FT_ERROR; +qemu_savevm_state_cancel(s-mon, s-file); +migrate_fd_error(s); +event_tap_unregister(); +} + int migrate_fd_cleanup(FdMigrationState *s) { int ret = 0; @@ -318,6 +327,17 @@ void migrate_fd_put_notify(void *opaque) qemu_file_put_notify(s-file); } +static void migrate_fd_get_notify(void *opaque) +{ +FdMigrationState *s = opaque; + +qemu_set_fd_handler2(s-fd, NULL, NULL, NULL, NULL); +qemu_file_get_notify(s-file); +if (qemu_file_has_error(s-file)) { +migrate_ft_trans_error(s); +} +} + ssize_t migrate_fd_put_buffer(void *opaque, const void *data, size_t size) { FdMigrationState *s = opaque; @@ -353,6 +373,10 @@ int migrate_fd_get_buffer(void *opaque, uint8_t *data, int64_t pos, size_t size) ret = -(s-get_error(s)); } +if (ret == -EAGAIN) { +qemu_set_fd_handler2(s-fd, NULL, migrate_fd_get_notify, NULL, s); +} + return ret; } @@ -379,6 +403,230 @@ void migrate_fd_connect(FdMigrationState *s) migrate_fd_put_ready(s); } +static int migrate_ft_trans_commit(void *opaque) +{ +FdMigrationState *s = opaque; +int ret = -1; + +if (ft_mode != FT_TRANSACTION_COMMIT ft_mode != FT_TRANSACTION_ATOMIC) { +fprintf(stderr, +migrate_ft_trans_commit: invalid ft_mode %d\n, ft_mode); +goto out; +} + +do { +if (ft_mode == FT_TRANSACTION_ATOMIC) { +if (qemu_ft_trans_begin(s-file) 0) { +fprintf(stderr, qemu_ft_trans_begin failed\n); +goto out; +} + +ret = qemu_savevm_trans_begin(s-mon, s-file, 0); +if (ret 0) { +fprintf(stderr, qemu_savevm_trans_begin failed\n); +goto out; +} + +ft_mode = FT_TRANSACTION_COMMIT; +if (ret) { +/* don't proceed until if fd isn't ready */ +goto out; +} +} + +/* make the VM state consistent by flushing outstanding events */ +vm_stop(0); + +/* send at full speed */ +qemu_file_set_rate_limit(s-file, 0); + +ret = qemu_savevm_trans_complete(s-mon, s-file); +if (ret 0) { +fprintf(stderr, qemu_savevm_trans_complete failed\n); +goto out; +} + +ret = qemu_ft_trans_commit(s-file); +if (ret 0) { +fprintf(stderr, qemu_ft_trans_commit failed\n); +goto out; +} + +if (ret) { +ft_mode = FT_TRANSACTION_RECV; +ret = 1; +goto out; +} + +/* flush and check if events are remaining */ +vm_start(); +ret = event_tap_flush_one(); +if (ret 0) { +fprintf(stderr, event_tap_flush_one failed\n); +goto out; +} + +ft_mode = ret ? FT_TRANSACTION_BEGIN : FT_TRANSACTION_ATOMIC; +} while (ft_mode != FT_TRANSACTION_BEGIN); + +vm_start(); +ret = 0; + +out: +return ret; +} + +static int migrate_ft_trans_get_ready(void *opaque) +{ +FdMigrationState *s = opaque; +int ret = -1; + +if (ft_mode != FT_TRANSACTION_RECV) { +fprintf(stderr, +migrate_ft_trans_get_ready: invalid ft_mode %d\n, ft_mode); +goto error_out; +} + +/* flush and check if events are remaining */ +vm_start(); +ret = event_tap_flush_one(); +if (ret 0) { +fprintf(stderr, event_tap_flush_one failed\n); +goto error_out; +} + +if (ret) { +ft_mode = FT_TRANSACTION_BEGIN; +} else { +ft_mode = FT_TRANSACTION_ATOMIC; + +ret = migrate_ft_trans_commit(s); +if (ret 0) { +goto error_out; +} +if (ret) { +goto out; +} +} + +vm_start(); +ret = 0; +goto out; + +error_out: +migrate_ft_trans_error(s); + +out: +return ret; +} + +static int migrate_ft_trans_put_ready(void) +{ +FdMigrationState *s = migrate_to_fms(current_migration); +