From c5e7cc94fec39fa7de764737aae6ab63ca478cd4 Mon Sep 17 00:00:00 2001 From: Chris Lu Date: Tue, 17 Mar 2026 14:37:32 -0700 Subject: [PATCH] Match Go ReceiveFile: prefer HardDrive location for EC and use response-level write errors Two fixes: (1) Go prefers HardDriveType disk location for EC volumes, falling back to first location. Returns "no storage location available" when no locations exist. (2) Write failures are now response-level errors (in response body) instead of gRPC status errors, matching Go. --- seaweed-volume/src/server/grpc_server.rs | 27 ++++++++++++++++++------ 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/seaweed-volume/src/server/grpc_server.rs b/seaweed-volume/src/server/grpc_server.rs index edfc75d07..f55f10e37 100644 --- a/seaweed-volume/src/server/grpc_server.rs +++ b/seaweed-volume/src/server/grpc_server.rs @@ -1332,12 +1332,21 @@ impl VolumeServer for VolumeGrpcService { // Determine file path let path = if info.is_ec_volume { let store = self.state.store.read().unwrap(); + // Go prefers a HardDriveType location, then falls back to first let dir = store .locations - .first() - .map(|loc| loc.directory.clone()) - .unwrap_or_default(); + .iter() + .find(|loc| loc.disk_type == DiskType::HardDrive) + .or_else(|| store.locations.first()) + .map(|loc| loc.directory.clone()); drop(store); + let dir = match dir { + Some(d) => d, + None => { + resp_error = Some("no storage location available".to_string()); + break; + } + }; let ec_base = if info.collection.is_empty() { format!("{}", info.volume_id) } else { @@ -1367,10 +1376,14 @@ impl VolumeServer for VolumeGrpcService { Some(volume_server_pb::receive_file_request::Data::FileContent(content)) => { if let Some(ref mut f) = target_file { use std::io::Write; - let n = f.write(&content).map_err(|e| { - Status::internal(format!("failed to write file: {}", e)) - })?; - bytes_written += n as u64; + match f.write(&content) { + Ok(n) => bytes_written += n as u64, + Err(e) => { + // Match Go: write failures are response-level errors, not gRPC errors + resp_error = Some(format!("failed to write file: {}", e)); + break; + } + } } else { // Go returns protocol violations as response-level errors resp_error = Some("file info must be sent first".to_string());