diff --git a/cmd/fs-v1-multipart.go b/cmd/fs-v1-multipart.go index 359ce87b2..255f354ac 100644 --- a/cmd/fs-v1-multipart.go +++ b/cmd/fs-v1-multipart.go @@ -574,11 +574,16 @@ func (fs fsObjects) CompleteMultipartUpload(bucket string, object string, upload return "", toObjectErr(err, minioMetaMultipartBucket, fsMetaPath) } + // This lock is held during rename of the appended tmp file to the actual + // location so that any competing GetObject/PutObject/DeleteObject do not race. + objectLock := nsMutex.NewNSLock(bucket, object) appendFallback := true // In case background-append did not append the required parts. if isPartsSame(fsMeta.Parts, parts) { err = fs.bgAppend.complete(fs.storage, bucket, object, uploadID, fsMeta) if err == nil { appendFallback = false + objectLock.Lock() + defer objectLock.Unlock() if err = fs.storage.RenameFile(minioMetaTmpBucket, uploadID, bucket, object); err != nil { return "", toObjectErr(traceError(err), minioMetaTmpBucket, uploadID) } @@ -653,6 +658,8 @@ func (fs fsObjects) CompleteMultipartUpload(bucket string, object string, upload } } + objectLock.Lock() + defer objectLock.Unlock() // Rename the file back to original location, if not delete the temporary object. err = fs.storage.RenameFile(minioMetaTmpBucket, tempObj, bucket, object) if err != nil {