From 66620a1ab834d100037f8defc2cf23915e82f92a Mon Sep 17 00:00:00 2001 From: Chris Lu Date: Thu, 25 Jun 2026 10:55:52 -0700 Subject: [PATCH] fix(volume): serve reads from remote after tier upload (Rust) (#10112) After VolumeTierMoveDatToRemote uploaded the .dat, the volume closed its local backend but never opened the remote one, leaving both dat_file and remote_dat_file empty. The needle read path has no lazy reopen, so reads returned "dat file not open" until the volume reloaded. Switch to the remote backend right after saving the .vif, the same as the Go volume server's LoadRemoteFile, so the volume keeps serving from remote storage immediately after tiering. --- seaweed-volume/src/server/grpc_server.rs | 12 +++++++++--- seaweed-volume/src/storage/volume.rs | 8 +------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/seaweed-volume/src/server/grpc_server.rs b/seaweed-volume/src/server/grpc_server.rs index a46971bec..6b97ac4fe 100644 --- a/seaweed-volume/src/server/grpc_server.rs +++ b/seaweed-volume/src/server/grpc_server.rs @@ -3335,9 +3335,15 @@ impl VolumeServer for VolumeGrpcService { ))); } - // Close local dat file handle (matches Go's v.LoadRemoteFile - // which closes DataBackend before switching to remote) - vol.close_local_dat_backend(); + // Switch the data backend from the local .dat to the remote + // object so reads keep working after upload (matches Go's + // LoadRemoteFile). + if let Err(e) = vol.load_remote_dat_file() { + return Err(Status::internal(format!( + "volume {} failed to load remote file: {}", + vid, e + ))); + } // Optionally remove local .dat file from disk if !keep_local { diff --git a/seaweed-volume/src/storage/volume.rs b/seaweed-volume/src/storage/volume.rs index a83c652e5..9fa355f30 100644 --- a/seaweed-volume/src/storage/volume.rs +++ b/seaweed-volume/src/storage/volume.rs @@ -949,7 +949,7 @@ impl Volume { Ok(()) } - fn load_remote_dat_file(&mut self) -> Result<(), VolumeError> { + pub(crate) fn load_remote_dat_file(&mut self) -> Result<(), VolumeError> { let (storage_name, storage_key) = self.remote_storage_name_key(); let backend = crate::remote_storage::s3_tier::global_s3_tier_registry() .read() @@ -2225,12 +2225,6 @@ impl Volume { } } - /// Close the local .dat file handle (matches Go's v.DataBackend.Close() in LoadRemoteFile). - /// Called after tier-upload when the local file is being replaced by remote storage. - pub fn close_local_dat_backend(&mut self) { - self.dat_file = None; - } - /// Close the remote dat file backend (matches Go's v.DataBackend.Close(); v.DataBackend = nil). /// Called after tier-download when the remote backend is being replaced by local storage. pub fn close_remote_dat_backend(&mut self) {