forked from wrenn/wrenn
fix: drop page cache before snapshot to reduce memory dump size
Linux keeps freed memory as page cache, which Firecracker snapshots as non-zero blocks. A 16GB VM with 12GB stale cache would write all 12GB to disk. Dropping pagecache (not dentries/inodes) in /snapshot/prepare before blocking the reclaimer shrinks snapshots to actual working set size with minimal resume latency impact.
This commit is contained in:
@ -10,12 +10,22 @@ use crate::state::AppState;
|
|||||||
/// POST /snapshot/prepare — quiesce subsystems before Firecracker snapshot.
|
/// POST /snapshot/prepare — quiesce subsystems before Firecracker snapshot.
|
||||||
///
|
///
|
||||||
/// In Rust there is no GC dance. We just:
|
/// In Rust there is no GC dance. We just:
|
||||||
/// 1. Stop port subsystem
|
/// 1. Drop page cache to shrink snapshot size
|
||||||
/// 2. Close idle connections via conntracker
|
/// 2. Stop port subsystem
|
||||||
/// 3. Set needs_restore flag
|
/// 3. Close idle connections via conntracker
|
||||||
|
/// 4. Set needs_restore flag
|
||||||
pub async fn post_snapshot_prepare(State(state): State<Arc<AppState>>) -> impl IntoResponse {
|
pub async fn post_snapshot_prepare(State(state): State<Arc<AppState>>) -> impl IntoResponse {
|
||||||
// Block memory reclaimer before anything else — prevents drop_caches
|
// Drop page cache BEFORE blocking the reclaimer — avoids snapshotting
|
||||||
// from running mid-freeze which would corrupt kernel page table state.
|
// gigabytes of stale cache that inflates the memory dump on disk.
|
||||||
|
// "1" = pagecache only (keep dentries/inodes for faster resume).
|
||||||
|
if let Err(e) = std::fs::write("/proc/sys/vm/drop_caches", "1") {
|
||||||
|
tracing::warn!(error = %e, "snapshot/prepare: drop_caches failed");
|
||||||
|
} else {
|
||||||
|
tracing::info!("snapshot/prepare: page cache dropped");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Block memory reclaimer — prevents drop_caches from running mid-freeze
|
||||||
|
// which would corrupt kernel page table state.
|
||||||
state.snapshot_in_progress.store(true, Ordering::Release);
|
state.snapshot_in_progress.store(true, Ordering::Release);
|
||||||
|
|
||||||
if let Some(ref ps) = state.port_subsystem {
|
if let Some(ref ps) = state.port_subsystem {
|
||||||
|
|||||||
Reference in New Issue
Block a user