summaryrefslogtreecommitdiff
path: root/migration
diff options
context:
space:
mode:
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