mirror of
https://github.com/pgsty/minio.git
synced 2026-07-28 00:16:18 +03:00
verify RenameData() versions to be consistent (#15649)
xl.meta gets written and never rolled back, however we definitely need to validate the state that is persisted on the disk, if there are inconsistencies - more than write quorum we should return an error to the client - if write quorum was achieved however there are inconsistent xl.meta's we should simply trigger an MRF on them
This commit is contained in:
+26
-3
@@ -712,6 +712,8 @@ func renameData(ctx context.Context, disks []StorageAPI, srcBucket, srcEntry str
|
||||
for index := range disks {
|
||||
metadata[index].SetTierFreeVersionID(fvID)
|
||||
}
|
||||
|
||||
diskVersions := make([]uint64, len(disks))
|
||||
// Rename file on all underlying storage disks.
|
||||
for index := range disks {
|
||||
index := index
|
||||
@@ -719,6 +721,7 @@ func renameData(ctx context.Context, disks []StorageAPI, srcBucket, srcEntry str
|
||||
if disks[index] == nil {
|
||||
return errDiskNotFound
|
||||
}
|
||||
|
||||
// Pick one FileInfo for a disk at index.
|
||||
fi := metadata[index]
|
||||
// Assign index when index is initialized
|
||||
@@ -726,16 +729,36 @@ func renameData(ctx context.Context, disks []StorageAPI, srcBucket, srcEntry str
|
||||
fi.Erasure.Index = index + 1
|
||||
}
|
||||
|
||||
if fi.IsValid() {
|
||||
return disks[index].RenameData(ctx, srcBucket, srcEntry, fi, dstBucket, dstEntry)
|
||||
if !fi.IsValid() {
|
||||
return errFileCorrupt
|
||||
}
|
||||
return errFileCorrupt
|
||||
sign, err := disks[index].RenameData(ctx, srcBucket, srcEntry, fi, dstBucket, dstEntry)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
diskVersions[index] = sign
|
||||
return nil
|
||||
}, index)
|
||||
}
|
||||
|
||||
// Wait for all renames to finish.
|
||||
errs := g.Wait()
|
||||
|
||||
versions := reduceCommonVersions(diskVersions, writeQuorum)
|
||||
if versions == 0 {
|
||||
err := reduceWriteQuorumErrs(ctx, errs, objectOpIgnoredErrs, writeQuorum)
|
||||
if err == nil {
|
||||
err = errErasureWriteQuorum
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for index, dversions := range diskVersions {
|
||||
if versions != dversions {
|
||||
errs[index] = errFileCorrupt
|
||||
}
|
||||
}
|
||||
|
||||
// We can safely allow RenameData errors up to len(er.getDisks()) - writeQuorum
|
||||
// otherwise return failure. Cleanup successful renames.
|
||||
err := reduceWriteQuorumErrs(ctx, errs, objectOpIgnoredErrs, writeQuorum)
|
||||
|
||||
Reference in New Issue
Block a user