From 62d8c649feb1894b3f33586360e5be69cadb2f3e Mon Sep 17 00:00:00 2001 From: Feng Ruohang Date: Wed, 2 Sep 2026 00:42:00 +0800 Subject: [PATCH] fix: preserve metadata during bucket creation and adoption After storage bucket creation, merge required versioning and lock defaults into the latest on-disk metadata under metadata.lock. Avoid ForceCreate and site-adoption rewrites that replaced existing bucket configuration.\n\nRefs: #102 Signed-off-by: Feng Ruohang --- cmd/erasure-server-pool.go | 57 +++++++++++++++++++++++++++++--------- cmd/site-replication.go | 41 +++++++++++++-------------- 2 files changed, 64 insertions(+), 34 deletions(-) diff --git a/cmd/erasure-server-pool.go b/cmd/erasure-server-pool.go index af804fb02..262a5aae3 100644 --- a/cmd/erasure-server-pool.go +++ b/cmd/erasure-server-pool.go @@ -882,23 +882,54 @@ func (z *erasureServerPools) MakeBucket(ctx context.Context, bucket string, opts return err } - // If it doesn't exist we get a new, so ignore errors - meta := newBucketMetadata(bucket) - meta.SetCreatedAt(opts.CreatedAt) - if opts.LockEnabled { - meta.VersioningConfigXML = enabledBucketVersioningConfig - meta.ObjectLockConfigXML = enabledBucketObjectLockConfig + if isMinioMetaBucketName(bucket) { + meta := newBucketMetadata(bucket) + meta.SetCreatedAt(opts.CreatedAt) + if err := meta.Save(context.Background(), z); err != nil { + return toObjectErr(err, bucket) + } + globalBucketMetadataSys.Set(bucket, meta) + return nil } - if opts.VersioningEnabled { - meta.VersioningConfigXML = enabledBucketVersioningConfig - } - - if err := meta.Save(context.Background(), z); err != nil { + ctx, unlock, err := lockBucketMetadata(ctx, z, bucket) + if err != nil { + return toObjectErr(err, bucket) + } + err = func() error { + defer unlock() + meta, err := readBucketMetadata(ctx, z, bucket) + if errors.Is(err, errConfigNotFound) { + meta = newBucketMetadata(bucket) + } else if err != nil { + return err + } + if meta.Created.IsZero() { + meta.SetCreatedAt(opts.CreatedAt) + } + if opts.LockEnabled { + if len(meta.VersioningConfigXML) == 0 { + meta.VersioningConfigXML = enabledBucketVersioningConfig + meta.VersioningConfigUpdatedAt = meta.Created + } + if len(meta.ObjectLockConfigXML) == 0 { + meta.ObjectLockConfigXML = enabledBucketObjectLockConfig + meta.ObjectLockConfigUpdatedAt = meta.Created + } + } + if opts.VersioningEnabled && len(meta.VersioningConfigXML) == 0 { + meta.VersioningConfigXML = enabledBucketVersioningConfig + meta.VersioningConfigUpdatedAt = meta.Created + } + if err = meta.Save(ctx, z); err != nil { + return err + } + globalBucketMetadataSys.Set(bucket, meta) + return nil + }() + if err != nil { return toObjectErr(err, bucket) } - - globalBucketMetadataSys.Set(bucket, meta) // Success. return nil diff --git a/cmd/site-replication.go b/cmd/site-replication.go index aff230822..eadaef93a 100644 --- a/cmd/site-replication.go +++ b/cmd/site-replication.go @@ -930,35 +930,34 @@ func (c *SiteReplicationSys) PeerBucketMakeWithVersioningHandler(ctx context.Con if !ok1 && !ok2 { return wrapSRErr(c.annotateErr(makeBucketWithVersion, err)) } - } else { - // Load updated bucket metadata into memory as new - // bucket was created. - globalNotificationSys.LoadBucketMetadata(GlobalContext, bucket) } - - meta, err := globalBucketMetadataSys.Get(bucket) + ctx, unlock, err := lockBucketMetadata(ctx, objAPI, bucket) if err != nil { return wrapSRErr(c.annotateErr(makeBucketWithVersion, err)) } - - meta.SetCreatedAt(opts.CreatedAt) - - if err := enablePeerBucketVersioning(&meta); err != nil { - return wrapSRErr(err) - } - if opts.LockEnabled && len(meta.ObjectLockConfigXML) == 0 { - meta.ObjectLockConfigXML = enabledBucketObjectLockConfig - if meta.ObjectLockConfigUpdatedAt.IsZero() { - meta.ObjectLockConfigUpdatedAt = meta.Created + err = func() error { + defer unlock() + meta, err := loadBucketMetadataParse(ctx, objAPI, bucket, true) + if err != nil { + return err } - } + meta.SetCreatedAt(opts.CreatedAt) - if err := meta.Save(context.Background(), objAPI); err != nil { - return wrapSRErr(err) + if err = enablePeerBucketVersioning(&meta); err != nil { + return err + } + if opts.LockEnabled && len(meta.ObjectLockConfigXML) == 0 { + meta.ObjectLockConfigXML = enabledBucketObjectLockConfig + if meta.ObjectLockConfigUpdatedAt.IsZero() { + meta.ObjectLockConfigUpdatedAt = meta.Created + } + } + return globalBucketMetadataSys.saveMetadata(ctx, objAPI, meta) + }() + if err != nil { + return wrapSRErr(c.annotateErr(makeBucketWithVersion, err)) } - globalBucketMetadataSys.Set(bucket, meta) - // Load updated bucket metadata into memory as new metadata updated. globalNotificationSys.LoadBucketMetadata(GlobalContext, bucket) return nil