mirror of
https://github.com/minio/minio.git
synced 2025-04-07 05:10:30 -04:00
fix: readQuorum calculation when defaultParityCount is 0 (#15363)
when parity is '0' the readQuorum must be equal to the number of data disks.
This commit is contained in:
parent
8249cd4406
commit
65166e4ce4
2
Makefile
2
Makefile
@ -140,6 +140,8 @@ clean: ## cleanup all generated assets
|
|||||||
@echo "Cleaning up all the generated files"
|
@echo "Cleaning up all the generated files"
|
||||||
@find . -name '*.test' | xargs rm -fv
|
@find . -name '*.test' | xargs rm -fv
|
||||||
@find . -name '*~' | xargs rm -fv
|
@find . -name '*~' | xargs rm -fv
|
||||||
|
@find . -name '.#*#' | xargs rm -fv
|
||||||
|
@find . -name '#*#' | xargs rm -fv
|
||||||
@rm -rvf minio
|
@rm -rvf minio
|
||||||
@rm -rvf build
|
@rm -rvf build
|
||||||
@rm -rvf release
|
@rm -rvf release
|
||||||
|
@ -180,9 +180,15 @@ func listOnlineDisks(disks []StorageAPI, partsMetadata []FileInfo, errs []error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Returns the latest updated FileInfo files and error in case of failure.
|
// Returns the latest updated FileInfo files and error in case of failure.
|
||||||
func getLatestFileInfo(ctx context.Context, partsMetadata []FileInfo, errs []error) (FileInfo, error) {
|
func getLatestFileInfo(ctx context.Context, partsMetadata []FileInfo, defaultParityCount int, errs []error) (FileInfo, error) {
|
||||||
// There should be atleast half correct entries, if not return failure
|
// There should be atleast half correct entries, if not return failure
|
||||||
reducedErr := reduceReadQuorumErrs(ctx, errs, objectOpIgnoredErrs, len(partsMetadata)/2)
|
expectedRQuorum := len(partsMetadata) / 2
|
||||||
|
if defaultParityCount == 0 {
|
||||||
|
// if parity count is '0', we expected all entries to be present.
|
||||||
|
expectedRQuorum = len(partsMetadata)
|
||||||
|
}
|
||||||
|
|
||||||
|
reducedErr := reduceReadQuorumErrs(ctx, errs, objectOpIgnoredErrs, expectedRQuorum)
|
||||||
if reducedErr != nil {
|
if reducedErr != nil {
|
||||||
return FileInfo{}, reducedErr
|
return FileInfo{}, reducedErr
|
||||||
}
|
}
|
||||||
|
@ -194,7 +194,7 @@ func TestListOnlineDisks(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
partsMetadata, errs := readAllFileInfo(ctx, erasureDisks, bucket, object, "", false)
|
partsMetadata, errs := readAllFileInfo(ctx, erasureDisks, bucket, object, "", false)
|
||||||
fi, err := getLatestFileInfo(ctx, partsMetadata, errs)
|
fi, err := getLatestFileInfo(ctx, partsMetadata, z.serverPools[0].sets[0].defaultParityCount, errs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to getLatestFileInfo %v", err)
|
t.Fatalf("Failed to getLatestFileInfo %v", err)
|
||||||
}
|
}
|
||||||
@ -370,7 +370,7 @@ func TestListOnlineDisksSmallObjects(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
partsMetadata, errs := readAllFileInfo(ctx, erasureDisks, bucket, object, "", true)
|
partsMetadata, errs := readAllFileInfo(ctx, erasureDisks, bucket, object, "", true)
|
||||||
_, err = getLatestFileInfo(ctx, partsMetadata, errs)
|
_, err = getLatestFileInfo(ctx, partsMetadata, z.serverPools[0].sets[0].defaultParityCount, errs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to getLatestFileInfo %v", err)
|
t.Fatalf("Failed to getLatestFileInfo %v", err)
|
||||||
}
|
}
|
||||||
@ -429,7 +429,7 @@ func TestListOnlineDisksSmallObjects(t *testing.T) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
partsMetadata, errs = readAllFileInfo(ctx, erasureDisks, bucket, object, "", true)
|
partsMetadata, errs = readAllFileInfo(ctx, erasureDisks, bucket, object, "", true)
|
||||||
fi, err := getLatestFileInfo(ctx, partsMetadata, errs)
|
fi, err := getLatestFileInfo(ctx, partsMetadata, z.serverPools[0].sets[0].defaultParityCount, errs)
|
||||||
if !errors.Is(err, errErasureReadQuorum) {
|
if !errors.Is(err, errErasureReadQuorum) {
|
||||||
t.Fatalf("Failed to getLatestFileInfo, expected %v, got %v", errErasureReadQuorum, err)
|
t.Fatalf("Failed to getLatestFileInfo, expected %v, got %v", errErasureReadQuorum, err)
|
||||||
}
|
}
|
||||||
@ -495,7 +495,7 @@ func TestDisksWithAllParts(t *testing.T) {
|
|||||||
t.Fatalf("Failed to read xl meta data %v", err)
|
t.Fatalf("Failed to read xl meta data %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fi, err := getLatestFileInfo(ctx, partsMetadata, errs)
|
fi, err := getLatestFileInfo(ctx, partsMetadata, s.defaultParityCount, errs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to get quorum consistent fileInfo %v", err)
|
t.Fatalf("Failed to get quorum consistent fileInfo %v", err)
|
||||||
}
|
}
|
||||||
|
@ -601,7 +601,7 @@ func TestHealCorrectQuorum(t *testing.T) {
|
|||||||
erasureDisks := er.getDisks()
|
erasureDisks := er.getDisks()
|
||||||
|
|
||||||
fileInfos, errs := readAllFileInfo(ctx, erasureDisks, bucket, object, "", false)
|
fileInfos, errs := readAllFileInfo(ctx, erasureDisks, bucket, object, "", false)
|
||||||
nfi, err := getLatestFileInfo(ctx, fileInfos, errs)
|
nfi, err := getLatestFileInfo(ctx, fileInfos, er.defaultParityCount, errs)
|
||||||
if errors.Is(err, errFileNotFound) {
|
if errors.Is(err, errFileNotFound) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -628,7 +628,7 @@ func TestHealCorrectQuorum(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fileInfos, errs = readAllFileInfo(ctx, erasureDisks, minioMetaBucket, cfgFile, "", false)
|
fileInfos, errs = readAllFileInfo(ctx, erasureDisks, minioMetaBucket, cfgFile, "", false)
|
||||||
nfi, err = getLatestFileInfo(ctx, fileInfos, errs)
|
nfi, err = getLatestFileInfo(ctx, fileInfos, er.defaultParityCount, errs)
|
||||||
if errors.Is(err, errFileNotFound) {
|
if errors.Is(err, errFileNotFound) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -734,7 +734,7 @@ func TestHealObjectCorruptedPools(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fileInfos, errs := readAllFileInfo(ctx, erasureDisks, bucket, object, "", false)
|
fileInfos, errs := readAllFileInfo(ctx, erasureDisks, bucket, object, "", false)
|
||||||
fi, err := getLatestFileInfo(ctx, fileInfos, errs)
|
fi, err := getLatestFileInfo(ctx, fileInfos, er.defaultParityCount, errs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to getLatestFileInfo - %v", err)
|
t.Fatalf("Failed to getLatestFileInfo - %v", err)
|
||||||
}
|
}
|
||||||
@ -762,7 +762,7 @@ func TestHealObjectCorruptedPools(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fileInfos, errs = readAllFileInfo(ctx, erasureDisks, bucket, object, "", false)
|
fileInfos, errs = readAllFileInfo(ctx, erasureDisks, bucket, object, "", false)
|
||||||
nfi, err := getLatestFileInfo(ctx, fileInfos, errs)
|
nfi, err := getLatestFileInfo(ctx, fileInfos, er.defaultParityCount, errs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to getLatestFileInfo - %v", err)
|
t.Fatalf("Failed to getLatestFileInfo - %v", err)
|
||||||
}
|
}
|
||||||
@ -793,7 +793,7 @@ func TestHealObjectCorruptedPools(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fileInfos, errs = readAllFileInfo(ctx, erasureDisks, bucket, object, "", false)
|
fileInfos, errs = readAllFileInfo(ctx, erasureDisks, bucket, object, "", false)
|
||||||
nfi, err = getLatestFileInfo(ctx, fileInfos, errs)
|
nfi, err = getLatestFileInfo(ctx, fileInfos, er.defaultParityCount, errs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to getLatestFileInfo - %v", err)
|
t.Fatalf("Failed to getLatestFileInfo - %v", err)
|
||||||
}
|
}
|
||||||
@ -897,7 +897,7 @@ func TestHealObjectCorruptedXLMeta(t *testing.T) {
|
|||||||
|
|
||||||
// Test 1: Remove the object backend files from the first disk.
|
// Test 1: Remove the object backend files from the first disk.
|
||||||
fileInfos, errs := readAllFileInfo(ctx, erasureDisks, bucket, object, "", false)
|
fileInfos, errs := readAllFileInfo(ctx, erasureDisks, bucket, object, "", false)
|
||||||
fi, err := getLatestFileInfo(ctx, fileInfos, errs)
|
fi, err := getLatestFileInfo(ctx, fileInfos, er.defaultParityCount, errs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to getLatestFileInfo - %v", err)
|
t.Fatalf("Failed to getLatestFileInfo - %v", err)
|
||||||
}
|
}
|
||||||
@ -920,7 +920,7 @@ func TestHealObjectCorruptedXLMeta(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fileInfos, errs = readAllFileInfo(ctx, erasureDisks, bucket, object, "", false)
|
fileInfos, errs = readAllFileInfo(ctx, erasureDisks, bucket, object, "", false)
|
||||||
nfi1, err := getLatestFileInfo(ctx, fileInfos, errs)
|
nfi1, err := getLatestFileInfo(ctx, fileInfos, er.defaultParityCount, errs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to getLatestFileInfo - %v", err)
|
t.Fatalf("Failed to getLatestFileInfo - %v", err)
|
||||||
}
|
}
|
||||||
@ -943,7 +943,7 @@ func TestHealObjectCorruptedXLMeta(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fileInfos, errs = readAllFileInfo(ctx, erasureDisks, bucket, object, "", false)
|
fileInfos, errs = readAllFileInfo(ctx, erasureDisks, bucket, object, "", false)
|
||||||
nfi2, err := getLatestFileInfo(ctx, fileInfos, errs)
|
nfi2, err := getLatestFileInfo(ctx, fileInfos, er.defaultParityCount, errs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to getLatestFileInfo - %v", err)
|
t.Fatalf("Failed to getLatestFileInfo - %v", err)
|
||||||
}
|
}
|
||||||
@ -1041,7 +1041,7 @@ func TestHealObjectCorruptedParts(t *testing.T) {
|
|||||||
secondDisk := erasureDisks[1]
|
secondDisk := erasureDisks[1]
|
||||||
|
|
||||||
fileInfos, errs := readAllFileInfo(ctx, erasureDisks, bucket, object, "", false)
|
fileInfos, errs := readAllFileInfo(ctx, erasureDisks, bucket, object, "", false)
|
||||||
fi, err := getLatestFileInfo(ctx, fileInfos, errs)
|
fi, err := getLatestFileInfo(ctx, fileInfos, er.defaultParityCount, errs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to getLatestFileInfo - %v", err)
|
t.Fatalf("Failed to getLatestFileInfo - %v", err)
|
||||||
}
|
}
|
||||||
|
@ -400,17 +400,17 @@ func writeUniqueFileInfo(ctx context.Context, disks []StorageAPI, bucket, prefix
|
|||||||
// readQuorum is the min required disks to read data.
|
// readQuorum is the min required disks to read data.
|
||||||
// writeQuorum is the min required disks to write data.
|
// writeQuorum is the min required disks to write data.
|
||||||
func objectQuorumFromMeta(ctx context.Context, partsMetaData []FileInfo, errs []error, defaultParityCount int) (objectReadQuorum, objectWriteQuorum int, err error) {
|
func objectQuorumFromMeta(ctx context.Context, partsMetaData []FileInfo, errs []error, defaultParityCount int) (objectReadQuorum, objectWriteQuorum int, err error) {
|
||||||
if defaultParityCount == 0 {
|
|
||||||
return 1, 1, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the latest updated Metadata and a count of all the latest updated FileInfo(s)
|
// get the latest updated Metadata and a count of all the latest updated FileInfo(s)
|
||||||
latestFileInfo, err := getLatestFileInfo(ctx, partsMetaData, errs)
|
latestFileInfo, err := getLatestFileInfo(ctx, partsMetaData, defaultParityCount, errs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, 0, err
|
return 0, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if latestFileInfo.Deleted {
|
if latestFileInfo.Deleted {
|
||||||
|
// special case when parity is '0'
|
||||||
|
if defaultParityCount == 0 {
|
||||||
|
return len(partsMetaData), len(partsMetaData), nil
|
||||||
|
}
|
||||||
// For delete markers do not use 'defaultParityCount' as it is not expected to be the case.
|
// For delete markers do not use 'defaultParityCount' as it is not expected to be the case.
|
||||||
// Use maximum allowed read quorum instead, writeQuorum+1 is returned for compatibility sake
|
// Use maximum allowed read quorum instead, writeQuorum+1 is returned for compatibility sake
|
||||||
// but there are no callers that shall be using this.
|
// but there are no callers that shall be using this.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user