From ac3a19138ae43ce66393d5cf2cccbe504b042354 Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Mon, 25 Sep 2023 08:26:29 -0700 Subject: [PATCH] fix: set scanning details locally to avoid cached values (#18092) atomic variable results such as scanning must not use cached values, instead rely on real-time information. --- cmd/storage-rest-client.go | 11 ++++++++++- cmd/xl-storage.go | 6 +++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/cmd/storage-rest-client.go b/cmd/storage-rest-client.go index fa3244650..3b18f88be 100644 --- a/cmd/storage-rest-client.go +++ b/cmd/storage-rest-client.go @@ -30,6 +30,7 @@ import ( "strconv" "strings" "sync" + "sync/atomic" "time" "github.com/minio/madmin-go/v3" @@ -134,6 +135,8 @@ func toStorageErr(err error) error { // Abstracts a remote disk. type storageRESTClient struct { + scanning int32 + endpoint Endpoint restClient *rest.Client diskID string @@ -207,6 +210,9 @@ func (client *storageRESTClient) Healing() *healingTracker { } func (client *storageRESTClient) NSScanner(ctx context.Context, cache dataUsageCache, updates chan<- dataUsageEntry, scanMode madmin.HealScanMode) (dataUsageCache, error) { + atomic.AddInt32(&client.scanning, 1) + defer atomic.AddInt32(&client.scanning, -1) + defer close(updates) pr, pw := io.Pipe() go func() { @@ -281,6 +287,8 @@ func (client *storageRESTClient) DiskInfo(_ context.Context, metrics bool) (info // transport is already down. return info, errDiskNotFound } + // Do not cache results from atomic variables + scanning := atomic.LoadInt32(&client.scanning) == 1 client.diskInfoCache.Once.Do(func() { client.diskInfoCache.TTL = time.Second client.diskInfoCache.Update = func() (interface{}, error) { @@ -306,8 +314,9 @@ func (client *storageRESTClient) DiskInfo(_ context.Context, metrics bool) (info }) val, err := client.diskInfoCache.Get() if val != nil { - return val.(DiskInfo), err + info = val.(DiskInfo) } + info.Scanning = scanning return info, err } diff --git a/cmd/xl-storage.go b/cmd/xl-storage.go index b9314dc52..6199a7cca 100644 --- a/cmd/xl-storage.go +++ b/cmd/xl-storage.go @@ -462,6 +462,7 @@ func (s *xlStorage) readMetadata(ctx context.Context, itemPath string) ([]byte, func (s *xlStorage) NSScanner(ctx context.Context, cache dataUsageCache, updates chan<- dataUsageEntry, scanMode madmin.HealScanMode) (dataUsageCache, error) { atomic.AddInt32(&s.scanning, 1) defer atomic.AddInt32(&s.scanning, -1) + var err error stopFn := globalScannerMetrics.log(scannerMetricScanBucketDrive, s.drivePath, cache.Info.Name) defer func() { @@ -650,6 +651,9 @@ func (s *xlStorage) NSScanner(ctx context.Context, cache dataUsageCache, updates // DiskInfo provides current information about disk space usage, // total free inodes and underlying filesystem. func (s *xlStorage) DiskInfo(_ context.Context, _ bool) (info DiskInfo, err error) { + // Do not cache results from atomic variables + scanning := atomic.LoadInt32(&s.scanning) == 1 + s.diskInfoCache.Once.Do(func() { s.diskInfoCache.TTL = time.Second s.diskInfoCache.Update = func() (interface{}, error) { @@ -677,7 +681,6 @@ func (s *xlStorage) DiskInfo(_ context.Context, _ bool) (info DiskInfo, err erro // - if we found an unformatted disk (no 'format.json') // - if we found healing tracker 'healing.bin' dcinfo.Healing = errors.Is(err, errUnformattedDisk) || (s.Healing() != nil) - dcinfo.Scanning = atomic.LoadInt32(&s.scanning) == 1 dcinfo.ID = diskID return dcinfo, err } @@ -687,6 +690,7 @@ func (s *xlStorage) DiskInfo(_ context.Context, _ bool) (info DiskInfo, err erro if v != nil { info = v.(DiskInfo) } + info.Scanning = scanning return info, err }