2024-04-08 17:22:13 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// Copyright (c) 2015-2024 MinIO, Inc.
 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-19 03:41:13 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								//
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// This file is part of MinIO Object Storage stack
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// This program is free software: you can redistribute it and/or modify
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// it under the terms of the GNU Affero General Public License as published by
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// the Free Software Foundation, either version 3 of the License, or
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// (at your option) any later version.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// This program is distributed in the hope that it will be useful
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// but WITHOUT ANY WARRANTY; without even the implied warranty of
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// GNU Affero General Public License for more details.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// You should have received a copy of the GNU Affero General Public License
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 01:27:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								package  cmd 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								import  ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									"context" 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-23 01:49:30 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"errors" 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-05 06:36:23 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"fmt" 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-08 17:22:13 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"math/rand" 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-12 05:48:54 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"runtime" 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-05 06:36:23 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"sort" 
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 01:27:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
									"time" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-20 00:46:47 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"github.com/dustin/go-humanize" 
							 
						 
					
						
							
								
									
										
										
										
											2023-06-20 08:53:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"github.com/minio/madmin-go/v3" 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-26 05:55:41 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"github.com/minio/minio/internal/bucket/lifecycle" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									objectlock  "github.com/minio/minio/internal/bucket/object/lock" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									"github.com/minio/minio/internal/bucket/replication" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									"github.com/minio/minio/internal/bucket/versioning" 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-02 05:59:40 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"github.com/minio/minio/internal/color" 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-23 23:50:35 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"github.com/minio/minio/internal/config/storageclass" 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-02 05:59:40 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"github.com/minio/minio/internal/logger" 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-25 07:05:23 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"github.com/minio/pkg/v3/console" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									"github.com/minio/pkg/v3/wildcard" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									"github.com/minio/pkg/v3/workers" 
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 01:27:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								const  ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									bgHealingUUID  =  "0000-0000-0000-0000" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// NewBgHealSequence creates a background healing sequence
 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-27 07:11:42 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// operation which scans all objects and heal them.
 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-30 04:07:26 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  newBgHealSequence ( )  * healSequence  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 01:27:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
									reqInfo  :=  & logger . ReqInfo { API :  "BackgroundHeal" } 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-04 13:35:40 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									ctx ,  cancelCtx  :=  context . WithCancel ( logger . SetReqInfo ( GlobalContext ,  reqInfo ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 01:27:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									hs  :=  madmin . HealOpts { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// Remove objects that do not have read-quorum
 
							 
						 
					
						
							
								
									
										
										
										
											2022-04-07 23:10:40 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										Remove :  healDeleteDangling , 
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 01:27:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									return  & healSequence { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										startTime :    UTCNow ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										clientToken :  bgHealingUUID , 
							 
						 
					
						
							
								
									
										
										
										
											2020-08-08 10:43:06 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										// run-background heal with reserved bucket
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										bucket :    minioReservedBucket , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										settings :  hs , 
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 01:27:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
										currentStatus :  healSequenceStatus { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											Summary :       healNotStartedStatus , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											HealSettings :  hs , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} , 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-04 13:35:40 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										cancelCtx :           cancelCtx , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										ctx :                 ctx , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										reportProgress :      false , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										scannedItemsMap :     make ( map [ madmin . HealItemType ] int64 ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										healedItemsMap :      make ( map [ madmin . HealItemType ] int64 ) , 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-10 02:04:41 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										healFailedItemsMap :  make ( map [ madmin . HealItemType ] int64 ) , 
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 01:27:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-01-17 07:32:00 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// getLocalBackgroundHealStatus will return the heal status of the local node
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  getLocalBackgroundHealStatus ( ctx  context . Context ,  o  ObjectLayer )  ( madmin . BgHealState ,  bool )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-09-11 00:16:26 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  globalBackgroundHealState  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  madmin . BgHealState { } ,  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-09-25 06:36:47 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 01:27:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
									bgSeq ,  ok  :=  globalBackgroundHealState . getHealSequenceByToken ( bgHealingUUID ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  ! ok  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-08-08 10:43:06 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return  madmin . BgHealState { } ,  false 
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 01:27:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-07-16 13:32:06 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									status  :=  madmin . BgHealState { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										ScannedItemsCount :  bgSeq . getScannedItemsCount ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-03 01:15:06 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									healDisksMap  :=  map [ string ] struct { } { } 
							 
						 
					
						
							
								
									
										
										
										
											2020-09-25 06:36:47 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									for  _ ,  ep  :=  range  getLocalDisksToHeal ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										healDisksMap [ ep . String ( ) ]  =  struct { } { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-05 06:36:23 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  o  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										healing  :=  globalBackgroundHealState . getLocalHealingDisks ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										for  _ ,  disk  :=  range  healing  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											status . HealDisks  =  append ( status . HealDisks ,  disk . Endpoint ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-09-25 06:36:47 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-05 06:36:23 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  status ,  true 
							 
						 
					
						
							
								
									
										
										
										
											2020-09-05 08:09:02 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-12-22 08:56:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									si  :=  o . LocalStorageInfo ( ctx ,  true ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-05 06:36:23 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									indexed  :=  make ( map [ string ] [ ] madmin . Disk ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									for  _ ,  disk  :=  range  si . Disks  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										setIdx  :=  fmt . Sprintf ( "%d-%d" ,  disk . PoolIndex ,  disk . SetIndex ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										indexed [ setIdx ]  =  append ( indexed [ setIdx ] ,  disk ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-08-08 04:22:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-05 06:36:23 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									for  id ,  disks  :=  range  indexed  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										ss  :=  madmin . SetStatus { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											ID :         id , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											SetIndex :   disks [ 0 ] . SetIndex , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											PoolIndex :  disks [ 0 ] . PoolIndex , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										for  _ ,  disk  :=  range  disks  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											ss . Disks  =  append ( ss . Disks ,  disk ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											if  disk . Healing  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												ss . HealStatus  =  "Healing" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												ss . HealPriority  =  "high" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												status . HealDisks  =  append ( status . HealDisks ,  disk . Endpoint ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										sortDisks ( ss . Disks ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										status . Sets  =  append ( status . Sets ,  ss ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									sort . Slice ( status . Sets ,  func ( i ,  j  int )  bool  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  status . Sets [ i ] . ID  <  status . Sets [ j ] . ID 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-08-23 23:50:35 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									backendInfo  :=  o . BackendInfo ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									status . SCParity  =  make ( map [ string ] int ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									status . SCParity [ storageclass . STANDARD ]  =  backendInfo . StandardSCParity 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									status . SCParity [ storageclass . RRS ]  =  backendInfo . RRSCParity 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-05 06:36:23 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									return  status ,  true 
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 01:27:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-05-10 01:15:03 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								type  healEntryResult  struct  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									bytes      uint64 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									success    bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									skipped    bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									entryDone  bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									name       string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-12-14 03:57:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// healErasureSet lists and heals all objects in a specific erasure set
 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-20 00:46:47 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( er  * erasureObjects )  healErasureSet ( ctx  context . Context ,  buckets  [ ] string ,  tracker  * healingTracker )  error  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-04-07 23:10:40 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									scanMode  :=  madmin . HealNormalScan 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-26 08:46:20 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-12-16 01:18:09 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// Make sure to copy since `buckets slice`
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// is modified in place by tracker.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									healBuckets  :=  make ( [ ] string ,  len ( buckets ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									copy ( healBuckets ,  buckets ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-01-10 12:34:04 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									objAPI  :=  newObjectLayerFn ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  objAPI  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  errServerNotInitialized 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-06-21 22:53:55 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									for  _ ,  bucket  :=  range  healBuckets  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-17 22:29:18 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										_ ,  err  :=  objAPI . HealBucket ( ctx ,  bucket ,  madmin . HealOpts { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											Recreate :  true , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											ScanMode :  scanMode , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-21 22:53:55 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// Log bucket healing error if any, we shall retry again.
 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-04 20:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											healingLogIf ( ctx ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-21 22:53:55 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-01-26 04:45:46 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									info ,  err  :=  tracker . disk . DiskInfo ( ctx ,  DiskInfoOptions { } ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-12 05:48:54 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  fmt . Errorf ( "unable to get disk information before healing it: %w" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									var  numHealers  uint64 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  numCores  :=  uint64 ( runtime . GOMAXPROCS ( 0 ) ) ;  info . NRRequests  >  numCores  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										numHealers  =  numCores  /  4 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										numHealers  =  info . NRRequests  /  4 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  numHealers  <  4  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										numHealers  =  4 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// allow overriding this value as well..
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  v  :=  globalHealConfig . GetWorkers ( ) ;  v  >  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										numHealers  =  uint64 ( v ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-04-04 20:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									healingLogEvent ( ctx ,  fmt . Sprintf ( "Healing drive '%s' - use %d parallel workers." ,  tracker . disk . String ( ) ,  numHealers ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-12 05:48:54 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									jt ,  _  :=  workers . New ( int ( numHealers ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-05-10 01:15:03 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									healEntryDone  :=  func ( name  string )  healEntryResult  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  healEntryResult { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											entryDone :  true , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											name :       name , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									healEntrySuccess  :=  func ( sz  uint64 )  healEntryResult  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  healEntryResult { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											bytes :    sz , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											success :  true , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									healEntryFailure  :=  func ( sz  uint64 )  healEntryResult  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  healEntryResult { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											bytes :  sz , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									healEntrySkipped  :=  func ( sz  uint64 )  healEntryResult  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  healEntryResult { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											bytes :    sz , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											skipped :  true , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// Collect updates to tracker from concurrent healEntry calls
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									results  :=  make ( chan  healEntryResult ,  1000 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									defer  close ( results ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									go  func ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										for  res  :=  range  results  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											if  res . entryDone  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												tracker . setObject ( res . name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												if  time . Since ( tracker . getLastUpdate ( ) )  >  time . Minute  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
													healingLogIf ( ctx ,  tracker . update ( ctx ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											tracker . updateProgress ( res . success ,  res . skipped ,  res . bytes ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-20 00:46:47 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									var  retErr  error 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-10 01:15:03 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 01:27:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
									// Heal all buckets with all objects
 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-16 01:18:09 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									for  _ ,  bucket  :=  range  healBuckets  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-20 00:46:47 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  tracker . isHealed ( bucket )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-05 06:36:23 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-10 01:15:03 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-05 06:36:23 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										var  forwardTo  string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// If we resume to the same bucket, forward to last known item.
 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-10 01:15:03 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										b  :=  tracker . getBucket ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  b  ==  bucket  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											forwardTo  =  tracker . getObject ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  b  !=  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// Reset to where last bucket ended if resuming.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											tracker . resume ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-05 06:36:23 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-19 05:49:56 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										tracker . setObject ( "" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										tracker . setBucket ( bucket ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-21 22:53:55 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										// Heal current bucket again in case if it is failed
 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-10 03:51:47 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										// in the beginning of erasure set healing
 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-10 12:34:04 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  _ ,  err  :=  objAPI . HealBucket ( ctx ,  bucket ,  madmin . HealOpts { 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-17 22:29:18 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											Recreate :  true , 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-26 08:46:20 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											ScanMode :  scanMode , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-08 17:22:13 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											// Set this such that when we return this function
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// we let the caller retry this disk again for the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// buckets that failed healing.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											retErr  =  err 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-04 20:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											healingLogIf ( ctx ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-20 00:46:47 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											continue 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-02 03:14:00 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 01:27:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-04-26 05:55:41 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										var  ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											vc    * versioning . Versioning 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											lc    * lifecycle . Lifecycle 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											lr    objectlock . Retention 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											rcfg  * replication . Config 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  ! isMinioMetaBucketName ( bucket )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											vc ,  err  =  globalBucketVersioningSys . Get ( bucket ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												retErr  =  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												healingLogIf ( ctx ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// Check if the current bucket has a configured lifecycle policy
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											lc ,  err  =  globalLifecycleSys . Get ( bucket ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											if  err  !=  nil  &&  ! errors . Is ( err ,  BucketLifecycleNotFound { Bucket :  bucket } )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												retErr  =  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												healingLogIf ( ctx ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// Check if bucket is object locked.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											lr ,  err  =  globalBucketObjectLockSys . Get ( bucket ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												retErr  =  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												healingLogIf ( ctx ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											rcfg ,  err  =  getReplicationConfig ( ctx ,  bucket ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												retErr  =  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												healingLogIf ( ctx ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-23 01:49:30 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-01 23:56:24 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-01-19 18:40:52 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  serverDebugLog  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-05 07:10:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											console . Debugf ( color . Green ( "healDrive:" ) + " healing bucket %s content on %s erasure set\n" , 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-19 05:49:56 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												bucket ,  humanize . Ordinal ( er . setIndex + 1 ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-19 18:40:52 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-04-26 14:32:14 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										disks ,  _ ,  healing  :=  er . getOnlineDisksWithHealingAndInfo ( true ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  len ( disks )  ==  healing  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// All drives in this erasure set were reformatted for some reasons, abort healing and mark it as successful
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											healingLogIf ( ctx ,  errors . New ( "all drives are in healing state, aborting.." ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										disks  =  disks [ : len ( disks ) - healing ]  // healing drives are always at the end of the list
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  len ( disks )  <  er . setDriveCount / 2  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											return  fmt . Errorf ( "not enough drives (found=%d, healing=%d, total=%d) are available to heal `%s`" ,  len ( disks ) ,  healing ,  er . setDriveCount ,  tracker . disk . String ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-10 08:09:19 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-07 01:25:48 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-04-08 17:22:13 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										rand . Shuffle ( len ( disks ) ,  func ( i ,  j  int )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											disks [ i ] ,  disks [ j ]  =  disks [ j ] ,  disks [ i ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										expectedDisks  :=  len ( disks ) / 2  +  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										fallbackDisks  :=  disks [ expectedDisks : ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										disks  =  disks [ : expectedDisks ] 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-07 01:25:48 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-12-01 23:56:24 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										filterLifecycle  :=  func ( bucket ,  object  string ,  fi  FileInfo )  bool  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											if  lc  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												return  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											versioned  :=  vc  !=  nil  &&  vc . Versioned ( object ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											objInfo  :=  fi . ToObjectInfo ( bucket ,  object ,  versioned ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											evt  :=  evalActionFromLifecycle ( ctx ,  * lc ,  lr ,  rcfg ,  objInfo ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											switch  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											case  evt . Action . DeleteRestored ( ) :  // if restored copy has expired,delete it synchronously
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												applyExpiryOnTransitionedObject ( ctx ,  newObjectLayerFn ( ) ,  objInfo ,  evt ,  lcEventSrc_Heal ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												return  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											case  evt . Action . Delete ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												globalExpiryState . enqueueByDays ( objInfo ,  evt ,  lcEventSrc_Heal ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												return  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												return  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-08-10 03:51:47 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										send  :=  func ( result  healEntryResult )  bool  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											select  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											case  <- ctx . Done ( ) : 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-29 01:05:40 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												if  ! contextCanceled ( ctx )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-04 20:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
													healingLogIf ( ctx ,  ctx . Err ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-29 01:05:40 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												} 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-10 03:51:47 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												return  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											case  results  <-  result : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												return  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-09-07 23:47:21 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										// Note: updates from healEntry to tracker must be sent on results channel.
 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-27 20:55:32 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										healEntry  :=  func ( bucket  string ,  entry  metaCacheEntry )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-12 05:48:54 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											defer  jt . Give ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 13:22:17 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											if  entry . name  ==  ""  &&  len ( entry . metadata )  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												// ignore entries that don't have metadata.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-19 03:06:54 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											if  entry . isDir ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 13:22:17 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												// ignore healing entry.name's with `/` suffix.
 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-19 03:06:54 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												return 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-10 08:09:19 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-27 20:55:32 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-08 01:38:31 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											// We might land at .metacache, .trash, .multipart
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// no need to heal them skip, only when bucket
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// is '.minio.sys'
 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-20 00:46:47 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											if  bucket  ==  minioMetaBucket  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-08 01:38:31 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												if  wildcard . Match ( "buckets/*/.metacache/*" ,  entry . name )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
													return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												if  wildcard . Match ( "tmp/.trash/*" ,  entry . name )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
													return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												if  wildcard . Match ( "multipart/*" ,  entry . name )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
													return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-27 11:32:58 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-12 05:48:54 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											// erasureObjects layer needs object names to be encoded
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											encodedEntryName  :=  encodeDirObject ( entry . name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-09-07 23:47:21 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											var  result  healEntryResult 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-20 00:46:47 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											fivs ,  err  :=  entry . fileInfoVersions ( bucket ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-19 03:06:54 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-10 01:15:03 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												res ,  err  :=  er . HealObject ( ctx ,  bucket ,  encodedEntryName ,  "" , 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-12 05:48:54 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
													madmin . HealOpts { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
														ScanMode :  scanMode , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
														Remove :    healDeleteDangling , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
													} ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-20 00:46:47 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-11 05:39:48 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
													if  isErrObjectNotFound ( err )  ||  isErrVersionNotFound ( err )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-27 20:55:32 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
														// queueing happens across namespace, ignore
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
														// objects that are not found.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
														return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
													} 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-07 23:47:21 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
													result  =  healEntryFailure ( 0 ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-04 20:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
													healingLogIf ( ctx ,  fmt . Errorf ( "unable to heal object %s/%s: %w" ,  bucket ,  entry . name ,  err ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-20 00:46:47 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-10 01:15:03 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
													result  =  healEntrySuccess ( uint64 ( res . ObjectSize ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-20 00:46:47 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												} 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-07 23:47:21 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-08-10 03:51:47 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												send ( result ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-19 03:06:54 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-26 08:46:20 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-27 20:55:32 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											var  versionNotFound  int 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-19 03:06:54 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											for  _ ,  version  :=  range  fivs . Versions  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-01 23:56:24 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												// Ignore a version with a modtime newer than healing start time.
 
							 
						 
					
						
							
								
									
										
										
										
											2023-06-01 04:10:45 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												if  version . ModTime . After ( tracker . Started )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
													continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												} 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-01 23:56:24 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												// Apply lifecycle rules on the objects that are expired.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												if  filterLifecycle ( bucket ,  version . Name ,  version )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
													versionNotFound ++ 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-29 01:05:40 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
													if  ! send ( healEntrySkipped ( uint64 ( version . Size ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
														return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
													} 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-01 23:56:24 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
													continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-05-10 01:15:03 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												res ,  err  :=  er . HealObject ( ctx ,  bucket ,  encodedEntryName , 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-12 05:48:54 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
													version . VersionID ,  madmin . HealOpts { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
														ScanMode :  scanMode , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
														Remove :    healDeleteDangling , 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-10 01:15:03 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
													} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-11 05:39:48 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
													if  isErrObjectNotFound ( err )  ||  isErrVersionNotFound ( err )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-27 20:55:32 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
														// queueing happens across namespace, ignore
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
														// objects that are not found.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
														versionNotFound ++ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
														continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
													} 
							 
						 
					
						
							
								
									
										
										
										
											2021-09-03 11:56:13 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
													// If not deleted, assume they failed.
 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-07 23:47:21 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
													result  =  healEntryFailure ( uint64 ( version . Size ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 13:22:17 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
													if  version . VersionID  !=  ""  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-04 20:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
														healingLogIf ( ctx ,  fmt . Errorf ( "unable to heal object %s/%s-v(%s): %w" ,  bucket ,  version . Name ,  version . VersionID ,  err ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 13:22:17 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
													}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-04 20:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
														healingLogIf ( ctx ,  fmt . Errorf ( "unable to heal object %s/%s: %w" ,  bucket ,  version . Name ,  err ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 13:22:17 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
													} 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-05 06:36:23 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-10 01:15:03 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
													result  =  healEntrySuccess ( uint64 ( res . ObjectSize ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-13 11:04:01 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												} 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-07 23:47:21 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-08-10 03:51:47 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												if  ! send ( result )  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-07 23:47:21 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
													return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												} 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-02 03:14:00 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-10 01:15:03 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-10-11 05:39:48 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											// All versions resulted in 'ObjectNotFound/VersionNotFound'
 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-27 20:55:32 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											if  versionNotFound  ==  len ( fivs . Versions )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-10 01:15:03 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											send ( healEntryDone ( entry . name ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-26 08:46:20 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// Wait and proceed if there are active requests
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											waitForLowHTTPReq ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 01:27:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-07 01:25:48 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// How to resolve partial results.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										resolver  :=  metadataResolutionParams { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											dirQuorum :  1 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											objQuorum :  1 , 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-26 14:32:14 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											bucket :     bucket , 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-07 01:25:48 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-04-23 01:49:30 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										err  =  listPathRaw ( ctx ,  listPathRawOptions { 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-19 03:06:54 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											disks :           disks , 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-08 17:22:13 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											fallbackDisks :   fallbackDisks , 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-26 14:32:14 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											bucket :          bucket , 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-19 03:06:54 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											recursive :       true , 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-05 06:36:23 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											forwardTo :       forwardTo , 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-19 03:06:54 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											minDisks :        1 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											reportNotFound :  false , 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-26 04:07:15 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											agreed :  func ( entry  metaCacheEntry )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-12 05:48:54 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												jt . Take ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-26 14:32:14 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												go  healEntry ( bucket ,  entry ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-26 04:07:15 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											} , 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-08 04:45:34 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											partial :  func ( entries  metaCacheEntries ,  _  [ ] error )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-07 01:25:48 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												entry ,  ok  :=  entries . resolve ( & resolver ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-27 11:32:58 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												if  ! ok  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-18 15:03:17 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
													// check if we can get one entry at least
 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-27 11:32:58 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
													// proceed to heal nonetheless.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
													entry ,  _  =  entries . firstFound ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-19 03:06:54 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												} 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-12 05:48:54 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												jt . Take ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-26 14:32:14 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												go  healEntry ( bucket ,  * entry ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-19 03:06:54 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											finished :  nil , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-12 05:48:54 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										jt . Wait ( )  // synchronize all the concurrent heal jobs
 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 03:14:44 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-20 00:46:47 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											// Set this such that when we return this function
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// we let the caller retry this disk again for the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// buckets it failed to list.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											retErr  =  err 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-17 22:29:18 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											healingLogIf ( ctx ,  fmt . Errorf ( "listing failed with: %v on bucket: %v" ,  err ,  bucket ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-20 00:46:47 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											continue 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 03:14:44 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-05 06:36:23 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										select  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// If context is canceled don't mark as done...
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										case  <- ctx . Done ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											return  ctx . Err ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										default : 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-20 00:46:47 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											tracker . bucketDone ( bucket ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-04 20:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											healingLogIf ( ctx ,  tracker . update ( ctx ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-05 06:36:23 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 01:27:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-19 05:49:56 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									tracker . setObject ( "" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									tracker . setBucket ( "" ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 01:27:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-05-31 22:48:50 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  retErr  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  retErr 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// Last sanity check
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  len ( tracker . QueuedBuckets )  >  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  fmt . Errorf ( "not all buckets were healed: %v" ,  tracker . QueuedBuckets ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									return  nil 
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 01:27:49 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-04-19 22:47:42 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  healBucket ( bucket  string ,  scan  madmin . HealScanMode )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// Get background heal sequence to send elements to heal
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									bgSeq ,  ok  :=  globalBackgroundHealState . getHealSequenceByToken ( bgHealingUUID ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  bgSeq . queueHealTask ( healSource { bucket :  bucket } ,  madmin . HealItemBucket ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-01-19 16:54:22 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// healObject sends the given object/version to the background healing workers
 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-19 22:47:42 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  healObject ( bucket ,  object ,  versionID  string ,  scan  madmin . HealScanMode )  error  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-02 03:14:00 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// Get background heal sequence to send elements to heal
 
							 
						 
					
						
							
								
									
										
										
										
											2020-08-08 10:43:06 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									bgSeq ,  ok  :=  globalBackgroundHealState . getHealSequenceByToken ( bgHealingUUID ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-27 05:06:04 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  ok  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-24 01:15:52 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return  bgSeq . healObject ( bucket ,  object ,  versionID ,  scan ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-02 03:14:00 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-19 22:47:42 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									return  nil 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-02 03:14:00 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								}