From 5150c869341122ee09c5acce4d01b1640f7f23be Mon Sep 17 00:00:00 2001 From: Lisandro Pin Date: Wed, 10 Jun 2026 19:55:16 +0200 Subject: [PATCH] Make shell command `ec.scrub` return shard details upon scrub failures in `LOCAL` mode. (#9913) This is useful information to deal with issues requiring EC shard rebuilding, such as https://github.com/seaweedfs/seaweedfs/issues/9872. --- weed/storage/erasure_coding/ec_volume_scrub.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/weed/storage/erasure_coding/ec_volume_scrub.go b/weed/storage/erasure_coding/ec_volume_scrub.go index aa759058b..208aeb78f 100644 --- a/weed/storage/erasure_coding/ec_volume_scrub.go +++ b/weed/storage/erasure_coding/ec_volume_scrub.go @@ -234,17 +234,21 @@ func (ecv *EcVolume) ScrubLocal() (int64, []*volume_server_pb.EcShardInfo, []err var data []byte locations := ecv.LocateEcShardNeedleInterval(ecv.Version, offset.ToActualOffset(), size) + localShardIds := []ShardId{} for i, iv := range locations { sid, soffset := iv.ToShardIdAndOffset(ErasureCodingLargeBlockSize, ErasureCodingSmallBlockSize) ssize := int64(iv.Size.Raw()) shard, found := ecv.FindEcVolumeShard(sid) + if !found { // shard is not local :( skip it hasRemoteChunks = true read += ssize continue } + localShardIds = append(localShardIds, sid) + if soffset+int64(ssize) > shard.Size() { flagShardBroken(shard, "local shard %d for needle %d is too short (%d), cannot read chunk %d/%d", sid, id, shard.Size(), i+1, len(locations)) continue @@ -267,14 +271,16 @@ func (ecv *EcVolume) ScrubLocal() (int64, []*volume_server_pb.EcShardInfo, []err read += int64(got) } + slices.Sort(localShardIds) + if got, want := read, needle.GetActualSize(size, ecv.Version); got != want { - return fmt.Errorf("expected %d bytes for needle %d, got %d", want, id, got) + return fmt.Errorf("expected %d bytes for needle %d on volume %d, got %d", want, id, ecv.VolumeId, got) } if !hasRemoteChunks { // needle was fully recovered from local shards \o/ let's check it n := needle.Needle{} if err := n.ReadBytes(data, 0, size, ecv.Version); err != nil { - errs = append(errs, fmt.Errorf("needle %d on volume %d: %v", id, ecv.VolumeId, err)) + errs = append(errs, fmt.Errorf("needle %d on volume %d, shards %v: %v", id, ecv.VolumeId, localShardIds, err)) } }