From 1979fc7fb19eadd32e3b3f3633c71b077122db03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=89=E6=AD=A3=E8=B6=85?= Date: Wed, 15 Apr 2026 08:36:55 +0800 Subject: [PATCH] fix: restore bitrot stream and checksum metadata (#2542) --- crates/ecstore/src/bitrot.rs | 2 +- crates/filemeta/src/filemeta.rs | 30 +++++++++++++++++++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/crates/ecstore/src/bitrot.rs b/crates/ecstore/src/bitrot.rs index 6969edf73..d3a599a3b 100644 --- a/crates/ecstore/src/bitrot.rs +++ b/crates/ecstore/src/bitrot.rs @@ -64,7 +64,7 @@ pub async fn create_bitrot_reader( Ok(Some(reader)) } else if let Some(disk) = disk { // Read from disk - if use_zero_copy { + if use_zero_copy && disk.is_local() { // Try zero-copy read first (uses mmap on Unix) let start = Instant::now(); match disk.read_file_zero_copy(bucket, path, offset, length).await { diff --git a/crates/filemeta/src/filemeta.rs b/crates/filemeta/src/filemeta.rs index c51cb2fea..aea74b605 100644 --- a/crates/filemeta/src/filemeta.rs +++ b/crates/filemeta/src/filemeta.rs @@ -24,7 +24,7 @@ use rustfs_utils::http::headers::{ AMZ_STORAGE_CLASS, }; use rustfs_utils::http::{ - AMZ_BUCKET_REPLICATION_STATUS, SUFFIX_DATA_MOV, SUFFIX_HEALING, SUFFIX_PURGESTATUS, SUFFIX_REPLICA_STATUS, + AMZ_BUCKET_REPLICATION_STATUS, SUFFIX_CRC, SUFFIX_DATA_MOV, SUFFIX_HEALING, SUFFIX_PURGESTATUS, SUFFIX_REPLICA_STATUS, SUFFIX_REPLICA_TIMESTAMP, SUFFIX_REPLICATION_STATUS, SUFFIX_REPLICATION_TIMESTAMP, has_internal_suffix, insert_bytes, is_internal_key, }; @@ -233,6 +233,10 @@ impl FileMeta { if let Some(mod_time) = fi.mod_time { obj.mod_time = Some(mod_time); } + + if let Some(content_hash) = fi.checksum.as_ref() { + insert_bytes(&mut obj.meta_sys, SUFFIX_CRC, content_hash.to_vec()); + } } // Update @@ -1721,6 +1725,30 @@ mod test { assert_eq!(after, Some(Bytes::from_static(b"inline").to_vec())); } + #[test] + fn test_update_object_version_persists_checksum_metadata() { + let mut fm = FileMeta::new(); + let version_id = Some(Uuid::new_v4()); + + let mut fi = crate::fileinfo::FileInfo::new("test", 2, 1); + fi.version_id = version_id; + fi.mod_time = Some(OffsetDateTime::now_utc()); + fm.add_version(fi).unwrap(); + + let checksum = Bytes::from_static(b"resolved-checksum"); + let mut update = crate::fileinfo::FileInfo::new("test", 2, 1); + update.version_id = version_id; + update.metadata.insert("x-amz-meta-owner".to_string(), "alice".to_string()); + update.checksum = Some(checksum.clone()); + + fm.update_object_version(update).unwrap(); + + let (_, version) = fm.find_version(version_id).unwrap(); + let stored = version.into_fileinfo("bucket", "test", true); + assert_eq!(stored.metadata.get("x-amz-meta-owner"), Some(&"alice".to_string())); + assert_eq!(stored.checksum, Some(checksum)); + } + #[test] fn test_version_merge_scenarios() { // Test various version merge scenarios