From 24f39800576ac969d5cebe081b43ae3896935183 Mon Sep 17 00:00:00 2001 From: Muskaan Singla Date: Fri, 19 Jan 2024 13:21:30 +0000 Subject: [PATCH 1/2] fix: reset dirty log on full snapshot path When a diff snapshot it taken, it always contains all pages that were dirtied since either instance start, or since the last diff snapshot was taken, whichever is more recent. This is not what we document it to do: > the diff consists of the memory pages which have been dirtied since > the last snapshot creation or since the creation of the microVM, > whichever of these events was the most recent. Here "last snapshot creation" includes full snapshots, not just diff snapshots (and that makes sense, if I take a diff snapshot after a full snapshot, I expect the diff snapshot to be a diff compared to the full snapshot). Signed-off-by: Roman Kovtyukh Co-authored-by: Muskaan Singla --- src/vmm/src/persist.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/vmm/src/persist.rs b/src/vmm/src/persist.rs index ef2769d0e0e..599a73fbd22 100644 --- a/src/vmm/src/persist.rs +++ b/src/vmm/src/persist.rs @@ -249,7 +249,10 @@ fn snapshot_memory_to_file( .dump_dirty(&mut file, &dirty_bitmap) .map_err(Memory) } - SnapshotType::Full => vmm.guest_memory().dump(&mut file).map_err(Memory), + SnapshotType::Full => { + let _ = vmm.get_dirty_bitmap().map_err(DirtyBitmap)?; + vmm.guest_memory().dump(&mut file).map_err(Memory) + } }?; file.flush() .map_err(|err| MemoryBackingFile("flush", err))?; From f996dc6bcd97e5c0610ec7fce5fd96b8a6abd230 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Barb=C3=A1chano?= Date: Fri, 19 Jan 2024 10:25:48 +0100 Subject: [PATCH 2/2] test: full snapshot resets dirty pages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Test that taking full snapshot is as described in documentation: > the diff consists of the memory pages which have been dirtied since > the last snapshot creation or since the creation of the microVM, > whichever of these events was the most recent. Signed-off-by: Roman Kovtyukh Co-authored-by: Pablo Barbáchano --- .../test_dirty_pages_in_full_snapshot.py | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 tests/integration_tests/functional/test_dirty_pages_in_full_snapshot.py diff --git a/tests/integration_tests/functional/test_dirty_pages_in_full_snapshot.py b/tests/integration_tests/functional/test_dirty_pages_in_full_snapshot.py new file mode 100644 index 00000000000..b867f8c5aa2 --- /dev/null +++ b/tests/integration_tests/functional/test_dirty_pages_in_full_snapshot.py @@ -0,0 +1,30 @@ +# Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Test scenario for reseting dirty pages after making a full snapshot.""" + + +def test_dirty_pages_after_full_snapshot(uvm_plain): + """ + Test if dirty pages are erased after making a full snapshot of a VM + """ + + vm_mem_size = 128 + uvm = uvm_plain + uvm.spawn() + uvm.basic_config(mem_size_mib=vm_mem_size, track_dirty_pages=True) + uvm.add_net_iface() + uvm.start() + uvm.ssh.run("true") + + snap_full = uvm.snapshot_full(vmstate_path="vmstate_full", mem_path="mem_full") + snap_diff = uvm.snapshot_diff(vmstate_path="vmstate_diff", mem_path="mem_diff") + snap_diff2 = uvm.snapshot_diff(vmstate_path="vmstate_diff2", mem_path="mem_diff2") + + # file size is the same, but the `diff` snapshot is actually a sparse file + assert snap_full.mem.stat().st_size == snap_diff.mem.stat().st_size + + # diff -> diff there should be no differences + assert snap_diff2.mem.stat().st_blocks == 0 + + # full -> diff there should be no differences + assert snap_diff.mem.stat().st_blocks == 0