mirror of
https://github.com/minio/minio.git
synced 2025-04-21 11:04:20 -04:00
fix: introduce isLeafDir in healing to fix the crash (#5920)
This PR also supports healing directories. Fixes #5917
This commit is contained in:
parent
5b74f918d4
commit
c872c30ea3
@ -153,6 +153,12 @@ func doTreeWalk(ctx context.Context, bucket, prefixDir, entryPrefixMatch, marker
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// When isleaf check is delayed, make sure that it is set correctly here.
|
||||||
|
if delayIsLeaf && isLeaf == nil {
|
||||||
|
return errInvalidArgument
|
||||||
|
}
|
||||||
|
|
||||||
// For an empty list return right here.
|
// For an empty list return right here.
|
||||||
if len(entries) == 0 {
|
if len(entries) == 0 {
|
||||||
return nil
|
return nil
|
||||||
@ -169,6 +175,7 @@ func doTreeWalk(ctx context.Context, bucket, prefixDir, entryPrefixMatch, marker
|
|||||||
if len(entries) == 0 {
|
if len(entries) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, entry := range entries {
|
for i, entry := range entries {
|
||||||
var leaf, leafDir bool
|
var leaf, leafDir bool
|
||||||
|
|
||||||
@ -187,7 +194,6 @@ func doTreeWalk(ctx context.Context, bucket, prefixDir, entryPrefixMatch, marker
|
|||||||
}
|
}
|
||||||
|
|
||||||
isDir := !leafDir && !leaf
|
isDir := !leafDir && !leaf
|
||||||
|
|
||||||
if i == 0 && markerDir == entry {
|
if i == 0 && markerDir == entry {
|
||||||
if !recursive {
|
if !recursive {
|
||||||
// Skip as the marker would already be listed in the previous listing.
|
// Skip as the marker would already be listed in the previous listing.
|
||||||
|
@ -1360,13 +1360,17 @@ func (s *xlSets) listObjectsHeal(ctx context.Context, bucket, prefix, marker, de
|
|||||||
return s.getHashedSet(entry).isObject(bucket, entry)
|
return s.getHashedSet(entry).isObject(bucket, entry)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isLeafDir := func(bucket, entry string) bool {
|
||||||
|
return s.getHashedSet(entry).isObjectDir(bucket, entry)
|
||||||
|
}
|
||||||
|
|
||||||
var setDisks = make([][]StorageAPI, len(s.sets))
|
var setDisks = make([][]StorageAPI, len(s.sets))
|
||||||
for _, set := range s.sets {
|
for _, set := range s.sets {
|
||||||
setDisks = append(setDisks, set.getLoadBalancedDisks())
|
setDisks = append(setDisks, set.getLoadBalancedDisks())
|
||||||
}
|
}
|
||||||
|
|
||||||
listDir := listDirSetsHealFactory(isLeaf, setDisks...)
|
listDir := listDirSetsHealFactory(isLeaf, setDisks...)
|
||||||
walkResultCh = startTreeWalk(ctx, bucket, prefix, marker, recursive, listDir, nil, nil, endWalkCh)
|
walkResultCh = startTreeWalk(ctx, bucket, prefix, marker, recursive, listDir, nil, isLeafDir, endWalkCh)
|
||||||
}
|
}
|
||||||
|
|
||||||
var objInfos []ObjectInfo
|
var objInfos []ObjectInfo
|
||||||
@ -1403,20 +1407,7 @@ func (s *xlSets) listObjectsHeal(ctx context.Context, bucket, prefix, marker, de
|
|||||||
result := ListObjectsInfo{IsTruncated: !eof}
|
result := ListObjectsInfo{IsTruncated: !eof}
|
||||||
for _, objInfo := range objInfos {
|
for _, objInfo := range objInfos {
|
||||||
result.NextMarker = objInfo.Name
|
result.NextMarker = objInfo.Name
|
||||||
if objInfo.IsDir {
|
result.Objects = append(result.Objects, objInfo)
|
||||||
result.Prefixes = append(result.Prefixes, objInfo.Name)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add each object seen to the result - objects are
|
|
||||||
// checked for healing later.
|
|
||||||
result.Objects = append(result.Objects, ObjectInfo{
|
|
||||||
Bucket: bucket,
|
|
||||||
Name: objInfo.Name,
|
|
||||||
ModTime: objInfo.ModTime,
|
|
||||||
Size: objInfo.Size,
|
|
||||||
IsDir: false,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
@ -539,12 +539,74 @@ func healObject(ctx context.Context, storageDisks []StorageAPI, bucket string, o
|
|||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// healObjectDir - heals object directory specifically, this special call
|
||||||
|
// is needed since we do not have a special backend format for directories.
|
||||||
|
func (xl xlObjects) healObjectDir(ctx context.Context, bucket, object string, dryRun bool) (hr madmin.HealResultItem, err error) {
|
||||||
|
storageDisks := xl.getDisks()
|
||||||
|
|
||||||
|
// Initialize heal result object
|
||||||
|
hr = madmin.HealResultItem{
|
||||||
|
Type: madmin.HealItemObject,
|
||||||
|
Bucket: bucket,
|
||||||
|
Object: object,
|
||||||
|
DiskCount: len(storageDisks),
|
||||||
|
ParityBlocks: len(storageDisks) / 2,
|
||||||
|
DataBlocks: len(storageDisks) / 2,
|
||||||
|
ObjectSize: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare object creation in all disks
|
||||||
|
for _, disk := range storageDisks {
|
||||||
|
if disk == nil {
|
||||||
|
hr.Before.Drives = append(hr.Before.Drives, madmin.HealDriveInfo{
|
||||||
|
UUID: "",
|
||||||
|
State: madmin.DriveStateOffline,
|
||||||
|
})
|
||||||
|
hr.After.Drives = append(hr.After.Drives, madmin.HealDriveInfo{
|
||||||
|
UUID: "",
|
||||||
|
State: madmin.DriveStateMissing,
|
||||||
|
})
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
drive := disk.String()
|
||||||
|
hr.Before.Drives = append(hr.Before.Drives, madmin.HealDriveInfo{
|
||||||
|
UUID: "",
|
||||||
|
Endpoint: drive,
|
||||||
|
State: madmin.DriveStateMissing,
|
||||||
|
})
|
||||||
|
hr.After.Drives = append(hr.After.Drives, madmin.HealDriveInfo{
|
||||||
|
UUID: "",
|
||||||
|
Endpoint: drive,
|
||||||
|
State: madmin.DriveStateMissing,
|
||||||
|
})
|
||||||
|
|
||||||
|
if !dryRun {
|
||||||
|
if err := disk.MakeVol(pathJoin(bucket, object)); err != nil && err != errVolumeExists {
|
||||||
|
return hr, toObjectErr(err, bucket, object)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, v := range hr.Before.Drives {
|
||||||
|
if v.Endpoint == drive {
|
||||||
|
hr.After.Drives[i].State = madmin.DriveStateOk
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hr, nil
|
||||||
|
}
|
||||||
|
|
||||||
// HealObject - heal the given object.
|
// HealObject - heal the given object.
|
||||||
//
|
//
|
||||||
// FIXME: If an object object was deleted and one disk was down,
|
// FIXME: If an object object was deleted and one disk was down,
|
||||||
// and later the disk comes back up again, heal on the object
|
// and later the disk comes back up again, heal on the object
|
||||||
// should delete it.
|
// should delete it.
|
||||||
func (xl xlObjects) HealObject(ctx context.Context, bucket, object string, dryRun bool) (hr madmin.HealResultItem, err error) {
|
func (xl xlObjects) HealObject(ctx context.Context, bucket, object string, dryRun bool) (hr madmin.HealResultItem, err error) {
|
||||||
|
// Healing directories handle it separately.
|
||||||
|
if hasSuffix(object, slashSeparator) {
|
||||||
|
return xl.healObjectDir(ctx, bucket, object, dryRun)
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: Metadata is read again in the healObject() call below.
|
// FIXME: Metadata is read again in the healObject() call below.
|
||||||
// Read metadata files from all the disks
|
// Read metadata files from all the disks
|
||||||
partsMetadata, errs := readAllXLMetadata(ctx, xl.getDisks(), bucket, object)
|
partsMetadata, errs := readAllXLMetadata(ctx, xl.getDisks(), bucket, object)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user