mirror of
https://github.com/pgsty/minio.git
synced 2026-11-10 17:45:32 +03:00
fix(restore): rehydrate the selected version under its object lock
Preserve handler version context, resolve the requested version's pool, and return on the initial read failure without writing metadata. Propagate owned NoLock to single-part writes, multipart completion and failure cleanup in the same patch. Preserve the original modification time on cleanup. Route the restore status copy by version and allow internal multipart rehydration only for a matching completed transition. Single-pool restores own the metadata snapshot through download and cleanup. Keep public completion in object-before-upload order, using the target set's object lock for single-pool calls, so concurrent completion cannot invert locks. Cover real signed POSTs, null/UUID and cross-pool identity, download failures, multipart overwrite guards, Object Lock updates and concurrent completion. This package depends on the restored-copy cleanup safety delivered in R2. Signed-off-by: Feng Ruohang <rh@vonng.com>
This commit is contained in:
@@ -34,6 +34,7 @@ import (
|
||||
"github.com/google/uuid"
|
||||
"github.com/klauspost/readahead"
|
||||
"github.com/minio/minio-go/v7/pkg/set"
|
||||
"github.com/minio/minio/internal/bucket/lifecycle"
|
||||
"github.com/minio/minio/internal/config/storageclass"
|
||||
"github.com/minio/minio/internal/crypto"
|
||||
"github.com/minio/minio/internal/hash"
|
||||
@@ -1697,13 +1698,18 @@ func (er erasureObjects) CompleteMultipartUpload(ctx context.Context, bucket str
|
||||
return oi, toObjectErr(err, bucket, object)
|
||||
}
|
||||
} else {
|
||||
_, gerr := getObjectInfo(ctx, bucket, object, ObjectOptions{
|
||||
current, gerr := getObjectInfo(ctx, bucket, object, ObjectOptions{
|
||||
VersionID: fi.VersionID,
|
||||
Versioned: opts.Versioned,
|
||||
VersionSuspended: opts.VersionSuspended,
|
||||
NoLock: true,
|
||||
})
|
||||
switch {
|
||||
case gerr == nil && opts.Transition.RestoreRequest != nil &&
|
||||
current.TransitionedObject.Status == lifecycle.TransitionComplete &&
|
||||
current.ETag == fi.Metadata["etag"] && current.Size == fi.Size && current.ModTime.Equal(fi.ModTime):
|
||||
// The internal restore path rehydrates this same tiered version.
|
||||
// Ordinary multipart completion must still reject a version overwrite.
|
||||
case gerr == nil, errors.As(gerr, &MethodNotAllowed{}):
|
||||
return oi, toObjectErr(errAuthentication, bucket, object)
|
||||
case isErrVersionNotFound(gerr) || isErrObjectNotFound(gerr):
|
||||
|
||||
Reference in New Issue
Block a user