From fd4da3a3396ec35cf9dda387b4b767f0d955b645 Mon Sep 17 00:00:00 2001 From: Chris Lu Date: Tue, 20 Oct 2026 13:12:41 -0700 Subject: [PATCH] s3: read the winning entry when a create loses the race The concurrent-create branch called existingBucketError on a name the registry had just cached as absent, answering NoSuchBucket, and the auto-create fallback could assign an S3 owner to a table bucket it met there. The negative cache is cleared before the existing-bucket error is built, and a table bucket keeps its owner-less shape. --- weed/s3api/s3api_bucket_handlers.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/weed/s3api/s3api_bucket_handlers.go b/weed/s3api/s3api_bucket_handlers.go index 0dce16aa80..79dddc434c 100644 --- a/weed/s3api/s3api_bucket_handlers.go +++ b/weed/s3api/s3api_bucket_handlers.go @@ -380,6 +380,9 @@ func (s3a *S3ApiServer) PutBucketHandler(w http.ResponseWriter, r *http.Request) s3err.WriteErrorResponse(w, r, s3err.ErrBucketAlreadyExists) return } + if s3a.bucketConfigCache != nil { + s3a.bucketConfigCache.RemoveNegativeCache(bucket) + } errCode := s3a.existingBucketError(r, bucket, currentIdentityId, requestHasACL) if errCode == s3err.ErrBucketAlreadyOwnedByYou { s3a.healBucketOwnerIndex(bucket, currentIdentityId) @@ -761,10 +764,15 @@ func (s3a *S3ApiServer) autoCreateBucket(r *http.Request, bucket string) error { glog.Warningf("autoCreateBucket: failed to check existence for bucket %s: %v", bucket, err2) return fmt.Errorf("failed to auto-create bucket %s: %w", bucket, errors.Join(err, err2)) } else if exist { + entry, getErr := s3a.getEntry(s3a.option.BucketsPath, bucket) + if getErr == nil && concurrentEntryIsForeign(entry, nil) { + // A table bucket carries no S3 owner and must not gain one. + return nil + } // The bucket exists, which is fine. However, we should ensure it has an owner. // If it was created by a concurrent request that didn't set an owner, // we'll set it here to ensure consistency. - if entry, getErr := s3a.getEntry(s3a.option.BucketsPath, bucket); getErr == nil { + if getErr == nil { if entry.Extended == nil || len(entry.Extended[s3_constants.AmzIdentityId]) == 0 { // No owner set, assign current admin as owner setBucketOwner(r)(entry)