Perform final cleanup in a bottom half, and add joining the thread to the series of cleanup actions.
Signed-off-by: Paolo Bonzini <pbonz...@redhat.com> --- include/migration/migration.h | 1 + migration.c | 37 +++++++++++++++++++------------------ 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/include/migration/migration.h b/include/migration/migration.h index 4928642..d78bbbb 100644 --- a/include/migration/migration.h +++ b/include/migration/migration.h @@ -38,6 +38,7 @@ struct MigrationState size_t buffer_size; size_t buffer_capacity; QemuThread thread; + QEMUBH *cleanup_bh; QEMUFile *file; int fd; diff --git a/migration.c b/migration.c index a7f619b..8abaaea 100644 --- a/migration.c +++ b/migration.c @@ -260,8 +260,13 @@ void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params, /* shared migration helpers */ -static void migrate_fd_cleanup(MigrationState *s) +static void migrate_fd_cleanup(void *opaque) { + MigrationState *s = opaque; + + qemu_bh_delete(s->cleanup_bh); + s->cleanup_bh = NULL; + if (s->file) { DPRINTF("closing file\n"); qemu_fclose(s->file); @@ -281,15 +286,9 @@ static void migrate_fd_cleanup(MigrationState *s) void migrate_fd_error(MigrationState *s) { DPRINTF("setting error state\n"); - __sync_val_compare_and_swap(&s->state, MIG_STATE_ACTIVE, MIG_STATE_ERROR); - migrate_fd_cleanup(s); -} - -static void migrate_fd_completed(MigrationState *s) -{ - DPRINTF("setting completed state\n"); - __sync_val_compare_and_swap(&s->state, MIG_STATE_ACTIVE, MIG_STATE_COMPLETED); - migrate_fd_cleanup(s); + assert(s->file == NULL); + s->state = MIG_STATE_ERROR; + notifier_list_notify(&migration_state_notifiers, s); } static ssize_t migrate_fd_put_buffer(MigrationState *s, const void *data, @@ -316,7 +315,6 @@ static void migrate_fd_cancel(MigrationState *s) DPRINTF("cancelling migration\n"); __sync_val_compare_and_swap(&s->state, MIG_STATE_ACTIVE, MIG_STATE_CANCELLED); - migrate_fd_cleanup(s); } int migrate_fd_close(MigrationState *s) @@ -580,6 +578,11 @@ static int buffered_close(void *opaque) DPRINTF("closing\n"); + qemu_mutex_unlock_iothread(); + qemu_thread_join(&s->thread); + qemu_mutex_lock_iothread(); + assert (s->state != MIG_STATE_ACTIVE); + return migrate_fd_close(s); } @@ -692,13 +695,9 @@ static void *buffered_file_thread(void *opaque) } buffered_flush(s); if (qemu_file_get_error(s->file)) { - qemu_mutex_lock_iothread(); - migrate_fd_error(s); - qemu_mutex_unlock_iothread(); + __sync_val_compare_and_swap(&s->state, MIG_STATE_ACTIVE, MIG_STATE_ERROR); } else if (last_round && s->buffer_size == 0) { - qemu_mutex_lock_iothread(); - migrate_fd_completed(s); - qemu_mutex_unlock_iothread(); + __sync_val_compare_and_swap(&s->state, MIG_STATE_ACTIVE, MIG_STATE_COMPLETED); } } @@ -714,6 +713,7 @@ static void *buffered_file_thread(void *opaque) vm_start(); } } + qemu_bh_schedule(s->cleanup_bh); qemu_mutex_unlock_iothread(); g_free(s->buffer); @@ -739,9 +739,10 @@ void migrate_fd_connect(MigrationState *s) s->xfer_limit = s->bandwidth_limit / XFER_LIMIT_RATIO; + s->cleanup_bh = qemu_bh_new(migrate_fd_cleanup, s); s->file = qemu_fopen_ops(s, &buffered_file_ops); qemu_thread_create(&s->thread, buffered_file_thread, s, - QEMU_THREAD_DETACHED); + QEMU_THREAD_JOINABLE); notifier_list_notify(&migration_state_notifiers, s); } -- 1.7.1