Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 15 additions & 7 deletions src/commands/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1031,16 +1031,24 @@ pub async fn create_snapshot_core(
.await
.context("writing snapshot config")?;

// Atomic rename from temp to final location
// If final exists (e.g., from previous snapshot with same name), remove it first
// Atomic replace: rename old out of the way, then rename new into place.
// Same technique as the diff snapshot path above — avoids a window where
// no snapshot exists if we crash between remove and rename.
if snapshot_dir.exists() {
tokio::fs::remove_dir_all(snapshot_dir)
let old_snapshot_dir = snapshot_dir.with_extension("old");
let _ = tokio::fs::remove_dir_all(&old_snapshot_dir).await;
tokio::fs::rename(snapshot_dir, &old_snapshot_dir)
.await
.context("moving old snapshot out of the way")?;
tokio::fs::rename(&temp_snapshot_dir, snapshot_dir)
.await
.context("renaming temp snapshot to final location")?;
let _ = tokio::fs::remove_dir_all(&old_snapshot_dir).await;
} else {
tokio::fs::rename(&temp_snapshot_dir, snapshot_dir)
.await
.context("removing existing snapshot directory")?;
.context("renaming temp snapshot to final location")?;
}
tokio::fs::rename(&temp_snapshot_dir, snapshot_dir)
.await
.context("renaming temp snapshot to final location")?;

info!(
snapshot = %snapshot_config.name,
Expand Down
5 changes: 4 additions & 1 deletion src/network/bridged.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,11 @@ async fn is_ip_in_use_on_veth(ip: &str) -> bool {
};

let stdout = String::from_utf8_lossy(&output.stdout);
// Match "inet <ip>/" exactly to avoid substring false positives
// (e.g., checking 10.1.1.1 should not match 10.1.1.10 or 210.1.1.1)
let inet_pattern = format!("inet {}/", ip);
for line in stdout.lines() {
if line.contains(ip) && line.contains("veth0-") {
if line.contains(&inet_pattern) && line.contains("veth0-") {
return true;
}
}
Expand Down
9 changes: 4 additions & 5 deletions src/network/portmap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -383,11 +383,10 @@ pub async fn cleanup_global_nat_if_unused() {
}
}

// Disable IP forwarding
let _ = Command::new("sysctl")
.args(["-w", "net.ipv4.ip_forward=0"])
.output()
.await;
// Note: we intentionally do NOT disable ip_forward here.
// Other services on the host (Docker, Kubernetes, VPNs, etc.) may depend on
// IP forwarding being enabled. Since we can't know whether fcvm was the one
// that enabled it, the safe default is to leave it on.

debug!("global NAT cleanup complete");
}
Expand Down
Loading