diff --git a/include/migration/failover.h b/include/migration/failover.h index 327473506874c7b0169a9e02c4b29141384d4337..7e0f36a27423dedea1a9e574a1ca98d1274d5a6f 100644 --- a/include/migration/failover.h +++ b/include/migration/failover.h @@ -14,7 +14,12 @@ #define QEMU_FAILOVER_H #include "qemu-common.h" +#include "qapi-types.h" +void failover_init_state(void); +FailoverStatus failover_set_state(FailoverStatus old_state, + FailoverStatus new_state); +FailoverStatus failover_get_state(void); void failover_request_active(Error **errp); #endif diff --git a/migration/colo-failover.c b/migration/colo-failover.c index e31fc10c826880d1c0502931df44464948d7f86a..6cca039eb99b682a72322c4dde2b485ead623ac8 100644 --- a/migration/colo-failover.c +++ b/migration/colo-failover.c @@ -15,22 +15,63 @@ #include "migration/failover.h" #include "qmp-commands.h" #include "qapi/qmp/qerror.h" +#include "qemu/error-report.h" +#include "trace.h" static QEMUBH *failover_bh; +static FailoverStatus failover_state; static void colo_failover_bh(void *opaque) { + int old_state; + qemu_bh_delete(failover_bh); failover_bh = NULL; + + old_state = failover_set_state(FAILOVER_STATUS_REQUIRE, + FAILOVER_STATUS_ACTIVE); + if (old_state != FAILOVER_STATUS_REQUIRE) { + error_report("Unknown error for failover, old_state = %s", + FailoverStatus_lookup[old_state]); + return; + } + /* TODO: Do failover work */ } void failover_request_active(Error **errp) { + if (failover_set_state(FAILOVER_STATUS_NONE, + FAILOVER_STATUS_REQUIRE) != FAILOVER_STATUS_NONE) { + error_setg(errp, "COLO failover is already actived"); + return; + } failover_bh = qemu_bh_new(colo_failover_bh, NULL); qemu_bh_schedule(failover_bh); } +void failover_init_state(void) +{ + failover_state = FAILOVER_STATUS_NONE; +} + +FailoverStatus failover_set_state(FailoverStatus old_state, + FailoverStatus new_state) +{ + FailoverStatus old; + + old = atomic_cmpxchg(&failover_state, old_state, new_state); + if (old == old_state) { + trace_colo_failover_set_state(FailoverStatus_lookup[new_state]); + } + return old; +} + +FailoverStatus failover_get_state(void) +{ + return atomic_read(&failover_state); +} + void qmp_x_colo_lost_heartbeat(Error **errp) { if (get_colo_mode() == COLO_MODE_UNKNOWN) { diff --git a/migration/colo.c b/migration/colo.c index 12fa0b411157911d4e59498602cb40a569933642..6b32c9183c6000ed021b51a496c1843ece4dec61 100644 --- a/migration/colo.c +++ b/migration/colo.c @@ -232,6 +232,8 @@ static void colo_process_checkpoint(MigrationState *s) Error *local_err = NULL; int ret; + failover_init_state(); + s->rp_state.from_dst_file = qemu_file_get_return_path(s->to_dst_file); if (!s->rp_state.from_dst_file) { error_report("Open QEMUFile from_dst_file failed"); @@ -332,6 +334,8 @@ void *colo_process_incoming_thread(void *opaque) migrate_set_state(&mis->state, MIGRATION_STATUS_ACTIVE, MIGRATION_STATUS_COLO); + failover_init_state(); + mis->to_src_file = qemu_file_get_return_path(mis->from_src_file); if (!mis->to_src_file) { error_report("COLO incoming thread: Open QEMUFile to_src_file failed"); diff --git a/migration/trace-events b/migration/trace-events index f374c8cf274204bb8a5184bf48b07eb81bc4d248..94134f700bb2c602eb2d9c27a7627693ec2a67ac 100644 --- a/migration/trace-events +++ b/migration/trace-events @@ -212,3 +212,4 @@ migration_tls_incoming_handshake_complete(void) "" colo_vm_state_change(const char *old, const char *new) "Change '%s' => '%s'" colo_send_message(const char *msg) "Send '%s' message" colo_receive_message(const char *msg) "Receive '%s' message" +colo_failover_set_state(const char *new_state) "new state %s" diff --git a/qapi-schema.json b/qapi-schema.json index a18484115f6348538ed4f791ee1e31f65c461817..8a7b5270910277d907072fdce04e3de56971c66b 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -839,6 +839,24 @@ { 'enum': 'COLOMode', 'data': [ 'unknown', 'primary', 'secondary'] } +## +# @FailoverStatus +# +# An enumeration of COLO failover status +# +# @none: no failover has ever happened +# +# @require: got failover requirement but not handled +# +# @active: in the process of doing failover +# +# @completed: finish the process of failover +# +# Since: 2.8 +## +{ 'enum': 'FailoverStatus', + 'data': [ 'none', 'require', 'active', 'completed'] } + ## # @x-colo-lost-heartbeat #