mirror of
https://github.com/pgsty/minio.git
synced 2026-11-01 13:22:02 +03:00
fix: reuse validated latest state without rescanning version history
Signed-off-by: Feng Ruohang <rh@vonng.com>
This commit is contained in:
@@ -997,7 +997,7 @@ func (er erasureObjects) getObjectFileInfo(ctx context.Context, bucket, object s
|
|||||||
rw.Lock()
|
rw.Lock()
|
||||||
// when its a versioned bucket and empty versionID - at totalResp == setDriveCount
|
// when its a versioned bucket and empty versionID - at totalResp == setDriveCount
|
||||||
// we must use rawFileInfo to resolve versions to figure out the latest version.
|
// 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,
|
fi, onlineMeta, onlineDisks, modTime, etag, err = calcQuorum(pickLatestQuorumFilesInfo(ctx,
|
||||||
rawArr, errs, bucket, object, readData, opts.InclFreeVersions))
|
rawArr, errs, bucket, object, readData, opts.InclFreeVersions))
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ func TestMutationVersionHistoryRead(t *testing.T) {
|
|||||||
}
|
}
|
||||||
meta[i], errs[i] = fileInfoFromRaw(raw[i], bucket, object, false, false)
|
meta[i], errs[i] = fileInfoFromRaw(raw[i], bucket, object, false, false)
|
||||||
}
|
}
|
||||||
return uniformLatestVersion(raw, meta, errs)
|
return uniformLatestVersion(meta, errs)
|
||||||
}
|
}
|
||||||
if !uniform() {
|
if !uniform() {
|
||||||
t.Fatal("healthy version history requires redundant full metadata decoding")
|
t.Fatal("healthy version history requires redundant full metadata decoding")
|
||||||
|
|||||||
+12
-29
@@ -194,37 +194,20 @@ func (s *xlStorage) undoWrite(ctx context.Context, volume, path string, fi FileI
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// All drives have replied. A uniform indexed latest version may avoid the
|
// All drives have replied, and fileInfoFromRaw has already validated each raw
|
||||||
// second metadata decode, including healthy version histories. Conflicts retain
|
// buffer and selected its latest visible version. Reuse that decoded state:
|
||||||
// the full merge. Exact FileInfo comparison also prevents the four-byte header
|
// revalidating the raw history here adds work proportional to version count.
|
||||||
// signature from being treated as a collision-free identity.
|
// Any missing response, logical disagreement, or history-property disagreement
|
||||||
func uniformLatestVersion(raw []RawFileInfo, meta []FileInfo, errs []error) bool {
|
// retains the full merge. Legacy objects and delete markers also use that path.
|
||||||
if len(raw) == 0 {
|
func uniformLatestVersion(meta []FileInfo, errs []error) bool {
|
||||||
|
if len(meta) == 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
var first xlMetaV2VersionHeader
|
first := meta[0]
|
||||||
var firstVersions int
|
for i, fi := range meta {
|
||||||
for i, r := range raw {
|
if errs[i] != nil || !fi.IsValid() || fi.XLV1 || fi.Deleted || !fi.IsLatest || fi.NumVersions < 1 ||
|
||||||
if errs[i] != nil || !meta[i].IsValid() || !sameFileInfoVersion(meta[0], meta[i]) {
|
!fi.ModTime.Equal(first.ModTime) || !sameFileInfoVersion(first, fi) ||
|
||||||
return false
|
fi.NumVersions != first.NumVersions || !fi.SuccessorModTime.Equal(first.SuccessorModTime) {
|
||||||
}
|
|
||||||
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) {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user