From ca2761e6e197d338290989ee1e3d7ef9015e7e20 Mon Sep 17 00:00:00 2001 From: Chris Lu Date: Tue, 17 Mar 2026 14:42:58 -0700 Subject: [PATCH] Match Go makeupDiff: validate .cpd compaction revision is old + 1 Go reads the new .cpd file's super block and verifies the compaction revision is exactly old + 1. Rust only validated the old revision. --- seaweed-volume/src/storage/volume.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/seaweed-volume/src/storage/volume.rs b/seaweed-volume/src/storage/volume.rs index 26bc69af9..71776e7db 100644 --- a/seaweed-volume/src/storage/volume.rs +++ b/seaweed-volume/src/storage/volume.rs @@ -910,6 +910,12 @@ impl Volume { } } + /// Returns true when the volume has a data backend (local .dat file or + /// remote tiered storage). Mirrors Go's `v.DataBackend != nil` check. + pub fn has_data_backend(&self) -> bool { + self.dat_file.is_some() || self.remote_dat_file.is_some() + } + fn current_dat_file_size(&self) -> io::Result { if let Some(ref f) = self.dat_file { Ok(f.metadata()?.len()) @@ -2764,6 +2770,24 @@ impl Volume { ))); } + // Read the new .cpd file's super block and verify its compaction revision is old + 1 + let cpd_path_check = self.file_name(".cpd"); + let mut cpd_file_check = File::open(&cpd_path_check)?; + let mut sb_buf = [0u8; SUPER_BLOCK_SIZE]; + cpd_file_check.read_exact(&mut sb_buf)?; + let new_super_block = SuperBlock::from_bytes(&sb_buf)?; + let old_compact_revision = old_super_block.compaction_revision; + let new_compact_revision = new_super_block.compaction_revision; + if old_compact_revision + 1 != new_compact_revision { + return Err(VolumeError::Io(io::Error::new( + io::ErrorKind::Other, + format!( + "old dat file's compact revision {} + 1 does not equal new dat file's compact revision {}", + old_compact_revision, new_compact_revision + ), + ))); + } + let old_idx_path = self.file_name(".idx"); let mut old_idx_file = File::open(&old_idx_path)?;