diff --git a/cmd/erasure-object.go b/cmd/erasure-object.go index ba306afab..628c10caa 100644 --- a/cmd/erasure-object.go +++ b/cmd/erasure-object.go @@ -364,6 +364,24 @@ func (er erasureObjects) getObjectFileInfo(ctx context.Context, bucket, object s } if reducedErr := reduceReadQuorumErrs(ctx, errs, objectOpIgnoredErrs, readQuorum); reducedErr != nil { + if reducedErr == errErasureReadQuorum && bucket != minioMetaBucket { + if _, ok := isObjectDangling(metaArr, errs, nil); ok { + reducedErr = errFileNotFound + if opts.VersionID != "" { + reducedErr = errFileVersionNotFound + } + // Remove the dangling object only when: + // - This is a non versioned bucket + // - This is a versioned bucket and the version ID is passed, the reason + // is that we cannot fetch the ID of the latest version when we don't trust xl.meta + if !opts.Versioned || opts.VersionID != "" { + er.deleteObjectVersion(ctx, bucket, object, 1, FileInfo{ + Name: object, + VersionID: opts.VersionID, + }) + } + } + } return fi, nil, nil, toObjectErr(reducedErr, bucket, object) } diff --git a/cmd/fs-v1-multipart_test.go b/cmd/fs-v1-multipart_test.go index e75bf2da9..eaaabd800 100644 --- a/cmd/fs-v1-multipart_test.go +++ b/cmd/fs-v1-multipart_test.go @@ -21,6 +21,7 @@ import ( "context" "os" "path/filepath" + "runtime" "sync" "testing" "time" @@ -195,6 +196,11 @@ func TestCompleteMultipartUpload(t *testing.T) { // TestCompleteMultipartUpload - test CompleteMultipartUpload func TestAbortMultipartUpload(t *testing.T) { + if runtime.GOOS == globalWindowsOSName { + // Concurrent AbortMultipartUpload() fails on windows + t.Skip() + } + // Prepare for tests disk := filepath.Join(globalTestTmpDir, "minio-"+nextSuffix()) defer os.RemoveAll(disk) @@ -219,7 +225,6 @@ func TestAbortMultipartUpload(t *testing.T) { if _, err := obj.PutObjectPart(GlobalContext, bucketName, objectName, uploadID, 1, mustGetPutObjReader(t, bytes.NewReader(data), 5, md5Hex, ""), opts); err != nil { t.Fatal("Unexpected error ", err) } - time.Sleep(time.Second) // Without Sleep on windows, the fs.AbortMultipartUpload() fails with "The process cannot access the file because it is being used by another process." if err := obj.AbortMultipartUpload(GlobalContext, bucketName, objectName, uploadID, opts); err != nil { t.Fatal("Unexpected error ", err) } diff --git a/cmd/test-utils_test.go b/cmd/test-utils_test.go index dbbfcb87b..1de9dd0e3 100644 --- a/cmd/test-utils_test.go +++ b/cmd/test-utils_test.go @@ -2242,9 +2242,15 @@ func generateTLSCertKey(host string) ([]byte, []byte, error) { func mustGetZoneEndpoints(args ...string) EndpointServerSets { endpoints := mustGetNewEndpoints(args...) + drivesPerSet := len(args) + setCount := 1 + if len(args) >= 16 { + drivesPerSet = 16 + setCount = len(args) / 16 + } return []ZoneEndpoints{{ - SetCount: 1, - DrivesPerSet: len(args), + SetCount: setCount, + DrivesPerSet: drivesPerSet, Endpoints: endpoints, }} }