From 302ec27fa220dc443db37671bedc868dab3f6f27 Mon Sep 17 00:00:00 2001 From: Krishnan Parthasarathi Date: Fri, 27 May 2016 13:42:44 +0530 Subject: [PATCH] Fixed race during parallel PutObjectPart requests (#1775) The race is between two parallel PutObjectPart requests updating partsInfo in xl.json. Previously, it was being updated under a RLock(). --- xl-v1-multipart.go | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/xl-v1-multipart.go b/xl-v1-multipart.go index 4b0dccc06..ba6bc02c5 100644 --- a/xl-v1-multipart.go +++ b/xl-v1-multipart.go @@ -114,23 +114,19 @@ func (xl xlObjects) putObjectPartCommon(bucket string, object string, uploadID s if !IsValidObjectName(object) { return "", ObjectNameInvalid{Bucket: bucket, Object: object} } + // Hold write lock on the uploadID so that no one aborts it. + nsMutex.Lock(minioMetaBucket, pathJoin(mpartMetaPrefix, bucket, object, uploadID)) + defer nsMutex.Unlock(minioMetaBucket, pathJoin(mpartMetaPrefix, bucket, object, uploadID)) + if !xl.isUploadIDExists(bucket, object, uploadID) { return "", InvalidUploadID{UploadID: uploadID} } - // Hold read lock on the uploadID so that no one aborts it. - nsMutex.RLock(minioMetaBucket, pathJoin(mpartMetaPrefix, bucket, object, uploadID)) - defer nsMutex.RUnlock(minioMetaBucket, pathJoin(mpartMetaPrefix, bucket, object, uploadID)) // Hold write lock on the part so that there is no parallel upload on the part. nsMutex.Lock(minioMetaBucket, pathJoin(mpartMetaPrefix, bucket, object, uploadID, strconv.Itoa(partID))) defer nsMutex.Unlock(minioMetaBucket, pathJoin(mpartMetaPrefix, bucket, object, uploadID, strconv.Itoa(partID))) uploadIDPath := path.Join(mpartMetaPrefix, bucket, object, uploadID) - xlMeta, err := xl.readXLMetadata(minioMetaBucket, uploadIDPath) - if err != nil { - return "", toObjectErr(err, minioMetaBucket, uploadIDPath) - } - // List all online disks. onlineDisks, higherVersion, err := xl.listOnlineDisks(minioMetaBucket, pathJoin(mpartMetaPrefix, bucket, object, uploadID)) if err != nil { @@ -142,6 +138,11 @@ func (xl xlObjects) putObjectPartCommon(bucket string, object string, uploadID s higherVersion++ } + xlMeta, err := xl.readXLMetadata(minioMetaBucket, uploadIDPath) + if err != nil { + return "", toObjectErr(err, minioMetaBucket, uploadIDPath) + } + // Initialize a new erasure with online disks and new distribution. erasure := newErasure(onlineDisks, xlMeta.Erasure.Distribution)