Skip to content

Commit ca503de

Browse files
committed
Load existing snapshots with private read-only mappings
1 parent 40cb5ba commit ca503de

File tree

3 files changed

+33
-20
lines changed

3 files changed

+33
-20
lines changed

lib/tinykvm/machine_state.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ bool Machine::load_snapshot_state()
9494
if (!memory.has_loadable_snapshot_state()) {
9595
return false;
9696
}
97-
if (!this->memory.has_snapshot_area) {
97+
if (!this->memory.has_snapshot_area()) {
9898
throw std::runtime_error("No snapshot state area allocated");
9999
}
100100
if (this->is_forked()) {
@@ -280,15 +280,15 @@ void Machine::save_snapshot_state_now() const
280280

281281
void* vMemory::get_snapshot_state_area() const
282282
{
283-
if (!this->has_snapshot_area) {
283+
if (!this->has_snapshot_area()) {
284284
throw std::runtime_error("No snapshot state area allocated");
285285
}
286286
// The snapshot state area is after the end of the memory
287287
return (void*)(this->ptr + this->size);
288288
}
289289
bool vMemory::has_loadable_snapshot_state() const noexcept
290290
{
291-
if (this->has_snapshot_area) {
291+
if (this->has_snapshot_area()) {
292292
void* area = this->get_snapshot_state_area();
293293
uint32_t* magic = reinterpret_cast<uint32_t*>(area);
294294
return *magic == SnapshotState::MAGIC;
@@ -297,7 +297,7 @@ bool vMemory::has_loadable_snapshot_state() const noexcept
297297
}
298298
void* Machine::get_snapshot_state_user_area() const
299299
{
300-
if (!this->memory.has_snapshot_area) {
300+
if (!this->memory.has_snapshot_area()) {
301301
return nullptr;
302302
}
303303
void* map = this->memory.get_snapshot_state_area();

lib/tinykvm/memory.cpp

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ namespace tinykvm {
2222
static constexpr bool VERBOSE_MMAP = false;
2323

2424
vMemory::vMemory(Machine& m, const MachineOptions& options,
25-
uint64_t ph, uint64_t sf, char* p, size_t s, bool own)
25+
uint64_t ph, uint64_t sf, char* p, size_t s, int fd, bool own)
2626
: machine(m), physbase(ph), safebase(sf),
2727
// Over-allocate in order to avoid trouble with 2MB-aligned operations
28-
ptr(p), size(overaligned_memsize(s)), owned(own),
29-
has_snapshot_area(own && !options.snapshot_file.empty()),
28+
ptr(p), size(overaligned_memsize(s)),
29+
owned(own), snapshot_fd(fd),
3030
main_memory_writes(options.master_direct_memory_writes),
3131
split_hugepages(options.split_hugepages),
3232
executable_heap(options.executable_heap),
@@ -55,7 +55,7 @@ vMemory::vMemory(Machine& m, const MachineOptions& options,
5555
}
5656
}
5757
vMemory::vMemory(Machine& m, const MachineOptions& options, const vMemory& other)
58-
: vMemory{m, options, other.physbase, other.safebase, other.ptr, other.size, false}
58+
: vMemory{m, options, other.physbase, other.safebase, other.ptr, other.size, -1, false}
5959
{
6060
this->executable_heap = other.executable_heap;
6161
this->mmap_physical_begin = other.mmap_physical_begin;
@@ -379,7 +379,7 @@ vMemory::AllocationResult vMemory::allocate_mapped_memory(
379379
if (advice != 0x0) {
380380
madvise(ptr, size, advice);
381381
}
382-
return AllocationResult{ptr, size};
382+
return AllocationResult{ptr, size, -1};
383383
}
384384
vMemory::AllocationResult
385385
vMemory::allocate_filebacked_memory(const MachineOptions& options, size_t size)
@@ -406,7 +406,10 @@ vMemory::AllocationResult
406406
close(fd);
407407
throw std::runtime_error("Failed to stat VM snapshot file: " + filename);
408408
}
409-
if (st.st_size != off_t(size)) {
409+
bool already_right_size = (st.st_size == off_t(size));
410+
char* ptr = (char*)MAP_FAILED;
411+
// If the file is not the correct size, resize it
412+
if (!already_right_size) {
410413
if (st.st_size != 0) {
411414
close(fd);
412415
throw std::runtime_error("VM snapshot file has incorrect size: " + filename);
@@ -416,14 +419,18 @@ vMemory::AllocationResult
416419
close(fd);
417420
throw std::runtime_error("Failed to set size of VM snapshot file: " + filename);
418421
}
422+
ptr = (char*) mmap(NULL, size, PROT_READ | PROT_WRITE,
423+
MAP_SHARED | MAP_NORESERVE, fd, 0);
424+
} else {
425+
// Map an existing file, which should not be modified on disk
426+
ptr = (char*) mmap(NULL, size, PROT_READ | PROT_WRITE,
427+
MAP_PRIVATE | MAP_NORESERVE, fd, 0);
419428
}
420-
char* ptr = (char*) mmap(NULL, size, PROT_READ | PROT_WRITE,
421-
MAP_SHARED | MAP_NORESERVE, fd, 0);
422429
close(fd);
423430
if (ptr == MAP_FAILED) {
424431
memory_exception("Failed to mmap VM snapshot file", 0, size);
425432
}
426-
return AllocationResult{ptr, size - ColdStartStateSize()};
433+
return AllocationResult{ptr, size - ColdStartStateSize(), fd};
427434
}
428435

429436
vMemory vMemory::New(Machine& m, const MachineOptions& options,
@@ -435,12 +442,12 @@ vMemory vMemory::New(Machine& m, const MachineOptions& options,
435442
size = vMemory::overaligned_memsize(size);
436443
// Use file-backed memory if requested
437444
if (!options.snapshot_file.empty()) {
438-
const auto [res_ptr, res_size] = allocate_filebacked_memory(options, size);
439-
return vMemory(m, options, phys, safe, res_ptr, res_size);
445+
const auto [res_ptr, res_size, fd] = allocate_filebacked_memory(options, size);
446+
return vMemory(m, options, phys, safe, res_ptr, res_size, fd);
440447
}
441448
// Normal 2MB main memory allocation
442-
const auto [res_ptr, res_size] = allocate_mapped_memory(options, size);
443-
return vMemory(m, options, phys, safe, res_ptr, res_size);
449+
const auto [res_ptr, res_size, fd] = allocate_mapped_memory(options, size);
450+
return vMemory(m, options, phys, safe, res_ptr, res_size, -1);
444451
}
445452

446453
VirtualMem vMemory::vmem() const

lib/tinykvm/memory.hpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ struct vMemory {
2828
char* ptr;
2929
size_t size;
3030
bool owned = true;
31-
bool has_snapshot_area = false;
31+
int snapshot_fd = -1;
3232
/* Remote end pointer for this memory */
3333
uint64_t remote_end = 0;
3434
bool remote_must_update_gigapages = true;
@@ -97,7 +97,7 @@ struct vMemory {
9797
uint64_t expectedUsermodeFlags() const noexcept;
9898

9999
/* Create new identity-mapped memory regions */
100-
vMemory(Machine&, const MachineOptions&, uint64_t, uint64_t, char*, size_t, bool = true);
100+
vMemory(Machine&, const MachineOptions&, uint64_t, uint64_t, char*, size_t, int fd, bool own = true);
101101
unsigned allocate_region_idx();
102102
void install_mmap_ranges(const Machine& other);
103103
void delete_foreign_mmap_ranges();
@@ -115,8 +115,14 @@ struct vMemory {
115115
}
116116
bool has_loadable_snapshot_state() const noexcept;
117117
void* get_snapshot_state_area() const;
118+
int get_snapshot_memory_fd() const noexcept {
119+
return snapshot_fd;
120+
}
121+
bool has_snapshot_area() const noexcept {
122+
return snapshot_fd != -1;
123+
}
118124
private:
119-
using AllocationResult = std::tuple<char*, size_t>;
125+
using AllocationResult = std::tuple<char*, size_t, int>;
120126
static AllocationResult allocate_mapped_memory(const MachineOptions&, size_t size);
121127
static AllocationResult allocate_filebacked_memory(const MachineOptions&, size_t size);
122128
std::vector<unsigned> m_bank_idx_free_list;

0 commit comments

Comments
 (0)