summaryrefslogtreecommitdiff
path: root/migration
diff options
context:
space:
mode:
authorPavel Butsykin <pbutsykin@virtuozzo.com>2017-02-03 18:23:21 +0300
committerDr. David Alan Gilbert <dgilbert@redhat.com>2017-02-13 17:27:13 +0000
commitced1c6166ef901a91578d54ff39f46b3e7ae870f (patch)
tree42d4a017224beac9dfb2114b0cba52a2bf9d2960 /migration
parent53f09a1076f5efbba7d751a8005e2fcf008606db (diff)
downloadqemu-ced1c6166ef901a91578d54ff39f46b3e7ae870f.tar.gz
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 <pbutsykin@virtuozzo.com> Message-Id: <20170203152321.19739-4-pbutsykin@virtuozzo.com> Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Diffstat (limited to 'migration')
-rw-r--r--migration/migration.c4
-rw-r--r--migration/ram.c19
2 files changed, 23 insertions, 0 deletions
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