migration: Fix possible race when shutting down to_dst_file
It's not safe to call qemu_file_shutdown() on the to_dst_file without first checking for the file's presence under the lock. The cleanup of this file happens at postcopy_pause() and migrate_fd_cleanup() which are not necessarily running in the same thread as migrate_fd_cancel(). Reviewed-by: Peter Xu <peterx@redhat.com> Signed-off-by: Fabiano Rosas <farosas@suse.de> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> Message-ID: <20230918172822.19052-5-farosas@suse.de>
This commit is contained in:
parent
639decf529
commit
7478fb0df9
@ -1246,7 +1246,7 @@ static void migrate_fd_error(MigrationState *s, const Error *error)
|
||||
static void migrate_fd_cancel(MigrationState *s)
|
||||
{
|
||||
int old_state ;
|
||||
QEMUFile *f = migrate_get_current()->to_dst_file;
|
||||
|
||||
trace_migrate_fd_cancel();
|
||||
|
||||
WITH_QEMU_LOCK_GUARD(&s->qemu_file_lock) {
|
||||
@ -1272,11 +1272,13 @@ static void migrate_fd_cancel(MigrationState *s)
|
||||
* If we're unlucky the migration code might be stuck somewhere in a
|
||||
* send/write while the network has failed and is waiting to timeout;
|
||||
* if we've got shutdown(2) available then we can force it to quit.
|
||||
* The outgoing qemu file gets closed in migrate_fd_cleanup that is
|
||||
* called in a bh, so there is no race against this cancel.
|
||||
*/
|
||||
if (s->state == MIGRATION_STATUS_CANCELLING && f) {
|
||||
qemu_file_shutdown(f);
|
||||
if (s->state == MIGRATION_STATUS_CANCELLING) {
|
||||
WITH_QEMU_LOCK_GUARD(&s->qemu_file_lock) {
|
||||
if (s->to_dst_file) {
|
||||
qemu_file_shutdown(s->to_dst_file);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (s->state == MIGRATION_STATUS_CANCELLING && s->block_inactive) {
|
||||
Error *local_err = NULL;
|
||||
@ -1536,12 +1538,14 @@ void qmp_migrate_pause(Error **errp)
|
||||
{
|
||||
MigrationState *ms = migrate_get_current();
|
||||
MigrationIncomingState *mis = migration_incoming_get_current();
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
if (ms->state == MIGRATION_STATUS_POSTCOPY_ACTIVE) {
|
||||
/* Source side, during postcopy */
|
||||
qemu_mutex_lock(&ms->qemu_file_lock);
|
||||
ret = qemu_file_shutdown(ms->to_dst_file);
|
||||
if (ms->to_dst_file) {
|
||||
ret = qemu_file_shutdown(ms->to_dst_file);
|
||||
}
|
||||
qemu_mutex_unlock(&ms->qemu_file_lock);
|
||||
if (ret) {
|
||||
error_setg(errp, "Failed to pause source migration");
|
||||
|
Loading…
Reference in New Issue
Block a user