From 22d59e757da6e83ccb954fc6abc094375d73d444 Mon Sep 17 00:00:00 2001 From: Anis Eleuch Date: Thu, 16 Nov 2023 08:39:53 -0800 Subject: [PATCH] Remove stale data in HEAD/GET object (#18460) Currently if the object does not exist in quorum disks of an erasure set, the dangling code is never called because the returned error will be errFileNotFound or errFileVersionNotFound; With this commit, when errFileNotFound or errFileVersionNotFound is returning when trying to calculate the quorum of a given object, the code checks if a disk returned nil, which means a stale object exists in that disk, that will trigger deleteIfDangling() function --- cmd/erasure-object.go | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/cmd/erasure-object.go b/cmd/erasure-object.go index 45d2822b9..ff324c364 100644 --- a/cmd/erasure-object.go +++ b/cmd/erasure-object.go @@ -666,6 +666,32 @@ func readAllXL(ctx context.Context, disks []StorageAPI, bucket, object string, r return metaFileInfos, errs } +// Checking if an object is dangling costs some IOPS; hence implementing this function +// which decides which condition it is useful to check if an object is dangling +// +// errs: errors from reading xl.meta in all disks +// err: reduced errs +// bucket: the object name in question +func shouldCheckForDangling(err error, errs []error, bucket string) bool { + // Avoid data in .minio.sys for now + if bucket == minioMetaBucket { + return false + } + switch { + // Check if we have a read quorum issue + case errors.Is(err, errErasureReadQuorum): + return true + // Check if the object is inexistent in most disks but not all of them + case errors.Is(err, errFileNotFound) || errors.Is(err, errFileVersionNotFound): + for i := range errs { + if errs[i] == nil { + return true + } + } + } + return false +} + func (er erasureObjects) getObjectFileInfo(ctx context.Context, bucket, object string, opts ObjectOptions, readData bool) (fi FileInfo, metaArr []FileInfo, onlineDisks []StorageAPI, err error) { disks := er.getDisks() @@ -680,7 +706,7 @@ func (er erasureObjects) getObjectFileInfo(ctx context.Context, bucket, object s readQuorum, _, err := objectQuorumFromMeta(ctx, metaArr, errs, er.defaultParityCount) if err != nil { - if errors.Is(err, errErasureReadQuorum) && !strings.HasPrefix(bucket, minioMetaBucket) { + if shouldCheckForDangling(err, errs, bucket) { _, derr := er.deleteIfDangling(ctx, bucket, object, metaArr, errs, nil, opts) if derr != nil { err = derr @@ -690,7 +716,7 @@ func (er erasureObjects) getObjectFileInfo(ctx context.Context, bucket, object s } if reducedErr := reduceReadQuorumErrs(ctx, errs, objectOpIgnoredErrs, readQuorum); reducedErr != nil { - if errors.Is(reducedErr, errErasureReadQuorum) && !strings.HasPrefix(bucket, minioMetaBucket) { + if shouldCheckForDangling(err, errs, bucket) { _, derr := er.deleteIfDangling(ctx, bucket, object, metaArr, errs, nil, opts) if derr != nil { reducedErr = derr