FS/CompleteMultipart: lock the namespace before renaming the appended tmp file. (#3371)

This commit is contained in:
Krishna Srinivas 2016-11-30 12:56:36 +05:30 committed by Harshavardhana
parent d056f19d07
commit e3b4910b66
1 changed files with 7 additions and 0 deletions

View File

@ -574,11 +574,16 @@ func (fs fsObjects) CompleteMultipartUpload(bucket string, object string, upload
return "", toObjectErr(err, minioMetaMultipartBucket, fsMetaPath) 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. appendFallback := true // In case background-append did not append the required parts.
if isPartsSame(fsMeta.Parts, parts) { if isPartsSame(fsMeta.Parts, parts) {
err = fs.bgAppend.complete(fs.storage, bucket, object, uploadID, fsMeta) err = fs.bgAppend.complete(fs.storage, bucket, object, uploadID, fsMeta)
if err == nil { if err == nil {
appendFallback = false appendFallback = false
objectLock.Lock()
defer objectLock.Unlock()
if err = fs.storage.RenameFile(minioMetaTmpBucket, uploadID, bucket, object); err != nil { if err = fs.storage.RenameFile(minioMetaTmpBucket, uploadID, bucket, object); err != nil {
return "", toObjectErr(traceError(err), minioMetaTmpBucket, uploadID) 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. // Rename the file back to original location, if not delete the temporary object.
err = fs.storage.RenameFile(minioMetaTmpBucket, tempObj, bucket, object) err = fs.storage.RenameFile(minioMetaTmpBucket, tempObj, bucket, object)
if err != nil { if err != nil {