From d07089ceaccb1e53355133e3e67599ca76b8223a Mon Sep 17 00:00:00 2001 From: Klaus Post Date: Wed, 1 Mar 2023 06:34:45 +0100 Subject: [PATCH] Fix scanner deadlock on lost global lock (#16726) --- cmd/erasure-server-pool.go | 2 ++ cmd/erasure.go | 14 +++++++++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/cmd/erasure-server-pool.go b/cmd/erasure-server-pool.go index 346ce8840..952732337 100644 --- a/cmd/erasure-server-pool.go +++ b/cmd/erasure-server-pool.go @@ -689,9 +689,11 @@ func (z *erasureServerPools) NSScanner(ctx context.Context, updates chan<- DataU case updateCloser <- ch: <-ch case <-ctx.Done(): + mu.Lock() if firstErr == nil { firstErr = ctx.Err() } + defer mu.Unlock() } return firstErr } diff --git a/cmd/erasure.go b/cmd/erasure.go index 7cf97a785..bd4926e6a 100644 --- a/cmd/erasure.go +++ b/cmd/erasure.go @@ -412,9 +412,6 @@ func (er erasureObjects) nsScanner(ctx context.Context, buckets []BucketInfo, wa for { select { - case <-ctx.Done(): - // Return without saving. - return case <-t.C: if cache.Info.LastUpdate.Equal(lastSave) { continue @@ -488,10 +485,13 @@ func (er erasureObjects) nsScanner(ctx context.Context, buckets []BucketInfo, wa go func(name string) { defer wg.Done() for update := range updates { - bucketResults <- dataUsageEntryInfo{ + select { + case <-ctx.Done(): + case bucketResults <- dataUsageEntryInfo{ Name: name, Parent: dataUsageRoot, Entry: update, + }: } } }(cache.Info.Name) @@ -519,10 +519,14 @@ func (er erasureObjects) nsScanner(ctx context.Context, buckets []BucketInfo, wa root = cache.flatten(*r) } t := time.Now() - bucketResults <- dataUsageEntryInfo{ + select { + case <-ctx.Done(): + return + case bucketResults <- dataUsageEntryInfo{ Name: cache.Info.Name, Parent: dataUsageRoot, Entry: root, + }: } // We want to avoid synchronizing up all writes in case // the results are piled up.