mirror of
https://github.com/pgsty/minio.git
synced 2026-11-09 17:21:51 +03:00
Integrate complete R3 input-error regression fix
Signed-off-by: Feng Ruohang <rh@vonng.com>
This commit is contained in:
@@ -104,7 +104,7 @@ jobs:
|
||||
- name: Run multipart listing, cancellation and cleanup tests under race detector
|
||||
env:
|
||||
MINIO_API_REQUESTS_MAX: "10000"
|
||||
run: go test -race ./cmd -run '^Test(Multipart|PaginateMultipartUploads|ListMultipartUploads|CleanupStaleUploads|ExtractModTime)' -count=1 -timeout=5m
|
||||
run: go test -race ./cmd -run '^Test(ObjectCompleteMultipartUpload|Multipart|PaginateMultipartUploads|ListMultipartUploads|CleanupStaleUploads|ExtractModTime)' -count=1 -timeout=5m
|
||||
|
||||
- name: Run listing metadata recovery, pagination and cancellation tests under race detector
|
||||
run: go test -race ./cmd -run '^Test(ListFallback|ListingCache|ListingMerge|ListingRecovery|ListingPending|ListingEntry|ListingSecondLock|StreamMetadataParts|LocalLockerListing|DistributedListing|MergeXLV2LatestNullCrossParity|CountXLV2MixedECGroups|ListCrossParity|ListObjectVersionsCrossParityNull|MigrationCrossParity)' -count=1 -timeout=5m
|
||||
|
||||
@@ -2419,13 +2419,17 @@ func (z *erasureServerPools) CompleteMultipartUpload(ctx context.Context, bucket
|
||||
|
||||
// Hold write locks to verify uploaded parts, also disallows any
|
||||
// parallel PutObjectPart() requests.
|
||||
uploadIDLock := z.NewNSLock(bucket, pathJoin(object, uploadID))
|
||||
wlkctx, err := uploadIDLock.GetLock(ctx, globalOperationTimeout)
|
||||
if err != nil {
|
||||
return objInfo, err
|
||||
// An empty upload ID aliases the object lock already held above.
|
||||
// Let the storage layer return its normal missing bucket/upload error.
|
||||
if uploadID != "" {
|
||||
uploadIDLock := z.NewNSLock(bucket, pathJoin(object, uploadID))
|
||||
wlkctx, err := uploadIDLock.GetLock(ctx, globalOperationTimeout)
|
||||
if err != nil {
|
||||
return objInfo, err
|
||||
}
|
||||
ctx = wlkctx.Context()
|
||||
defer uploadIDLock.Unlock(wlkctx)
|
||||
}
|
||||
ctx = wlkctx.Context()
|
||||
defer uploadIDLock.Unlock(wlkctx)
|
||||
|
||||
if z.SinglePool() {
|
||||
return z.serverPools[0].CompleteMultipartUpload(ctx, bucket, object, uploadID, uploadedParts, opts)
|
||||
|
||||
@@ -707,3 +707,35 @@ func (r *nativeRestorePartGateReader) Read(p []byte) (int, error) {
|
||||
}
|
||||
return r.ReadCloser.Read(p)
|
||||
}
|
||||
|
||||
// Invalid upload paths must retain the backend's normal error precedence,
|
||||
// rather than reacquiring the object lock as the upload lock.
|
||||
func TestMultipartCompletionLockAlias(t *testing.T) {
|
||||
for _, pools := range []int{1, 2} {
|
||||
for _, id := range []string{"", ".", "./"} {
|
||||
t.Run(fmt.Sprintf("pools=%d/id=%q", pools, id), func(t *testing.T) {
|
||||
r := newRestoreSafetyTest(t, pools, versioning.Enabled)
|
||||
for _, missingBucket := range []bool{false, true} {
|
||||
bucket := r.bucket
|
||||
if missingBucket {
|
||||
bucket = "missing-bucket"
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(t.Context(), 200*time.Millisecond)
|
||||
_, err := r.z.CompleteMultipartUpload(ctx, bucket, r.object, id, nil, ObjectOptions{})
|
||||
cancel()
|
||||
if id != "" {
|
||||
if !errors.As(err, &MalformedUploadID{}) {
|
||||
t.Errorf("malformed upload: %v", err)
|
||||
}
|
||||
} else if missingBucket {
|
||||
if !isErrBucketNotFound(err) {
|
||||
t.Errorf("missing bucket: %v", err)
|
||||
}
|
||||
} else if !errors.As(err, &InvalidUploadID{}) {
|
||||
t.Errorf("invalid upload: %v", err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user