java-topology/defects/minio/patch/minio-0001-heal-tracker-isHealed-linear-scan.patch

53 lines
1.8 KiB
Diff
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# UNDF: UNDF-2026-000000768
# UNDF: (leave blank)
# minio-0001: healingTracker.isHealed() uses slices.Contains(HealedBuckets, bucket) → O(B×H)
#
# File: cmd/background-newdisks-heal-ops.go
# Function: healingTracker.isHealed()
# Called from: cmd/global-heal.go line 270, inside `for _, bucket := range healBuckets`
#
# The heal loop iterates all buckets (B) and for each calls isHealed() which
# does slices.Contains over HealedBuckets (H). As healing progresses, H grows
# toward B, making total cost O(B²). With 10K+ buckets this is significant.
#
# Irony: setQueuedBuckets() already builds a set.CreateStringSet(HealedBuckets...)
# for the same data, but isHealed() doesn't use it.
#
# Fix: maintain a map[string]struct{} alongside the slice for O(1) lookup.
# Severity: MEDIUM (O(B²) during disk healing, B = number of buckets)
# Overhead ratio: ~250x at B=500
#
--- a/cmd/background-newdisks-heal-ops.go
+++ b/cmd/background-newdisks-heal-ops.go
@@ -48,6 +48,7 @@
type healingTracker struct {
mu *sync.RWMutex `msg:"-"`
+ healedSet map[string]struct{} `msg:"-"` // O(1) lookup mirror of HealedBuckets
ID string
PoolIndex int
@@ -163,6 +164,7 @@
func (h *healingTracker) resetHealStatusCounters() {
h.HealedBuckets = nil
+ h.healedSet = make(map[string]struct{})
h.QueuedBuckets = nil
h.ItemsHealed = 0
h.ItemsFailed = 0
@@ -269,7 +271,8 @@
func (h *healingTracker) isHealed(bucket string) bool {
h.mu.RLock()
defer h.mu.RUnlock()
- return slices.Contains(h.HealedBuckets, bucket)
+ _, ok := h.healedSet[bucket]
+ return ok
}
@@ -298,6 +301,9 @@
h.ResumeBytesSkipped = h.BytesSkipped
h.HealedBuckets = append(h.HealedBuckets, bucket)
+ if h.healedSet == nil {
+ h.healedSet = make(map[string]struct{})
+ }
+ h.healedSet[bucket] = struct{}{}
for i, b := range h.QueuedBuckets {
if b == bucket {