xl: Respect min. space by checking PrepareFile err (#3867)

It was possible to upload a big file which overcomes the minimal
disk space limit in XL, PrepareFile was actually checking for disk
space but we weren't checking its returned error. This patch fixes
this behavior.
master
Anis Elleuch 8 years ago committed by Harshavardhana
parent 79e0b9e69a
commit a2eae54d11
  1. 4
      cmd/object-api-putobject_test.go
  2. 8
      cmd/xl-v1-multipart.go
  3. 28
      cmd/xl-v1-object.go

@ -179,11 +179,11 @@ func testObjectAPIPutObject(obj ObjectLayer, instanceType string, t TestErrHandl
// Wrapper for calling PutObject tests for both XL multiple disks case // Wrapper for calling PutObject tests for both XL multiple disks case
// when quorum is not available. // when quorum is not available.
func TestObjectAPIPutObjectDiskNotFound(t *testing.T) { func TestObjectAPIPutObjectDiskNotFound(t *testing.T) {
ExecObjectLayerDiskAlteredTest(t, testObjectAPIPutObjectDiskNotFOund) ExecObjectLayerDiskAlteredTest(t, testObjectAPIPutObjectDiskNotFound)
} }
// Tests validate correctness of PutObject. // Tests validate correctness of PutObject.
func testObjectAPIPutObjectDiskNotFOund(obj ObjectLayer, instanceType string, disks []string, t *testing.T) { func testObjectAPIPutObjectDiskNotFound(obj ObjectLayer, instanceType string, disks []string, t *testing.T) {
// Generating cases for which the PutObject fails. // Generating cases for which the PutObject fails.
bucket := "minio-bucket" bucket := "minio-bucket"
object := "minio-object" object := "minio-object"

@ -648,11 +648,9 @@ func (xl xlObjects) PutObjectPart(bucket, object, uploadID string, partID int, s
defer xl.deleteObject(minioMetaTmpBucket, tmpPart) defer xl.deleteObject(minioMetaTmpBucket, tmpPart)
if size > 0 { if size > 0 {
for _, disk := range onlineDisks { if pErr := xl.prepareFile(minioMetaTmpBucket, tmpPartPath, size, onlineDisks, xlMeta.Erasure.BlockSize, xlMeta.Erasure.DataBlocks); err != nil {
if disk != nil { return PartInfo{}, toObjectErr(pErr, bucket, object)
actualSize := xl.sizeOnDisk(size, xlMeta.Erasure.BlockSize, xlMeta.Erasure.DataBlocks)
disk.PrepareFile(minioMetaTmpBucket, tmpPartPath, actualSize)
}
} }
} }

@ -36,6 +36,25 @@ import (
// list all errors which can be ignored in object operations. // list all errors which can be ignored in object operations.
var objectOpIgnoredErrs = append(baseIgnoredErrs, errDiskAccessDenied) var objectOpIgnoredErrs = append(baseIgnoredErrs, errDiskAccessDenied)
// prepareFile hints the bottom layer to optimize the creation of a new object
func (xl xlObjects) prepareFile(bucket, object string, size int64, onlineDisks []StorageAPI, blockSize int64, dataBlocks int) error {
pErrs := make([]error, len(onlineDisks))
// Calculate the real size of the part in one disk.
actualSize := xl.sizeOnDisk(size, blockSize, dataBlocks)
// Prepare object creation in a all disks
for index, disk := range onlineDisks {
if disk != nil {
if err := disk.PrepareFile(bucket, object, actualSize); err != nil {
// Save error to reduce it later
pErrs[index] = err
// Ignore later access to disk which generated the error
onlineDisks[index] = nil
}
}
}
return reduceWriteQuorumErrs(pErrs, objectOpIgnoredErrs, xl.writeQuorum)
}
/// Object Operations /// Object Operations
// CopyObject - copy object source object to destination object. // CopyObject - copy object source object to destination object.
@ -555,12 +574,9 @@ func (xl xlObjects) PutObject(bucket string, object string, size int64, data io.
// Hint the filesystem to pre-allocate one continuous large block. // Hint the filesystem to pre-allocate one continuous large block.
// This is only an optimization. // This is only an optimization.
if curPartSize > 0 { if curPartSize > 0 {
// Calculate the real size of the part in the disk. pErr := xl.prepareFile(minioMetaTmpBucket, tempErasureObj, curPartSize, onlineDisks, xlMeta.Erasure.BlockSize, xlMeta.Erasure.DataBlocks)
actualSize := xl.sizeOnDisk(curPartSize, xlMeta.Erasure.BlockSize, xlMeta.Erasure.DataBlocks) if pErr != nil {
for _, disk := range onlineDisks { return ObjectInfo{}, toObjectErr(pErr, bucket, object)
if disk != nil {
disk.PrepareFile(minioMetaTmpBucket, tempErasureObj, actualSize)
}
} }
} }

Loading…
Cancel
Save