fix: protect ReplicationStats against concurrent map iteration and write crash (#17403)

This commit is contained in:
Klaus Post 2023-06-12 09:17:11 -07:00 committed by GitHub
parent bb24346e04
commit 6f2406b0b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 37 additions and 7 deletions

View File

@ -373,7 +373,7 @@ func (f *folderScanner) sendUpdate() {
} }
if flat := f.updateCache.sizeRecursive(f.newCache.Info.Name); flat != nil { if flat := f.updateCache.sizeRecursive(f.newCache.Info.Name); flat != nil {
select { select {
case f.updates <- *flat: case f.updates <- flat.clone():
default: default:
} }
f.lastUpdate = time.Now() f.lastUpdate = time.Now()

View File

@ -88,6 +88,20 @@ func (ats *allTierStats) merge(other *allTierStats) {
} }
} }
func (ats *allTierStats) clone() *allTierStats {
if ats == nil {
return nil
}
dst := *ats
if dst.Tiers != nil {
dst.Tiers = make(map[string]tierStats, len(dst.Tiers))
for tier, st := range dst.Tiers {
dst.Tiers[tier] = st
}
}
return &dst
}
func (ats *allTierStats) adminStats(stats map[string]madmin.TierStats) map[string]madmin.TierStats { func (ats *allTierStats) adminStats(stats map[string]madmin.TierStats) map[string]madmin.TierStats {
if ats == nil { if ats == nil {
return stats return stats
@ -168,6 +182,25 @@ type replicationAllStatsV1 struct {
ReplicaSize uint64 `msg:"ReplicaSize,omitempty"` ReplicaSize uint64 `msg:"ReplicaSize,omitempty"`
} }
// clone creates a deep-copy clone.
func (r *replicationAllStats) clone() *replicationAllStats {
if r == nil {
return nil
}
// Shallow copy
dst := *r
// Copy individual targets.
if dst.Targets != nil {
dst.Targets = make(map[string]replicationStats, len(dst.Targets))
for k, v := range r.Targets {
dst.Targets[k] = v
}
}
return &dst
}
//msgp:encode ignore dataUsageEntryV2 dataUsageEntryV3 dataUsageEntryV4 dataUsageEntryV5 dataUsageEntryV6 //msgp:encode ignore dataUsageEntryV2 dataUsageEntryV3 dataUsageEntryV4 dataUsageEntryV5 dataUsageEntryV6
//msgp:marshal ignore dataUsageEntryV2 dataUsageEntryV3 dataUsageEntryV4 dataUsageEntryV5 dataUsageEntryV6 //msgp:marshal ignore dataUsageEntryV2 dataUsageEntryV3 dataUsageEntryV4 dataUsageEntryV5 dataUsageEntryV6
@ -413,14 +446,11 @@ func (e dataUsageEntry) clone() dataUsageEntry {
e.Children = ch e.Children = ch
} }
if e.ReplicationStats != nil { if e.ReplicationStats != nil {
// Copy to new struct // Clone ReplicationStats
r := *e.ReplicationStats e.ReplicationStats = e.ReplicationStats.clone()
e.ReplicationStats = &r
} }
if e.AllTierStats != nil { if e.AllTierStats != nil {
ats := newAllTierStats() e.AllTierStats = e.AllTierStats.clone()
ats.merge(e.AllTierStats)
e.AllTierStats = ats
} }
return e return e
} }