When the VM is shut down vfio_vmstate_change/_prepare() are called to transition the VFIO device state to STOP. They are called after migration_shutdown() and thus, by this time, the migration object is already freed (more specifically, MigrationState->qemu_file_lock is already destroyed).
In this case, if there is an error in vfio_vmstate_change/_prepare(), it calls migration_file_set_error() which tries to lock the already destroyed MigrationState->qemu_file_lock, leading to the following assert: qemu-system-x86_64: ../util/qemu-thread-posix.c:92: qemu_mutex_lock_impl: Assertion `mutex->initialized' failed. Fix this by not setting migration file error in the shut down flow. Fixes: 20c64c8a51a4 ("migration: migration_file_set_error") Signed-off-by: Avihai Horon <avih...@nvidia.com> --- hw/vfio/migration.c | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c index 992dc3b102..1c44b036ea 100644 --- a/hw/vfio/migration.c +++ b/hw/vfio/migration.c @@ -783,6 +783,25 @@ static const SaveVMHandlers savevm_vfio_handlers = { /* ---------------------------------------------------------------------- */ +static void vfio_vmstate_change_error_report(int ret, Error *err, + RunState state) +{ + if (state == RUN_STATE_SHUTDOWN) { + /* + * If VM is being shut down, migration object might have already been + * freed, so just report the error. + */ + error_report_err(err); + return; + } + + /* + * Migration should be aborted in this case, but vm_state_notify() + * currently does not support reporting failures. + */ + migration_file_set_error(ret, err); +} + static void vfio_vmstate_change_prepare(void *opaque, bool running, RunState state) { @@ -798,11 +817,7 @@ static void vfio_vmstate_change_prepare(void *opaque, bool running, ret = vfio_migration_set_state_or_reset(vbasedev, new_state, &local_err); if (ret) { - /* - * Migration should be aborted in this case, but vm_state_notify() - * currently does not support reporting failures. - */ - migration_file_set_error(ret, local_err); + vfio_vmstate_change_error_report(ret, local_err, state); } trace_vfio_vmstate_change_prepare(vbasedev->name, running, @@ -829,11 +844,7 @@ static void vfio_vmstate_change(void *opaque, bool running, RunState state) ret = vfio_migration_set_state_or_reset(vbasedev, new_state, &local_err); if (ret) { - /* - * Migration should be aborted in this case, but vm_state_notify() - * currently does not support reporting failures. - */ - migration_file_set_error(ret, local_err); + vfio_vmstate_change_error_report(ret, local_err, state); } trace_vfio_vmstate_change(vbasedev->name, running, RunState_str(state), -- 2.40.1