|
@@ -116,6 +116,27 @@ static void migration_downtime_start(MigrationState *s)
|
|
s->downtime_start = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
|
|
s->downtime_start = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/*
|
|
|
|
+ * This is unfortunate: incoming migration actually needs the outgoing
|
|
|
|
+ * migration state (MigrationState) to be there too, e.g. to query
|
|
|
|
+ * capabilities, parameters, using locks, setup errors, etc.
|
|
|
|
+ *
|
|
|
|
+ * NOTE: when calling this, making sure current_migration exists and not
|
|
|
|
+ * been freed yet! Otherwise trying to access the refcount is already
|
|
|
|
+ * an use-after-free itself..
|
|
|
|
+ *
|
|
|
|
+ * TODO: Move shared part of incoming / outgoing out into separate object.
|
|
|
|
+ * Then this is not needed.
|
|
|
|
+ */
|
|
|
|
+static void migrate_incoming_ref_outgoing_state(void)
|
|
|
|
+{
|
|
|
|
+ object_ref(migrate_get_current());
|
|
|
|
+}
|
|
|
|
+static void migrate_incoming_unref_outgoing_state(void)
|
|
|
|
+{
|
|
|
|
+ object_unref(migrate_get_current());
|
|
|
|
+}
|
|
|
|
+
|
|
static void migration_downtime_end(MigrationState *s)
|
|
static void migration_downtime_end(MigrationState *s)
|
|
{
|
|
{
|
|
int64_t now = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
|
|
int64_t now = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
|
|
@@ -863,7 +884,7 @@ process_incoming_migration_co(void *opaque)
|
|
* postcopy thread.
|
|
* postcopy thread.
|
|
*/
|
|
*/
|
|
trace_process_incoming_migration_co_postcopy_end_main();
|
|
trace_process_incoming_migration_co_postcopy_end_main();
|
|
- return;
|
|
|
|
|
|
+ goto out;
|
|
}
|
|
}
|
|
/* Else if something went wrong then just fall out of the normal exit */
|
|
/* Else if something went wrong then just fall out of the normal exit */
|
|
}
|
|
}
|
|
@@ -879,7 +900,8 @@ process_incoming_migration_co(void *opaque)
|
|
}
|
|
}
|
|
|
|
|
|
migration_bh_schedule(process_incoming_migration_bh, mis);
|
|
migration_bh_schedule(process_incoming_migration_bh, mis);
|
|
- return;
|
|
|
|
|
|
+ goto out;
|
|
|
|
+
|
|
fail:
|
|
fail:
|
|
migrate_set_state(&mis->state, MIGRATION_STATUS_ACTIVE,
|
|
migrate_set_state(&mis->state, MIGRATION_STATUS_ACTIVE,
|
|
MIGRATION_STATUS_FAILED);
|
|
MIGRATION_STATUS_FAILED);
|
|
@@ -896,6 +918,9 @@ fail:
|
|
|
|
|
|
exit(EXIT_FAILURE);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
+out:
|
|
|
|
+ /* Pairs with the refcount taken in qmp_migrate_incoming() */
|
|
|
|
+ migrate_incoming_unref_outgoing_state();
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -1901,6 +1926,17 @@ void qmp_migrate_incoming(const char *uri, bool has_channels,
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Making sure MigrationState is available until incoming migration
|
|
|
|
+ * completes.
|
|
|
|
+ *
|
|
|
|
+ * NOTE: QEMU _might_ leak this refcount in some failure paths, but
|
|
|
|
+ * that's OK. This is the minimum change we need to at least making
|
|
|
|
+ * sure success case is clean on the refcount. We can try harder to
|
|
|
|
+ * make it accurate for any kind of failures, but it might be an
|
|
|
|
+ * overkill and doesn't bring us much benefit.
|
|
|
|
+ */
|
|
|
|
+ migrate_incoming_ref_outgoing_state();
|
|
once = false;
|
|
once = false;
|
|
}
|
|
}
|
|
|
|
|