From 03875d61e3959c510f0d6b45282fcc72eb160db3 Mon Sep 17 00:00:00 2001 From: Feng Ruohang Date: Sun, 25 Oct 2026 13:02:23 +0800 Subject: [PATCH] fix: reuse validated latest state without rescanning version history Signed-off-by: Feng Ruohang --- cmd/erasure-object.go | 2 +- cmd/object-mutation-consistency_test.go | 2 +- cmd/object-mutation.go | 41 ++++++++----------------- 3 files changed, 14 insertions(+), 31 deletions(-) diff --git a/cmd/erasure-object.go b/cmd/erasure-object.go index e9a2fbb8f..c2dbcfdcb 100644 --- a/cmd/erasure-object.go +++ b/cmd/erasure-object.go @@ -997,7 +997,7 @@ func (er erasureObjects) getObjectFileInfo(ctx context.Context, bucket, object s rw.Lock() // when its a versioned bucket and empty versionID - at totalResp == setDriveCount // we must use rawFileInfo to resolve versions to figure out the latest version. - if opts.VersionID == "" && totalResp == er.setDriveCount && !uniformLatestVersion(rawArr, metaArr, errs) { + if opts.VersionID == "" && totalResp == er.setDriveCount && !uniformLatestVersion(metaArr, errs) { fi, onlineMeta, onlineDisks, modTime, etag, err = calcQuorum(pickLatestQuorumFilesInfo(ctx, rawArr, errs, bucket, object, readData, opts.InclFreeVersions)) } else { diff --git a/cmd/object-mutation-consistency_test.go b/cmd/object-mutation-consistency_test.go index 8573777ff..3c1c121cb 100644 --- a/cmd/object-mutation-consistency_test.go +++ b/cmd/object-mutation-consistency_test.go @@ -138,7 +138,7 @@ func TestMutationVersionHistoryRead(t *testing.T) { } meta[i], errs[i] = fileInfoFromRaw(raw[i], bucket, object, false, false) } - return uniformLatestVersion(raw, meta, errs) + return uniformLatestVersion(meta, errs) } if !uniform() { t.Fatal("healthy version history requires redundant full metadata decoding") diff --git a/cmd/object-mutation.go b/cmd/object-mutation.go index 8b1bdb2f0..be187d8be 100644 --- a/cmd/object-mutation.go +++ b/cmd/object-mutation.go @@ -194,37 +194,20 @@ func (s *xlStorage) undoWrite(ctx context.Context, volume, path string, fi FileI return nil } -// All drives have replied. A uniform indexed latest version may avoid the -// second metadata decode, including healthy version histories. Conflicts retain -// the full merge. Exact FileInfo comparison also prevents the four-byte header -// signature from being treated as a collision-free identity. -func uniformLatestVersion(raw []RawFileInfo, meta []FileInfo, errs []error) bool { - if len(raw) == 0 { +// All drives have replied, and fileInfoFromRaw has already validated each raw +// buffer and selected its latest visible version. Reuse that decoded state: +// revalidating the raw history here adds work proportional to version count. +// Any missing response, logical disagreement, or history-property disagreement +// retains the full merge. Legacy objects and delete markers also use that path. +func uniformLatestVersion(meta []FileInfo, errs []error) bool { + if len(meta) == 0 { return false } - var first xlMetaV2VersionHeader - var firstVersions int - for i, r := range raw { - if errs[i] != nil || !meta[i].IsValid() || !sameFileInfoVersion(meta[0], meta[i]) { - return false - } - buf, _, err := isIndexedMetaV2(r.Buf) - if err != nil || buf == nil { - return false - } - n, hv, mv, rest, err := decodeXLHeaders(buf) - if err != nil || n < 1 || mv != xlMetaVersion { - return false - } - var h xlMetaV2VersionHeader - err = decodeVersions(rest, 1, func(_ int, hdr, _ []byte) error { _, e := h.unmarshalV(hv, hdr); return e }) - if err != nil || h.Type != ObjectType || h.FreeVersion() { - return false - } - if i == 0 { - first = h - firstVersions = n - } else if h != first || n != firstVersions || meta[i].NumVersions != meta[0].NumVersions || !meta[i].SuccessorModTime.Equal(meta[0].SuccessorModTime) { + first := meta[0] + for i, fi := range meta { + if errs[i] != nil || !fi.IsValid() || fi.XLV1 || fi.Deleted || !fi.IsLatest || fi.NumVersions < 1 || + !fi.ModTime.Equal(first.ModTime) || !sameFileInfoVersion(first, fi) || + fi.NumVersions != first.NumVersions || !fi.SuccessorModTime.Equal(first.SuccessorModTime) { return false } }