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