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 {