diff --git a/weed/shell/command_ec_common.go b/weed/shell/command_ec_common.go index 3616c4e16..f059b4e74 100644 --- a/weed/shell/command_ec_common.go +++ b/weed/shell/command_ec_common.go @@ -678,11 +678,16 @@ func countShardsByRack(vid needle.VolumeId, locations []*EcNode) map[string]int func (ecb *ecBalancer) doBalanceEcShardsAcrossRacks(collection string, vid needle.VolumeId, locations []*EcNode) error { racks := ecb.racks() - // calculate average number of shards an ec rack should have for one volume - averageShardsPerEcRack := ceilDivide(erasure_coding.TotalShardsCount, len(racks)) - // see the volume's shards are in how many racks, and how many in each rack rackToShardCount := countShardsByRack(vid, locations) + + // Calculate actual total shards for this volume (not hardcoded default) + var totalShardsForVolume int + for _, count := range rackToShardCount { + totalShardsForVolume += count + } + // calculate average number of shards an ec rack should have for one volume + averageShardsPerEcRack := ceilDivide(totalShardsForVolume, len(racks)) rackEcNodesWithVid := groupBy(locations, func(ecNode *EcNode) string { return string(ecNode.rack) }) diff --git a/weed/topology/topology_ec.go b/weed/topology/topology_ec.go index 7097cb84b..88fcf5c8d 100644 --- a/weed/topology/topology_ec.go +++ b/weed/topology/topology_ec.go @@ -91,6 +91,10 @@ func NewEcShardLocations(collection string) *EcShardLocations { } func (loc *EcShardLocations) AddShard(shardId erasure_coding.ShardId, dn *DataNode) (added bool) { + // Defensive bounds check to prevent panic with out-of-range shard IDs + if int(shardId) >= erasure_coding.MaxShardCount { + return false + } dataNodes := loc.Locations[shardId] for _, n := range dataNodes { if n.Id() == dn.Id() { @@ -102,6 +106,10 @@ func (loc *EcShardLocations) AddShard(shardId erasure_coding.ShardId, dn *DataNo } func (loc *EcShardLocations) DeleteShard(shardId erasure_coding.ShardId, dn *DataNode) (deleted bool) { + // Defensive bounds check to prevent panic with out-of-range shard IDs + if int(shardId) >= erasure_coding.MaxShardCount { + return false + } dataNodes := loc.Locations[shardId] foundIndex := -1 for index, n := range dataNodes {