diff --git a/cmd/background-newdisks-heal-ops.go b/cmd/background-newdisks-heal-ops.go index 0b2ad8a37..c3da04efa 100644 --- a/cmd/background-newdisks-heal-ops.go +++ b/cmd/background-newdisks-heal-ops.go @@ -485,7 +485,12 @@ func healFreshDisk(ctx context.Context, z *erasureServerPools, endpoint Endpoint } // Remove .healing.bin from all disks with similar heal-id - for _, disk := range z.serverPools[poolIdx].sets[setIdx].getDisks() { + disks, err := z.GetDisks(poolIdx, setIdx) + if err != nil { + return err + } + + for _, disk := range disks { t, err := loadHealingTracker(ctx, disk) if err != nil { if !errors.Is(err, errFileNotFound) { diff --git a/cmd/data-scanner.go b/cmd/data-scanner.go index 67f1ff220..80d00f70f 100644 --- a/cmd/data-scanner.go +++ b/cmd/data-scanner.go @@ -33,7 +33,6 @@ import ( "sync" "time" - "github.com/dustin/go-humanize" "github.com/minio/madmin-go/v3" "github.com/minio/minio/internal/bucket/lifecycle" "github.com/minio/minio/internal/bucket/object/lock" @@ -302,7 +301,7 @@ type folderScanner struct { // The returned cache will always be valid, but may not be updated from the existing. // Before each operation sleepDuration is called which can be used to temporarily halt the scanner. // If the supplied context is canceled the function will return at the first chance. -func scanDataFolder(ctx context.Context, poolIdx, setIdx int, basePath string, cache dataUsageCache, getSize getSizeFn, scanMode madmin.HealScanMode) (dataUsageCache, error) { +func scanDataFolder(ctx context.Context, disks []StorageAPI, basePath string, cache dataUsageCache, getSize getSizeFn, scanMode madmin.HealScanMode) (dataUsageCache, error) { switch cache.Info.Name { case "", dataUsageRoot: return cache, errors.New("internal error: root scan attempted") @@ -321,20 +320,8 @@ func scanDataFolder(ctx context.Context, poolIdx, setIdx int, basePath string, c scanMode: scanMode, updates: cache.Info.updates, updateCurrentPath: updatePath, - } - - // Add disks for set healing. - if poolIdx >= 0 && setIdx >= 0 { - objAPI, ok := newObjectLayerFn().(*erasureServerPools) - if ok { - if poolIdx < len(objAPI.serverPools) && setIdx < len(objAPI.serverPools[poolIdx].sets) { - // Pass the disks belonging to the set. - s.disks = objAPI.serverPools[poolIdx].sets[setIdx].getDisks() - s.disksQuorum = len(s.disks) / 2 - } else { - logger.LogIf(ctx, fmt.Errorf("Matching pool %s, set %s not found", humanize.Ordinal(poolIdx+1), humanize.Ordinal(setIdx+1))) - } - } + disks: disks, + disksQuorum: len(disks) / 2, } // Enable healing in XL mode. @@ -649,8 +636,7 @@ func (f *folderScanner) scanFolder(ctx context.Context, folder cachedFolder, int break } - objAPI, ok := newObjectLayerFn().(*erasureServerPools) - if !ok || len(f.disks) == 0 || f.disksQuorum == 0 { + if len(f.disks) == 0 || f.disksQuorum == 0 { break } @@ -688,7 +674,9 @@ func (f *folderScanner) scanFolder(ctx context.Context, folder cachedFolder, int // Bucket might be missing as well with abandoned children. // make sure it is created first otherwise healing won't proceed // for objects. - _, _ = objAPI.HealBucket(ctx, bucket, madmin.HealOpts{}) + bgSeq.queueHealTask(healSource{ + bucket: bucket, + }, madmin.HealItemBucket) } resolver.bucket = bucket diff --git a/cmd/data-usage_test.go b/cmd/data-usage_test.go index b72b5261a..17a4cfc34 100644 --- a/cmd/data-usage_test.go +++ b/cmd/data-usage_test.go @@ -62,7 +62,7 @@ func TestDataUsageUpdate(t *testing.T) { return } - got, err := scanDataFolder(context.Background(), 0, 0, base, dataUsageCache{Info: dataUsageCacheInfo{Name: bucket}}, getSize, 0) + got, err := scanDataFolder(context.Background(), nil, base, dataUsageCache{Info: dataUsageCacheInfo{Name: bucket}}, getSize, 0) if err != nil { t.Fatal(err) } @@ -173,7 +173,7 @@ func TestDataUsageUpdate(t *testing.T) { } // Changed dir must be picked up in this many cycles. for i := 0; i < dataUsageUpdateDirCycles; i++ { - got, err = scanDataFolder(context.Background(), 0, 0, base, got, getSize, 0) + got, err = scanDataFolder(context.Background(), nil, base, got, getSize, 0) got.Info.NextCycle++ if err != nil { t.Fatal(err) @@ -280,7 +280,7 @@ func TestDataUsageUpdatePrefix(t *testing.T) { } return } - got, err := scanDataFolder(context.Background(), 0, 0, base, dataUsageCache{Info: dataUsageCacheInfo{Name: "bucket"}}, getSize, 0) + got, err := scanDataFolder(context.Background(), nil, base, dataUsageCache{Info: dataUsageCacheInfo{Name: "bucket"}}, getSize, 0) if err != nil { t.Fatal(err) } @@ -414,7 +414,7 @@ func TestDataUsageUpdatePrefix(t *testing.T) { } // Changed dir must be picked up in this many cycles. for i := 0; i < dataUsageUpdateDirCycles; i++ { - got, err = scanDataFolder(context.Background(), 0, 0, base, got, getSize, 0) + got, err = scanDataFolder(context.Background(), nil, base, got, getSize, 0) got.Info.NextCycle++ if err != nil { t.Fatal(err) @@ -562,7 +562,7 @@ func TestDataUsageCacheSerialize(t *testing.T) { } return } - want, err := scanDataFolder(context.Background(), 0, 0, base, dataUsageCache{Info: dataUsageCacheInfo{Name: bucket}}, getSize, 0) + want, err := scanDataFolder(context.Background(), nil, base, dataUsageCache{Info: dataUsageCacheInfo{Name: bucket}}, getSize, 0) if err != nil { t.Fatal(err) } diff --git a/cmd/erasure-healing-common_test.go b/cmd/erasure-healing-common_test.go index 41b630b17..8012dae1f 100644 --- a/cmd/erasure-healing-common_test.go +++ b/cmd/erasure-healing-common_test.go @@ -233,7 +233,12 @@ func TestListOnlineDisks(t *testing.T) { object := "object" data := bytes.Repeat([]byte("a"), smallFileThreshold*16) z := obj.(*erasureServerPools) - erasureDisks := z.serverPools[0].sets[0].getDisks() + + erasureDisks, err := z.GetDisks(0, 0) + if err != nil { + t.Fatal(err) + } + for i, test := range testCases { test := test t.Run(fmt.Sprintf("case-%d", i), func(t *testing.T) { @@ -405,7 +410,12 @@ func TestListOnlineDisksSmallObjects(t *testing.T) { object := "object" data := bytes.Repeat([]byte("a"), smallFileThreshold/2) z := obj.(*erasureServerPools) - erasureDisks := z.serverPools[0].sets[0].getDisks() + + erasureDisks, err := z.GetDisks(0, 0) + if err != nil { + t.Fatal(err) + } + for i, test := range testCases { test := test t.Run(fmt.Sprintf("case-%d", i), func(t *testing.T) { diff --git a/cmd/xl-storage.go b/cmd/xl-storage.go index 6ff92110b..d8c97faac 100644 --- a/cmd/xl-storage.go +++ b/cmd/xl-storage.go @@ -485,11 +485,16 @@ func (s *xlStorage) NSScanner(ctx context.Context, cache dataUsageCache, updates return cache, errServerNotInitialized } - cache.Info.updates = updates - poolIdx, setIdx, _ := s.GetDiskLoc() - dataUsageInfo, err := scanDataFolder(ctx, poolIdx, setIdx, s.diskPath, cache, func(item scannerItem) (sizeSummary, error) { + disks, err := objAPI.GetDisks(poolIdx, setIdx) + if err != nil { + return cache, err + } + + cache.Info.updates = updates + + dataUsageInfo, err := scanDataFolder(ctx, disks, s.diskPath, cache, func(item scannerItem) (sizeSummary, error) { // Look for `xl.meta/xl.json' at the leaf. if !strings.HasSuffix(item.Path, SlashSeparator+xlStorageFormatFile) && !strings.HasSuffix(item.Path, SlashSeparator+xlStorageFormatFileV1) {