From 1865985aa12b16834bf058bf34b89b0ca058a068 Mon Sep 17 00:00:00 2001 From: Feng Ruohang Date: Sun, 25 Oct 2026 12:41:54 +0800 Subject: [PATCH] fix: separate rollback ownership from readable metadata identity Signed-off-by: Feng Ruohang --- cmd/object-mutation.go | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/cmd/object-mutation.go b/cmd/object-mutation.go index 08a31a0c2..8b1bdb2f0 100644 --- a/cmd/object-mutation.go +++ b/cmd/object-mutation.go @@ -58,7 +58,7 @@ func sameFileInfoVersion(a, b FileInfo) bool { if a.VersionID != b.VersionID || a.Deleted != b.Deleted || a.XLV1 != b.XLV1 || a.Size != b.Size || a.TransitionStatus != b.TransitionStatus || a.TransitionTier != b.TransitionTier || a.TransitionedObjName != b.TransitionedObjName || a.TransitionVersionID != b.TransitionVersionID || - !maps.Equal(a.Metadata, b.Metadata) || !bytes.Equal(a.Checksum, b.Checksum) || len(a.Parts) != len(b.Parts) { + !sameVersionMetadata(a.Metadata, b.Metadata) || !bytes.Equal(a.Checksum, b.Checksum) || len(a.Parts) != len(b.Parts) { return false } if !a.Deleted && a.Size != 0 && !a.Erasure.Equal(b.Erasure) { @@ -73,9 +73,35 @@ func sameFileInfoVersion(a, b FileInfo) bool { return true } +// The undo capability controls rollback ownership, not the logical contents. +// A partial no-op update can revoke it without changing a single public field. +func sameVersionMetadata(a, b map[string]string) bool { + if a[rollbackIDKey] == b[rollbackIDKey] { + return maps.Equal(a, b) + } + for k, v := range a { + if k != rollbackIDKey { + if other, ok := b[k]; !ok || other != v { + return false + } + } + } + for k := range b { + if k != rollbackIDKey { + if _, ok := a[k]; !ok { + return false + } + } + } + return true +} + // Legacy callers without an undo capability must match the persisted state, // rather than transient coordinator-only fields in their original FileInfo. func samePersistedVersion(current, expected FileInfo) bool { + if current.Metadata[rollbackIDKey] != expected.Metadata[rollbackIDKey] { + return false + } var meta xlMetaV2 if err := meta.AddVersion(expected); err != nil { return false