From dc86b8d9d4e5bb274b38da89e249927f04b39bb9 Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Fri, 4 Oct 2024 00:13:14 -0700 Subject: [PATCH] fix: when readQuorum, inconsistent metadata return 404 (#20522) in cases where we cannot possibly know a way to read and construct the object, it is impossible to achieve any form of quorum via xl.meta while we have sufficient responses from all the drives, we should return object not found. --- cmd/erasure-object.go | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/cmd/erasure-object.go b/cmd/erasure-object.go index df878c67c..367f489e9 100644 --- a/cmd/erasure-object.go +++ b/cmd/erasure-object.go @@ -102,7 +102,7 @@ func (er erasureObjects) CopyObject(ctx context.Context, srcBucket, srcObject, d readQuorum, writeQuorum, err := objectQuorumFromMeta(ctx, metaArr, errs, er.defaultParityCount) if err != nil { - if errors.Is(err, errErasureReadQuorum) && !strings.HasPrefix(srcBucket, minioMetaBucket) { + if shouldCheckForDangling(err, errs, srcBucket) { _, derr := er.deleteIfDangling(context.Background(), srcBucket, srcObject, metaArr, errs, nil, srcOpts) if derr == nil { if srcOpts.VersionID != "" { @@ -690,13 +690,9 @@ func shouldCheckForDangling(err error, errs []error, bucket string) bool { // 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 - } - } + // Check if the object is non-existent on most disks but not all of them + case (errors.Is(err, errFileNotFound) || errors.Is(err, errFileVersionNotFound)) && (countErrs(errs, nil) > 0): + return true } return false } @@ -921,6 +917,16 @@ func (er erasureObjects) getObjectFileInfo(ctx context.Context, bucket, object s } } } + // when we have insufficient read quorum and inconsistent metadata return + // file not found, since we can't possibly have a way to recover this object + // anyway. + if v, ok := err.(InsufficientReadQuorum); ok && v.Type == RQInconsistentMeta { + if opts.VersionID != "" { + err = errFileVersionNotFound + } else { + err = errFileNotFound + } + } return fi, nil, nil, toObjectErr(err, bucket, object) } @@ -2138,7 +2144,7 @@ func (er erasureObjects) PutObjectMetadata(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(context.Background(), bucket, object, metaArr, errs, nil, opts) if derr == nil { if opts.VersionID != "" { @@ -2217,7 +2223,7 @@ func (er erasureObjects) PutObjectTags(ctx context.Context, bucket, object strin 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(context.Background(), bucket, object, metaArr, errs, nil, opts) if derr == nil { if opts.VersionID != "" {