Skip to content

Commit cb3cc8a

Browse files
roypatCompuIves
andcommitted
Allow immediate merging of diff snapshots during creation
Allows the automatic merging of diff snapshots with a base snapshot by directly writing the diff snapshot on top of a base snapshot file of matching size. Signed-off-by: Patrick Roy <[email protected]> Co-authored-by: Ives van Hoorne <[email protected]>
1 parent bca0979 commit cb3cc8a

File tree

3 files changed

+36
-3
lines changed

3 files changed

+36
-3
lines changed

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@
4949
Removed support for creating Firecracker snapshots targeting older versions
5050
of Firecracker. With this change, running 'firecracker --version' will not
5151
print the supported snapshot versions.
52+
- [#3002](https://github.com/firecracker-microvm/firecracker/pull/3002) and
53+
[#4301](https://github.com/firecracker-microvm/firecracker/pull/4301):
54+
Allow merging of diff snapshots into base snapshots by directly writing
55+
the diff snapshot on top of the base snapshot's memory file.
5256

5357
### Deprecated
5458

@@ -77,6 +81,13 @@
7781
Fixed a bug in the asynchronous virtio-block engine that rendered the device
7882
non-functional after a PATCH request was issued to Firecracker for updating
7983
the path to the host-side backing file of the device.
84+
- [#4301](https://github.com/firecracker-microvm/firecracker/pull/4301):
85+
Fixed a bug where if Firecracker was instructed to take a snapshot of a
86+
microvm which itself was restored from a snapshot, specifying `mem_file_path`
87+
to be the path of the memory file from which the microvm was restored would
88+
result in both the microvm and the snapshot being corrupted. It now instead
89+
performs a "write-back" of all memory that was updated since the snapshot
90+
was originally loaded.
8091

8192
## [1.5.0]
8293

resources/seccomp/x86_64-unknown-linux-musl.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
"default_action": "trap",
44
"filter_action": "allow",
55
"filter": [
6+
{
7+
"syscall": "stat"
8+
},
69
{
710
"syscall": "epoll_ctl"
811
},

src/vmm/src/persist.rs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,9 @@ pub enum CreateSnapshotError {
174174
SerializeMicrovmState(snapshot::Error),
175175
/// Cannot perform {0} on the snapshot backing file: {1}
176176
SnapshotBackingFile(&'static str, io::Error),
177+
#[rustfmt::skip]
178+
#[doc = "Size mismatch when writing diff snapshot on top of base layer: base layer size is {0} but diff layer is size {1}."]
179+
SnapshotBackingFileLengthMismatch(u64, u64),
177180
#[cfg(target_arch = "x86_64")]
178181
#[rustfmt::skip]
179182
#[doc = "Too many devices attached: {0}. The maximum number allowed for the snapshot data version requested is {FC_V0_23_MAX_DEVICES:}."]
@@ -237,17 +240,33 @@ fn snapshot_memory_to_file(
237240
snapshot_type: SnapshotType,
238241
) -> Result<(), CreateSnapshotError> {
239242
use self::CreateSnapshotError::*;
243+
244+
// Need to check this here, as we create the file in the line below
245+
let file_exists = mem_file_path.exists();
240246
let mut file = OpenOptions::new()
241247
.write(true)
242248
.create(true)
243-
.truncate(true)
244249
.open(mem_file_path)
245250
.map_err(|err| MemoryBackingFile("open", err))?;
246251

247252
// Set the length of the file to the full size of the memory area.
248253
let mem_size_mib = mem_size_mib(vmm.guest_memory());
249-
file.set_len(mem_size_mib * 1024 * 1024)
250-
.map_err(|err| MemoryBackingFile("set_length", err))?;
254+
let expected_size = mem_size_mib * 1024 * 1024;
255+
256+
if file_exists {
257+
let file_size = file
258+
.metadata()
259+
.map_err(|e| MemoryBackingFile("get_metadata", e))?
260+
.len();
261+
262+
if file_size != expected_size {
263+
return Err(SnapshotBackingFileLengthMismatch(file_size, expected_size));
264+
}
265+
} else {
266+
// Set the length of the file to the full size of the memory area.
267+
file.set_len(expected_size)
268+
.map_err(|e| MemoryBackingFile("set_length", e))?;
269+
}
251270

252271
match snapshot_type {
253272
SnapshotType::Diff => {

0 commit comments

Comments
 (0)