mirror of
https://github.com/minio/minio.git
synced 2025-01-11 23:13:23 -05:00
Recreate bucket metacache if corrupted (#10800)
If bucket metadata cannot be read, clean up existing and create a new.
This commit is contained in:
parent
422898d9b3
commit
fe9f23e632
@ -51,7 +51,17 @@ type bucketMetacache struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// newBucketMetacache creates a new bucketMetacache.
|
// newBucketMetacache creates a new bucketMetacache.
|
||||||
func newBucketMetacache(bucket string) *bucketMetacache {
|
// Optionally remove all existing caches.
|
||||||
|
func newBucketMetacache(bucket string, cleanup bool) *bucketMetacache {
|
||||||
|
if cleanup {
|
||||||
|
// Recursively delete all caches.
|
||||||
|
objAPI := newObjectLayerFn()
|
||||||
|
ez, ok := objAPI.(*erasureServerSets)
|
||||||
|
if ok {
|
||||||
|
ctx := context.Background()
|
||||||
|
ez.deleteAll(ctx, minioMetaBucket, metacachePrefixForID(bucket, slashSeparator))
|
||||||
|
}
|
||||||
|
}
|
||||||
return &bucketMetacache{
|
return &bucketMetacache{
|
||||||
bucket: bucket,
|
bucket: bucket,
|
||||||
caches: make(map[string]metacache, 10),
|
caches: make(map[string]metacache, 10),
|
||||||
@ -97,19 +107,26 @@ func loadBucketMetaCache(ctx context.Context, bucket string) (*bucketMetacache,
|
|||||||
} else {
|
} else {
|
||||||
logger.LogIf(ctx, err)
|
logger.LogIf(ctx, err)
|
||||||
}
|
}
|
||||||
return newBucketMetacache(bucket), err
|
if errors.Is(err, InsufficientReadQuorum{}) {
|
||||||
|
// Cache is likely lost. Clean up and return new.
|
||||||
|
return newBucketMetacache(bucket, true), nil
|
||||||
|
}
|
||||||
|
return newBucketMetacache(bucket, false), err
|
||||||
}
|
}
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
if decErr != nil {
|
if decErr != nil {
|
||||||
|
if errors.Is(err, context.Canceled) {
|
||||||
|
return newBucketMetacache(bucket, false), err
|
||||||
|
}
|
||||||
// Log the error, but assume the data is lost and return a fresh bucket.
|
// Log the error, but assume the data is lost and return a fresh bucket.
|
||||||
// Otherwise a broken cache will never recover.
|
// Otherwise a broken cache will never recover.
|
||||||
logger.LogIf(ctx, decErr)
|
logger.LogIf(ctx, decErr)
|
||||||
return newBucketMetacache(bucket), nil
|
return newBucketMetacache(bucket, true), nil
|
||||||
}
|
}
|
||||||
// Sanity check...
|
// Sanity check...
|
||||||
if meta.bucket != bucket {
|
if meta.bucket != bucket {
|
||||||
logger.Info("loadBucketMetaCache: loaded cache name mismatch, want %s, got %s. Discarding.", bucket, meta.bucket)
|
logger.Info("loadBucketMetaCache: loaded cache name mismatch, want %s, got %s. Discarding.", bucket, meta.bucket)
|
||||||
return newBucketMetacache(bucket), nil
|
return newBucketMetacache(bucket, true), nil
|
||||||
}
|
}
|
||||||
return &meta, nil
|
return &meta, nil
|
||||||
}
|
}
|
||||||
@ -393,6 +410,16 @@ func (b *bucketMetacache) deleteAll() {
|
|||||||
logger.LogIf(ctx, errors.New("bucketMetacache: expected objAPI to be *erasureZones"))
|
logger.LogIf(ctx, errors.New("bucketMetacache: expected objAPI to be *erasureZones"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
b.updated = true
|
||||||
|
if !b.transient {
|
||||||
|
// Delete all.
|
||||||
|
ez.deleteAll(ctx, minioMetaBucket, metacachePrefixForID(b.bucket, slashSeparator))
|
||||||
|
b.caches = make(map[string]metacache, 10)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transient are in different buckets.
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
for id := range b.caches {
|
for id := range b.caches {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
@ -400,9 +427,9 @@ func (b *bucketMetacache) deleteAll() {
|
|||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
ez.deleteAll(ctx, minioMetaBucket, metacachePrefixForID(cache.bucket, cache.id))
|
ez.deleteAll(ctx, minioMetaBucket, metacachePrefixForID(cache.bucket, cache.id))
|
||||||
}(b.caches[id])
|
}(b.caches[id])
|
||||||
delete(b.caches, id)
|
|
||||||
}
|
}
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
b.caches = make(map[string]metacache, 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
// deleteCache will delete a specific cache and all files related to it across the cluster.
|
// deleteCache will delete a specific cache and all files related to it across the cluster.
|
||||||
|
@ -45,7 +45,7 @@ const metacacheManagerTransientBucket = "**transient**"
|
|||||||
// initManager will start async saving the cache.
|
// initManager will start async saving the cache.
|
||||||
func (m *metacacheManager) initManager() {
|
func (m *metacacheManager) initManager() {
|
||||||
// Add a transient bucket.
|
// Add a transient bucket.
|
||||||
tb := newBucketMetacache(metacacheManagerTransientBucket)
|
tb := newBucketMetacache(metacacheManagerTransientBucket, false)
|
||||||
tb.transient = true
|
tb.transient = true
|
||||||
m.buckets[metacacheManagerTransientBucket] = tb
|
m.buckets[metacacheManagerTransientBucket] = tb
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user