Fix concurrent map read/write (#13052)

Clones were not independent.

Fixes race:

```
WARNING: DATA RACE
Read at 0x00c002040cc0 by goroutine 50:
  runtime.mapiterinit()
      c:/go/src/runtime/map.go:802 +0x0
  github.com/minio/minio/cmd.(*dataUsageCache).flatten()
      d:/minio/minio/cmd/data-usage-cache.go:551 +0xad
  github.com/minio/minio/cmd.(*dataUsageCache).dui()
      d:/minio/minio/cmd/data-usage-cache.go:352 +0x144
  github.com/minio/minio/cmd.(*erasureServerPools).NSScanner.func3.1()
      d:/minio/minio/cmd/erasure-server-pool.go:542 +0x2a4
  github.com/minio/minio/cmd.(*erasureServerPools).NSScanner.func3()
      d:/minio/minio/cmd/erasure-server-pool.go:561 +0x24b

Previous write at 0x00c002040cc0 by goroutine 1391:
  runtime.mapassign_faststr()
      c:/go/src/runtime/map_faststr.go:202 +0x0
  github.com/minio/minio/cmd.(*dataUsageEntry).addChild()
      d:/minio/minio/cmd/data-usage-cache.go:231 +0x313
  github.com/minio/minio/cmd.(*dataUsageCache).replace()
      d:/minio/minio/cmd/data-usage-cache.go:383 +0x293
  github.com/minio/minio/cmd.erasureObjects.nsScanner.func1()
      d:/minio/minio/cmd/erasure.go:428 +0x3a6
```
This commit is contained in:
Klaus Post 2021-08-24 16:11:38 +02:00 committed by GitHub
parent e0abb46616
commit c8ca055935
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -238,6 +238,24 @@ func (e *dataUsageEntry) removeChild(hash dataUsageHash) {
} }
} }
// Create a clone of the entry.
func (e dataUsageEntry) clone() dataUsageEntry {
// We operate on a copy from the receiver.
if e.Children != nil {
ch := make(dataUsageHashMap, len(e.Children))
for k, v := range e.Children {
ch[k] = v
}
e.Children = ch
}
if e.ReplicationStats != nil {
// Copy to new struct
r := *e.ReplicationStats
e.ReplicationStats = &r
}
return e
}
// find a path in the cache. // find a path in the cache.
// Returns nil if not found. // Returns nil if not found.
func (d *dataUsageCache) find(path string) *dataUsageEntry { func (d *dataUsageCache) find(path string) *dataUsageEntry {
@ -672,7 +690,7 @@ func (d *dataUsageCache) clone() dataUsageCache {
Cache: make(map[string]dataUsageEntry, len(d.Cache)), Cache: make(map[string]dataUsageEntry, len(d.Cache)),
} }
for k, v := range d.Cache { for k, v := range d.Cache {
clone.Cache[k] = v clone.Cache[k] = v.clone()
} }
return clone return clone
} }