1 /* 2 * COarse-grain LOck-stepping Virtual Machines for Non-stop Service (COLO) 3 * (a.k.a. Fault Tolerance or Continuous Replication) 4 * 5 * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD. 6 * Copyright (c) 2016 FUJITSU LIMITED 7 * Copyright (c) 2016 Intel Corporation 8 * 9 * This work is licensed under the terms of the GNU GPL, version 2 or 10 * later. See the COPYING file in the top-level directory. 11 */ 12 13 #include "qemu/osdep.h" 14 #include "migration/colo.h" 15 #include "migration/failover.h" 16 #include "qmp-commands.h" 17 #include "qapi/qmp/qerror.h" 18 #include "qemu/error-report.h" 19 #include "trace.h" 20 21 static QEMUBH *failover_bh; 22 static FailoverStatus failover_state; 23 24 static void colo_failover_bh(void *opaque) 25 { 26 int old_state; 27 28 qemu_bh_delete(failover_bh); 29 failover_bh = NULL; 30 31 old_state = failover_set_state(FAILOVER_STATUS_REQUIRE, 32 FAILOVER_STATUS_ACTIVE); 33 if (old_state != FAILOVER_STATUS_REQUIRE) { 34 error_report("Unknown error for failover, old_state = %s", 35 FailoverStatus_lookup[old_state]); 36 return; 37 } 38 39 colo_do_failover(NULL); 40 } 41 42 void failover_request_active(Error **errp) 43 { 44 if (failover_set_state(FAILOVER_STATUS_NONE, 45 FAILOVER_STATUS_REQUIRE) != FAILOVER_STATUS_NONE) { 46 error_setg(errp, "COLO failover is already actived"); 47 return; 48 } 49 failover_bh = qemu_bh_new(colo_failover_bh, NULL); 50 qemu_bh_schedule(failover_bh); 51 } 52 53 void failover_init_state(void) 54 { 55 failover_state = FAILOVER_STATUS_NONE; 56 } 57 58 FailoverStatus failover_set_state(FailoverStatus old_state, 59 FailoverStatus new_state) 60 { 61 FailoverStatus old; 62 63 old = atomic_cmpxchg(&failover_state, old_state, new_state); 64 if (old == old_state) { 65 trace_colo_failover_set_state(FailoverStatus_lookup[new_state]); 66 } 67 return old; 68 } 69 70 FailoverStatus failover_get_state(void) 71 { 72 return atomic_read(&failover_state); 73 } 74 75 void qmp_x_colo_lost_heartbeat(Error **errp) 76 { 77 if (get_colo_mode() == COLO_MODE_UNKNOWN) { 78 error_setg(errp, QERR_FEATURE_DISABLED, "colo"); 79 return; 80 } 81 82 failover_request_active(errp); 83 } 84