From: Lidong Chen <jemmy858...@gmail.com> The channel_close maybe invoked by different threads. For example, source qemu invokes qemu_fclose in main thread, migration thread and return path thread. Destination qemu invokes qemu_fclose in main thread, listen thread and COLO incoming thread.
Signed-off-by: Lidong Chen <lidongc...@tencent.com> Reviewed-by: Daniel P. Berrangé <berra...@redhat.com> --- migration/migration.c | 2 ++ migration/migration.h | 7 +++++++ migration/qemu-file.c | 6 ++++-- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/migration/migration.c b/migration/migration.c index b7d9854..a3a0756 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -3200,6 +3200,7 @@ static void migration_instance_finalize(Object *obj) qemu_sem_destroy(&ms->postcopy_pause_sem); qemu_sem_destroy(&ms->postcopy_pause_rp_sem); qemu_sem_destroy(&ms->rp_state.rp_sem); + qemu_mutex_destroy(&ms->qemu_file_close_lock); error_free(ms->error); } @@ -3236,6 +3237,7 @@ static void migration_instance_init(Object *obj) qemu_sem_init(&ms->rp_state.rp_sem, 0); qemu_sem_init(&ms->rate_limit_sem, 0); qemu_mutex_init(&ms->qemu_file_lock); + qemu_mutex_init(&ms->qemu_file_close_lock); } /* diff --git a/migration/migration.h b/migration/migration.h index 64a7b33..a50c2de 100644 --- a/migration/migration.h +++ b/migration/migration.h @@ -122,6 +122,13 @@ struct MigrationState QemuMutex qemu_file_lock; /* + * The to_src_file and from_dst_file point to one QIOChannelRDMA, + * And qemu_fclose maybe invoked by different threads. use this lock + * to avoid concurrent invoke channel_close by different threads. + */ + QemuMutex qemu_file_close_lock; + + /* * Used to allow urgent requests to override rate limiting. */ QemuSemaphore rate_limit_sem; diff --git a/migration/qemu-file.c b/migration/qemu-file.c index 977b9ae..74c48e0 100644 --- a/migration/qemu-file.c +++ b/migration/qemu-file.c @@ -323,12 +323,14 @@ void qemu_update_position(QEMUFile *f, size_t size) */ int qemu_fclose(QEMUFile *f) { - int ret; + int ret, ret2; qemu_fflush(f); ret = qemu_file_get_error(f); if (f->ops->close) { - int ret2 = f->ops->close(f->opaque); + qemu_mutex_lock(&migrate_get_current()->qemu_file_close_lock); + ret2 = f->ops->close(f->opaque); + qemu_mutex_unlock(&migrate_get_current()->qemu_file_close_lock); if (ret >= 0) { ret = ret2; } -- 1.8.3.1