diff --git a/lib/tinykvm/common.hpp b/lib/tinykvm/common.hpp index 5cf237e..771951b 100644 --- a/lib/tinykvm/common.hpp +++ b/lib/tinykvm/common.hpp @@ -97,9 +97,20 @@ namespace tinykvm /* Enable file-backed memory mappings for large files */ bool mmap_backed_files = false; /* Enable VM snapshot by file-mapping all physical memory - to the given file. The file is created if it does not exist, + to the given file. Depending on `snapshot_mode`, + the file may be created if it does not exist, and must be of the correct size if it does exist. */ std::string snapshot_file; + enum SnapshotMode { + Disabled = 0, + Open = 1, + Create = 2, + OpenOrCreate = 3, + }; + /* When using a snapshot_file, control whether file + should be created if missing, opened, or created + and possibly overwritten. */ + SnapshotMode snapshot_mode = OpenOrCreate; /* When using hugepages, cover the given size with hugepages, unless 0, in which case the entire main memory will be covered. */ diff --git a/lib/tinykvm/memory.cpp b/lib/tinykvm/memory.cpp index a18c1a3..346c0f4 100644 --- a/lib/tinykvm/memory.cpp +++ b/lib/tinykvm/memory.cpp @@ -397,12 +397,18 @@ vMemory::AllocationResult if (filename.empty()) { throw std::runtime_error("No VM snapshot file specified"); } - int fd = open(filename.c_str(), O_RDONLY | O_CLOEXEC); - if (fd < 0) { - if (errno != ENOENT) { + if (options.snapshot_mode == MachineOptions::SnapshotMode::Disabled) { + throw std::runtime_error("VM snapshot disabled"); + } + int fd = -1; + if (options.snapshot_mode != MachineOptions::SnapshotMode::Create) { + fd = open(filename.c_str(), O_RDONLY | O_CLOEXEC); + if (fd < 0 && (options.snapshot_mode == MachineOptions::SnapshotMode::Open || errno != ENOENT)) { throw std::runtime_error("Failed to open VM snapshot file: " + filename); } - fd = open(filename.c_str(), O_RDWR | O_CREAT | O_CLOEXEC, 0600); + } + if (fd < 0) { + fd = open(filename.c_str(), O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, 0600); if (fd < 0) { throw std::runtime_error("Failed to create VM snapshot file: " + filename); }