From 53f09a1076f5efbba7d751a8005e2fcf008606db Mon Sep 17 00:00:00 2001 From: Pavel Butsykin Date: Fri, 3 Feb 2017 18:23:20 +0300 Subject: add 'release-ram' migrate capability This feature frees the migrated memory on the source during postcopy-ram migration. In the second step of postcopy-ram migration when the source vm is put on pause we can free unnecessary memory. It will allow, in particular, to start relaxing the memory stress on the source host in a load-balancing scenario. Signed-off-by: Pavel Butsykin Message-Id: <20170203152321.19739-3-pbutsykin@virtuozzo.com> Reviewed-by: Dr. David Alan Gilbert Signed-off-by: Dr. David Alan Gilbert Manually merged in Pavel's 'migration: madvise error_report fixup!' --- migration/migration.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'migration/migration.c') diff --git a/migration/migration.c b/migration/migration.c index 2b179c69fa..68afc07016 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -1297,6 +1297,15 @@ void qmp_migrate_set_downtime(double value, Error **errp) qmp_migrate_set_parameters(&p, errp); } +bool migrate_release_ram(void) +{ + MigrationState *s; + + s = migrate_get_current(); + + return s->enabled_capabilities[MIGRATION_CAPABILITY_RELEASE_RAM]; +} + bool migrate_postcopy_ram(void) { MigrationState *s; -- cgit 1.4.1 From ced1c6166ef901a91578d54ff39f46b3e7ae870f Mon Sep 17 00:00:00 2001 From: Pavel Butsykin Date: Fri, 3 Feb 2017 18:23:21 +0300 Subject: migration: discard non-dirty ram pages after the start of postcopy After the start of postcopy migration there are some non-dirty pages which have already been migrated. These pages are no longer needed on the source vm so that we can free them and it doen't hurt to complete the migration. Signed-off-by: Pavel Butsykin Message-Id: <20170203152321.19739-4-pbutsykin@virtuozzo.com> Signed-off-by: Dr. David Alan Gilbert --- include/migration/migration.h | 1 + migration/migration.c | 4 ++++ migration/ram.c | 19 +++++++++++++++++++ 3 files changed, 24 insertions(+) (limited to 'migration/migration.c') diff --git a/include/migration/migration.h b/include/migration/migration.h index b9b706a7e3..71ce19062c 100644 --- a/include/migration/migration.h +++ b/include/migration/migration.h @@ -285,6 +285,7 @@ int ram_postcopy_send_discard_bitmap(MigrationState *ms); int ram_discard_range(MigrationIncomingState *mis, const char *block_name, uint64_t start, size_t length); int ram_postcopy_incoming_init(MigrationIncomingState *mis); +void ram_postcopy_migrated_memory_release(MigrationState *ms); /** * @migrate_add_blocker - prevent migration from proceeding diff --git a/migration/migration.c b/migration/migration.c index 68afc07016..2a26a20aaf 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -1722,6 +1722,10 @@ static int postcopy_start(MigrationState *ms, bool *old_vm_running) */ qemu_savevm_send_ping(ms->to_dst_file, 4); + if (migrate_release_ram()) { + ram_postcopy_migrated_memory_release(ms); + } + ret = qemu_file_get_error(ms->to_dst_file); if (ret) { error_report("postcopy_start: Migration stream errored"); diff --git a/migration/ram.c b/migration/ram.c index c22209db30..67f2efbc59 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -1537,6 +1537,25 @@ void ram_debug_dump_bitmap(unsigned long *todump, bool expected) /* **** functions for postcopy ***** */ +void ram_postcopy_migrated_memory_release(MigrationState *ms) +{ + struct RAMBlock *block; + unsigned long *bitmap = atomic_rcu_read(&migration_bitmap_rcu)->bmap; + + QLIST_FOREACH_RCU(block, &ram_list.blocks, next) { + unsigned long first = block->offset >> TARGET_PAGE_BITS; + unsigned long range = first + (block->used_length >> TARGET_PAGE_BITS); + unsigned long run_start = find_next_zero_bit(bitmap, range, first); + + while (run_start < range) { + unsigned long run_end = find_next_bit(bitmap, range, run_start + 1); + ram_discard_range(NULL, block->idstr, run_start << TARGET_PAGE_BITS, + (run_end - run_start) << TARGET_PAGE_BITS); + run_start = find_next_zero_bit(bitmap, range, run_end + 1); + } + } +} + /* * Callback from postcopy_each_ram_send_discard for each RAMBlock * Note: At this point the 'unsentmap' is the processed bitmap combined -- cgit 1.4.1 From 479125d53eb8509d69a0548f131028a65fcbd65a Mon Sep 17 00:00:00 2001 From: zhanghailiang Date: Tue, 17 Jan 2017 20:57:42 +0800 Subject: COLO: fix setting checkpoint-delay not working properly If we set checkpoint-delay through command 'migrate-set-parameters', It will not take effect until we finish last sleep chekpoint-delay, That's will be offensive espeically when we want to change its value from an extreme big one to a proper value. Fix it by using timer to realize checkpoint-delay. Signed-off-by: zhanghailiang Message-Id: <1484657864-21708-2-git-send-email-zhang.zhanghailiang@huawei.com> Signed-off-by: Dr. David Alan Gilbert Reviewed-by: Dr. David Alan Gilbert --- include/migration/colo.h | 2 ++ include/migration/migration.h | 5 +++++ migration/colo.c | 33 +++++++++++++++++++++++---------- migration/migration.c | 3 +++ 4 files changed, 33 insertions(+), 10 deletions(-) (limited to 'migration/migration.c') diff --git a/include/migration/colo.h b/include/migration/colo.h index e32eef4763..2bbff9e6c2 100644 --- a/include/migration/colo.h +++ b/include/migration/colo.h @@ -35,4 +35,6 @@ COLOMode get_colo_mode(void); /* failover */ void colo_do_failover(MigrationState *s); + +void colo_checkpoint_notify(void *opaque); #endif diff --git a/include/migration/migration.h b/include/migration/migration.h index 71ce19062c..cb83f1688e 100644 --- a/include/migration/migration.h +++ b/include/migration/migration.h @@ -188,6 +188,11 @@ struct MigrationState /* The RAMBlock used in the last src_page_request */ RAMBlock *last_req_rb; + /* The semaphore is used to notify COLO thread to do checkpoint */ + QemuSemaphore colo_checkpoint_sem; + int64_t colo_checkpoint_time; + QEMUTimer *colo_delay_timer; + /* The last error that occurred */ Error *error; }; diff --git a/migration/colo.c b/migration/colo.c index 93c85c538b..08b2e46dac 100644 --- a/migration/colo.c +++ b/migration/colo.c @@ -302,7 +302,7 @@ static void colo_process_checkpoint(MigrationState *s) { QIOChannelBuffer *bioc; QEMUFile *fb = 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; @@ -332,26 +332,21 @@ static void colo_process_checkpoint(MigrationState *s) qemu_mutex_unlock_iothread(); trace_colo_vm_state_change("stop", "run"); + timer_mod(s->colo_delay_timer, + current_time + s->parameters.x_checkpoint_delay); + while (s->state == MIGRATION_STATUS_COLO) { if (failover_get_state() != FAILOVER_STATUS_NONE) { error_report("failover request"); goto out; } - current_time = qemu_clock_get_ms(QEMU_CLOCK_HOST); - if (current_time - checkpoint_time < - s->parameters.x_checkpoint_delay) { - int64_t delay_ms; + qemu_sem_wait(&s->colo_checkpoint_sem); - delay_ms = s->parameters.x_checkpoint_delay - - (current_time - checkpoint_time); - g_usleep(delay_ms * 1000); - } ret = colo_do_checkpoint_transaction(s, bioc, fb); if (ret < 0) { goto out; } - checkpoint_time = qemu_clock_get_ms(QEMU_CLOCK_HOST); } out: @@ -364,14 +359,32 @@ out: qemu_fclose(fb); } + timer_del(s->colo_delay_timer); + if (s->rp_state.from_dst_file) { qemu_fclose(s->rp_state.from_dst_file); } } +void colo_checkpoint_notify(void *opaque) +{ + MigrationState *s = opaque; + int64_t next_notify_time; + + qemu_sem_post(&s->colo_checkpoint_sem); + s->colo_checkpoint_time = qemu_clock_get_ms(QEMU_CLOCK_HOST); + next_notify_time = s->colo_checkpoint_time + + s->parameters.x_checkpoint_delay; + timer_mod(s->colo_delay_timer, next_notify_time); +} + void migrate_start_colo_process(MigrationState *s) { qemu_mutex_unlock_iothread(); + qemu_sem_init(&s->colo_checkpoint_sem, 0); + s->colo_delay_timer = timer_new_ms(QEMU_CLOCK_HOST, + colo_checkpoint_notify, s); + migrate_set_state(&s->state, MIGRATION_STATUS_ACTIVE, MIGRATION_STATUS_COLO); colo_process_checkpoint(s); diff --git a/migration/migration.c b/migration/migration.c index 2a26a20aaf..c6ae69d371 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -891,6 +891,9 @@ void qmp_migrate_set_parameters(MigrationParameters *params, Error **errp) if (params->has_x_checkpoint_delay) { s->parameters.x_checkpoint_delay = params->x_checkpoint_delay; + if (migration_in_colo_state()) { + colo_checkpoint_notify(s); + } } } -- cgit 1.4.1