fix: scanner in healing cycle must use actual size (#16589)

This commit is contained in:
Harshavardhana 2023-02-10 06:53:03 -08:00 committed by GitHub
parent b363400587
commit 72daccd468
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 54 additions and 6 deletions

View file

@ -411,6 +411,11 @@ func (er *erasureObjects) healObject(ctx context.Context, bucket string, object
erasure.ShardFileSize(latestMeta.Parts[0].ActualSize) < smallFileThreshold)
}
result.ObjectSize, err = latestMeta.GetActualSize()
if err != nil {
return result, err
}
// Loop to find number of disks with valid data, per-drive
// data state and a list of outdated disks on which data needs
// to be healed.
@ -421,9 +426,6 @@ func (er *erasureObjects) healObject(ctx context.Context, bucket string, object
switch {
case v != nil:
driveState = madmin.DriveStateOk
// If data is sane on any one disk, we can
// extract the correct object size.
result.ObjectSize = partsMetadata[i].Size
case errs[i] == errDiskNotFound, dataErrs[i] == errDiskNotFound:
driveState = madmin.DriveStateOffline
case errs[i] == errFileNotFound, errs[i] == errFileVersionNotFound, errs[i] == errVolumeNotFound:
@ -673,9 +675,6 @@ func (er *erasureObjects) healObject(ctx context.Context, bucket string, object
})
}
// Set the size of the object in the heal result
result.ObjectSize = latestMeta.Size
return result, nil
}

View file

@ -23,15 +23,18 @@ import (
"fmt"
"net/http"
"sort"
"strconv"
"strings"
"time"
"github.com/minio/minio/internal/amztime"
"github.com/minio/minio/internal/bucket/replication"
"github.com/minio/minio/internal/crypto"
"github.com/minio/minio/internal/hash/sha256"
xhttp "github.com/minio/minio/internal/http"
"github.com/minio/minio/internal/logger"
"github.com/minio/minio/internal/sync/errgroup"
"github.com/minio/sio"
)
// Object was stored with additional erasure codes due to degraded system at upload time
@ -104,6 +107,52 @@ func (fi FileInfo) IsValid() bool {
correctIndexes)
}
func (fi FileInfo) checkMultipart() (int64, bool) {
if len(fi.Parts) == 0 {
return 0, false
}
if !crypto.IsMultiPart(fi.Metadata) {
return 0, false
}
var size int64
for _, part := range fi.Parts {
psize, err := sio.DecryptedSize(uint64(part.Size))
if err != nil {
return 0, false
}
size += int64(psize)
}
return size, len(extractETag(fi.Metadata)) != 32
}
// GetActualSize - returns the actual size of the stored object
func (fi FileInfo) GetActualSize() (int64, error) {
if _, ok := fi.Metadata[ReservedMetadataPrefix+"compression"]; ok {
sizeStr, ok := fi.Metadata[ReservedMetadataPrefix+"actual-size"]
if !ok {
return -1, errInvalidDecompressedSize
}
size, err := strconv.ParseInt(sizeStr, 10, 64)
if err != nil {
return -1, errInvalidDecompressedSize
}
return size, nil
}
if _, ok := crypto.IsEncrypted(fi.Metadata); ok {
size, ok := fi.checkMultipart()
if !ok {
size, err := sio.DecryptedSize(uint64(fi.Size))
if err != nil {
err = errObjectTampered // assign correct error type
}
return int64(size), err
}
return size, nil
}
return fi.Size, nil
}
// ToObjectInfo - Converts metadata to object info.
func (fi FileInfo) ToObjectInfo(bucket, object string, versioned bool) ObjectInfo {
object = decodeDirObject(object)