From 38caddffe766c3462c501ce54f5caba11d93587a Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Tue, 24 May 2022 17:27:45 -0700 Subject: [PATCH] fix: copyObject on versioned bucket when updating metadata (#14971) updating metadata with CopyObject on a versioned bucket causes the latest version to be not readable, this PR fixes this properly by handling the inline data bug fix introduced in PR #14780. This bug affects only inlined data. --- cmd/erasure-object.go | 25 +++++++++++++++---------- cmd/object-handlers.go | 4 ++++ 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/cmd/erasure-object.go b/cmd/erasure-object.go index 5a0639fe1..66f06d84e 100644 --- a/cmd/erasure-object.go +++ b/cmd/erasure-object.go @@ -133,15 +133,6 @@ func (er erasureObjects) CopyObject(ctx context.Context, srcBucket, srcObject, d modTime = UTCNow() } - // If the data is not inlined, we may end up incorrectly - // inlining the data here, that leads to an inconsistent - // situation where some objects are were not inlined - // were now inlined, make sure to `nil` the Data such - // that xl.meta is written as expected. - if !fi.InlineData() { - fi.Data = nil - } - fi.VersionID = versionID // set any new versionID we might have created fi.ModTime = modTime // set modTime for the new versionID if !dstOpts.MTime.IsZero() { @@ -151,12 +142,15 @@ func (er erasureObjects) CopyObject(ctx context.Context, srcBucket, srcObject, d fi.Metadata = srcInfo.UserDefined srcInfo.UserDefined["etag"] = srcInfo.ETag + inlineData := fi.InlineData() + freeVersionID := fi.TierFreeVersionID() + freeVersionMarker := fi.TierFreeVersion() + // Update `xl.meta` content on each disks. for index := range metaArr { if metaArr[index].IsValid() { metaArr[index].ModTime = modTime metaArr[index].VersionID = versionID - metaArr[index].Metadata = srcInfo.UserDefined if !metaArr[index].InlineData() { // If the data is not inlined, we may end up incorrectly // inlining the data here, that leads to an inconsistent @@ -165,6 +159,17 @@ func (er erasureObjects) CopyObject(ctx context.Context, srcBucket, srcObject, d // that xl.meta is written as expected. metaArr[index].Data = nil } + metaArr[index].Metadata = srcInfo.UserDefined + // Preserve existing values + if inlineData { + metaArr[index].SetInlineData() + } + if freeVersionID != "" { + metaArr[index].SetTierFreeVersionID(freeVersionID) + } + if freeVersionMarker { + metaArr[index].SetTierFreeVersion() + } } } diff --git a/cmd/object-handlers.go b/cmd/object-handlers.go index 8de0fa2b6..48123c464 100644 --- a/cmd/object-handlers.go +++ b/cmd/object-handlers.go @@ -1424,6 +1424,10 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re srcInfo.metadataOnly = false } + if srcInfo.metadataOnly { + gr.Close() // We are not interested in the reader stream at this point close it. + } + // Check if x-amz-metadata-directive or x-amz-tagging-directive was not set to REPLACE and source, // destination are same objects. Apply this restriction also when // metadataOnly is true indicating that we are not overwriting the object.