mirror of
https://github.com/minio/minio.git
synced 2024-12-24 22:25:54 -05:00
Fix multipart restore to remove part match (#12161)
Part ETags are not available after multipart finalizes, removing this check as not useful. Signed-off-by: Poorna Krishnamoorthy <poorna@minio.io> Co-authored-by: Harshavardhana <harsha@minio.io>
This commit is contained in:
parent
26544848ea
commit
4be0f92067
@ -505,6 +505,11 @@ func (er erasureObjects) healObject(ctx context.Context, bucket string, object s
|
|||||||
// record the index of the updated disks
|
// record the index of the updated disks
|
||||||
partsMetadata[i].Erasure.Index = i + 1
|
partsMetadata[i].Erasure.Index = i + 1
|
||||||
|
|
||||||
|
// dataDir should be empty when
|
||||||
|
// - transitionStatus is complete and not in restored state
|
||||||
|
if partsMetadata[i].TransitionStatus == lifecycle.TransitionComplete && !isRestoredObjectOnDisk(partsMetadata[i].Metadata) {
|
||||||
|
partsMetadata[i].DataDir = ""
|
||||||
|
}
|
||||||
// Attempt a rename now from healed data to final location.
|
// Attempt a rename now from healed data to final location.
|
||||||
if err = disk.RenameData(ctx, minioMetaTmpBucket, tmpID, partsMetadata[i], bucket, object); err != nil {
|
if err = disk.RenameData(ctx, minioMetaTmpBucket, tmpID, partsMetadata[i], bucket, object); err != nil {
|
||||||
logger.LogIf(ctx, err)
|
logger.LogIf(ctx, err)
|
||||||
|
@ -575,7 +575,7 @@ func (er erasureObjects) PutObjectPart(ctx context.Context, bucket, object, uplo
|
|||||||
PartNumber: partID,
|
PartNumber: partID,
|
||||||
ETag: md5hex,
|
ETag: md5hex,
|
||||||
LastModified: fi.ModTime,
|
LastModified: fi.ModTime,
|
||||||
Size: fi.Size,
|
Size: n,
|
||||||
ActualSize: data.ActualSize(),
|
ActualSize: data.ActualSize(),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
@ -1475,37 +1475,15 @@ func (er erasureObjects) restoreTransitionedObject(ctx context.Context, bucket s
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return setRestoreHeaderFn(oi, err)
|
return setRestoreHeaderFn(oi, err)
|
||||||
}
|
}
|
||||||
|
if pInfo.Size != partInfo.Size {
|
||||||
|
return setRestoreHeaderFn(oi, InvalidObjectState{Bucket: bucket, Object: object})
|
||||||
|
}
|
||||||
uploadedParts = append(uploadedParts, CompletePart{
|
uploadedParts = append(uploadedParts, CompletePart{
|
||||||
PartNumber: pInfo.PartNumber,
|
PartNumber: pInfo.PartNumber,
|
||||||
ETag: pInfo.ETag,
|
ETag: pInfo.ETag,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
partsMatch := true
|
|
||||||
// validate parts created via multipart
|
|
||||||
if len(oi.Parts) == len(uploadedParts) {
|
|
||||||
for i, pi := range oi.Parts {
|
|
||||||
if uploadedParts[i].ETag != pi.ETag {
|
|
||||||
partsMatch = false
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
partsMatch = false
|
|
||||||
}
|
|
||||||
|
|
||||||
if !partsMatch {
|
|
||||||
return setRestoreHeaderFn(oi, InvalidObjectState{Bucket: bucket, Object: object})
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = er.CompleteMultipartUpload(ctx, bucket, object, uploadID, uploadedParts, ObjectOptions{
|
_, err = er.CompleteMultipartUpload(ctx, bucket, object, uploadID, uploadedParts, ObjectOptions{
|
||||||
MTime: oi.ModTime,
|
MTime: oi.ModTime})
|
||||||
Versioned: globalBucketVersioningSys.Enabled(bucket),
|
return setRestoreHeaderFn(oi, err)
|
||||||
VersionSuspended: globalBucketVersioningSys.Suspended(bucket),
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
uploadIDPath := er.getUploadIDDir(bucket, object, uploadID)
|
|
||||||
return setRestoreHeaderFn(oi, toObjectErr(err, minioMetaMultipartBucket, uploadIDPath))
|
|
||||||
}
|
|
||||||
return setRestoreHeaderFn(oi, nil)
|
|
||||||
}
|
}
|
||||||
|
@ -495,7 +495,7 @@ func (e TransitionStorageClassNotFound) Error() string {
|
|||||||
type InvalidObjectState GenericError
|
type InvalidObjectState GenericError
|
||||||
|
|
||||||
func (e InvalidObjectState) Error() string {
|
func (e InvalidObjectState) Error() string {
|
||||||
return "The operation is not valid for the current state of the object" + e.Bucket + "/" + e.Object
|
return "The operation is not valid for the current state of the object " + e.Bucket + "/" + e.Object + "(" + e.VersionID + ")"
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Bucket related errors.
|
/// Bucket related errors.
|
||||||
|
@ -1858,8 +1858,7 @@ func (s *xlStorage) RenameData(ctx context.Context, srcVolume, srcPath string, f
|
|||||||
var srcDataPath string
|
var srcDataPath string
|
||||||
var dstDataPath string
|
var dstDataPath string
|
||||||
dataDir := retainSlash(fi.DataDir)
|
dataDir := retainSlash(fi.DataDir)
|
||||||
// no need to rename dataDir paths for objects that are in transitionComplete state.
|
if dataDir != "" {
|
||||||
if dataDir != "" && fi.TransitionStatus != lifecycle.TransitionComplete {
|
|
||||||
srcDataPath = retainSlash(pathJoin(srcVolumeDir, srcPath, dataDir))
|
srcDataPath = retainSlash(pathJoin(srcVolumeDir, srcPath, dataDir))
|
||||||
// make sure to always use path.Join here, do not use pathJoin as
|
// make sure to always use path.Join here, do not use pathJoin as
|
||||||
// it would additionally add `/` at the end and it comes in the
|
// it would additionally add `/` at the end and it comes in the
|
||||||
|
Loading…
Reference in New Issue
Block a user