@@ -38,5 +38,6 @@ void colo_do_failover(MigrationState *s);
bool colo_shutdown(void);
void colo_add_buffer_filter(Notifier *notifier, void *data);
+void colo_checkpoint_notify(void *opaque);
#endif
@@ -181,6 +181,8 @@ struct MigrationState
RAMBlock *last_req_rb;
QemuSemaphore colo_sem;
+ int64_t checkpoint_time;
+ QEMUTimer *delay_timer;
};
void migrate_set_state(int *state, int old_state, int new_state);
@@ -474,7 +474,7 @@ void colo_add_buffer_filter(Notifier *notifier, void *data)
static void colo_process_checkpoint(MigrationState *s)
{
QEMUSizedBuffer *buffer = NULL;
- int64_t current_time, checkpoint_time = qemu_clock_get_ms(QEMU_CLOCK_HOST);
+ int64_t current_time = qemu_clock_get_ms(QEMU_CLOCK_HOST);
Error *local_err = NULL;
int ret;
@@ -528,29 +528,22 @@ static void colo_process_checkpoint(MigrationState *s)
if (ret < 0) {
goto out;
}
-
+ timer_mod(s->delay_timer,
+ current_time + s->parameters[MIGRATION_PARAMETER_X_CHECKPOINT_DELAY]);
while (s->state == MIGRATION_STATUS_COLO) {
if (failover_request_is_active()) {
error_report("failover request");
goto out;
}
- current_time = qemu_clock_get_ms(QEMU_CLOCK_HOST);
- if ((current_time - checkpoint_time <
- s->parameters[MIGRATION_PARAMETER_X_CHECKPOINT_DELAY]) &&
- !colo_shutdown_requested) {
- int64_t delay_ms;
-
- delay_ms = s->parameters[MIGRATION_PARAMETER_X_CHECKPOINT_DELAY] -
- (current_time - checkpoint_time);
- g_usleep(delay_ms * 1000);
+ if (!colo_shutdown_requested) {
+ qemu_sem_wait(&s->colo_sem);
}
/* start a colo checkpoint */
ret = colo_do_checkpoint_transaction(s, buffer);
if (ret < 0) {
goto out;
}
- checkpoint_time = qemu_clock_get_ms(QEMU_CLOCK_HOST);
}
out:
@@ -572,7 +565,7 @@ out:
qsb_free(buffer);
buffer = NULL;
-
+ timer_del(s->delay_timer);
/* Hope this not to be too long to wait here */
qemu_sem_wait(&s->colo_sem);
qemu_sem_destroy(&s->colo_sem);
@@ -586,12 +579,26 @@ out:
}
}
+void colo_checkpoint_notify(void *opaque)
+{
+ MigrationState *s = opaque;
+ int64_t next_notify_time;
+
+ qemu_sem_post(&s->colo_sem);
+ s->checkpoint_time = qemu_clock_get_ms(QEMU_CLOCK_HOST);
+ next_notify_time = s->checkpoint_time +
+ s->parameters[MIGRATION_PARAMETER_X_CHECKPOINT_DELAY];
+ timer_mod(s->delay_timer, next_notify_time);
+}
+
void migrate_start_colo_process(MigrationState *s)
{
qemu_mutex_unlock_iothread();
qemu_sem_init(&s->colo_sem, 0);
migrate_set_state(&s->state, MIGRATION_STATUS_ACTIVE,
MIGRATION_STATUS_COLO);
+ s->delay_timer = timer_new_ms(QEMU_CLOCK_HOST, colo_checkpoint_notify,
+ s);
colo_process_checkpoint(s);
qemu_mutex_lock_iothread();
}
@@ -825,6 +825,7 @@ void qmp_migrate_set_parameters(bool has_compress_level,
if (has_x_checkpoint_delay) {
s->parameters[MIGRATION_PARAMETER_X_CHECKPOINT_DELAY] =
x_checkpoint_delay;
+ colo_checkpoint_notify(s);
}
}