From 3b3e8af430b2923d0e269d407a8c5205f94292f7 Mon Sep 17 00:00:00 2001 From: Chris Lu Date: Mon, 27 Jul 2026 18:40:57 -0700 Subject: [PATCH] volume: skip a shard-holding disk when staging a decoded volume (Go+Rust) (#10464) volume: skip a shard-holding disk when staging a decoded volume ReceiveFile staged-new-volume mode picked any free disk of the target medium. Skip a disk that already holds the vid's EC shards (Go DiskLocation.FindEcVolume / Rust ec_volumes), so a decoded .dat never lands in the same directory as a shard. This lets a caller safely stage onto a shard host that has a spare disk, instead of requiring a host with no shard of the vid at all. Claude-Session: https://claude.ai/code/session_01Ks16jnt4S7gdDk8cheQ3xu --- seaweed-volume/src/server/grpc_server.rs | 9 ++++++++- weed/server/volume_grpc_copy.go | 7 +++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/seaweed-volume/src/server/grpc_server.rs b/seaweed-volume/src/server/grpc_server.rs index 95a26652e..d6cf49f51 100644 --- a/seaweed-volume/src/server/grpc_server.rs +++ b/seaweed-volume/src/server/grpc_server.rs @@ -1768,7 +1768,14 @@ impl VolumeServer for VolumeGrpcService { // .idx.copying/.vif.copying are not valid volume names, // so the scanner never half-loads a partial push. let want = DiskType::from_string(&info.disk_type); - match store.find_free_location_predicate(|l| l.disk_type == want) { + let staged_vid = VolumeId(info.volume_id); + // Skip a disk already holding this vid's EC shards, so the + // decoded .dat never lands in the same directory as a shard — + // lets the caller target a shard host that has a spare disk. + match store.find_free_location_predicate(|l| { + l.disk_type == want + && !l.ec_volumes().any(|(v, _)| *v == staged_vid) + }) { Some(i) => { let dir = store.locations[i].directory.clone(); drop(store); diff --git a/weed/server/volume_grpc_copy.go b/weed/server/volume_grpc_copy.go index 0d7534839..e925e2031 100644 --- a/weed/server/volume_grpc_copy.go +++ b/weed/server/volume_grpc_copy.go @@ -700,7 +700,14 @@ func (vs *VolumeServer) ReceiveFile(stream volume_server_pb.VolumeServer_Receive // VolumeEcShardsToVolume(from_staged). .idx.copying/.vif.copying // are not valid volume names, so the scanner never half-loads. want := types.ToDiskType(fileInfo.DiskType) + stagedVid := needle.VolumeId(fileInfo.VolumeId) loc := vs.store.FindFreeLocation(func(l *storage.DiskLocation) bool { + // Skip a disk that already holds this vid's EC shards, so the + // decoded .dat never lands in the same directory as a shard — + // lets the caller target a shard host that has a spare disk. + if _, holds := l.FindEcVolume(stagedVid); holds { + return false + } return l.DiskType == want }) if loc == nil {