2016-05-05 03:18:20 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								/ *  
						 
					
						
							
								
									
										
										
										
											2019-04-10 02:39:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  MinIO  Cloud  Storage ,  ( C )  2016 ,  2017 ,  2018  MinIO ,  Inc . 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-05 03:18:20 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Licensed  under  the  Apache  License ,  Version  2.0  ( the  "License" ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  you  may  not  use  this  file  except  in  compliance  with  the  License . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  You  may  obtain  a  copy  of  the  License  at 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *      http : //www.apache.org/licenses/LICENSE-2.0
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Unless  required  by  applicable  law  or  agreed  to  in  writing ,  software 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  distributed  under  the  License  is  distributed  on  an  "AS IS"  BASIS , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  WITHOUT  WARRANTIES  OR  CONDITIONS  OF  ANY  KIND ,  either  express  or  implied . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  See  the  License  for  the  specific  language  governing  permissions  and 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  limitations  under  the  License . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * / 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-08-19 07:23:42 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								package  cmd  
						 
					
						
							
								
									
										
										
										
											2016-05-05 03:18:20 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-05-07 15:59:43 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								import  (  
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"context" 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-07 15:59:43 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"encoding/json" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"fmt" 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"io/ioutil" 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-19 11:17:35 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"reflect" 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-03 07:34:15 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"sync" 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"encoding/hex" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-21 10:42:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									humanize  "github.com/dustin/go-humanize" 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-19 11:17:35 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/minio/minio/cmd/logger" 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-21 10:42:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									sha256  "github.com/minio/sha256-simd" 
							 
						 
					
						
							
								
									
										
										
										
											2017-06-13 08:40:28 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								const  (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Represents XL backend.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									formatBackendXL  =  "xl" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// formatXLV1.XL.Version - version '1'.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-09 06:30:55 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									formatXLVersionV1  =  "1" 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// formatXLV2.XL.Version - version '2'.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									formatXLVersionV2  =  "2" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-03-16 04:55:23 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// formatXLV3.XL.Version - version '3'.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									formatXLVersionV3  =  "3" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Distribution algorithm used.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									formatXLVersionV2DistributionAlgo  =  "CRCMOD" 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-09 06:30:55 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
									
										
										
										
											2017-06-13 08:40:28 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// Offline disk UUID represents an offline disk.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								const  offlineDiskUUID  =  "ffffffff-ffff-ffff-ffff-ffffffffffff"  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Healing is only supported for the list of errors mentioned here.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								var  formatHealErrors  =  map [ error ] struct { } {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									errUnformattedDisk :  { } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									errDiskNotFound :     { } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// List of errors considered critical for disk formatting.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								var  formatCriticalErrors  =  map [ error ] struct { } {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									errCorruptedFormat :  { } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									errFaultyDisk :       { } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Used to detect the version of "xl" format.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  formatXLVersionDetect  struct  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									XL  struct  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Version  string  ` json:"version" ` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  ` json:"xl" ` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Represents the V1 backend disk structure version
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// under `.minio.sys` and actual data namespace.
  
						 
					
						
							
								
									
										
										
										
											2018-01-09 06:30:55 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								// formatXLV1 - structure holds format config version '1'.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  formatXLV1  struct  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									formatMetaV1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									XL  struct  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Version  string  ` json:"version" `  // Version of 'xl' format.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Disk     string  ` json:"disk" `     // Disk field carries assigned disk uuid.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// JBOD field carries the input disk order generated the first
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// time when fresh disks were supplied.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										JBOD  [ ] string  ` json:"jbod" ` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  ` json:"xl" `  // XL field holds xl format.
 
							 
						 
					
						
							
								
									
										
										
										
											2017-06-13 08:40:28 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// Represents the V2 backend disk structure version
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// under `.minio.sys` and actual data namespace.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// formatXLV2 - structure holds format config version '2'.
  
						 
					
						
							
								
									
										
										
										
											2018-07-17 11:26:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// The V2 format to support "large bucket" support where a bucket
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// can span multiple erasure sets.
  
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								type  formatXLV2  struct  {  
						 
					
						
							
								
									
										
										
										
											2018-07-17 11:26:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									formatMetaV1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									XL  struct  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										Version  string  ` json:"version" `  // Version of 'xl' format.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										This     string  ` json:"this" `     // This field carries assigned disk uuid.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Sets field carries the input disk order generated the first
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// time when fresh disks were supplied, it is a two dimensional
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// array second dimension represents list of disks used per set.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Sets  [ ] [ ] string  ` json:"sets" ` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Distribution algorithm represents the hashing algorithm
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// to pick the right set index for an object.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										DistributionAlgo  string  ` json:"distributionAlgo" ` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  ` json:"xl" ` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-03-16 04:55:23 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// formatXLV3 struct is same as formatXLV2 struct except that formatXLV3.XL.Version is "3" indicating
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// the simplified multipart backend which is a flat hierarchy now.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// In .minio.sys/multipart we have:
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// sha256(bucket/object)/uploadID/[xl.json, part.1, part.2 ....]
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  formatXLV3  struct  {  
						 
					
						
							
								
									
										
										
										
											2018-07-17 11:26:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									formatMetaV1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									XL  struct  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-16 04:55:23 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										Version  string  ` json:"version" `  // Version of 'xl' format.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										This     string  ` json:"this" `     // This field carries assigned disk uuid.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Sets field carries the input disk order generated the first
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// time when fresh disks were supplied, it is a two dimensional
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// array second dimension represents list of disks used per set.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Sets  [ ] [ ] string  ` json:"sets" ` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Distribution algorithm represents the hashing algorithm
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// to pick the right set index for an object.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										DistributionAlgo  string  ` json:"distributionAlgo" ` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  ` json:"xl" ` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// Returns formatXL.XL.Version
  
						 
					
						
							
								
									
										
										
										
											2018-03-16 04:55:23 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  newFormatXLV3 ( numSets  int ,  setLen  int )  * formatXLV3  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									format  :=  & formatXLV3 { } 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									format . Version  =  formatMetaVersionV1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									format . Format  =  formatBackendXL 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-19 11:17:35 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									format . ID  =  mustGetUUID ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-16 04:55:23 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									format . XL . Version  =  formatXLVersionV3 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									format . XL . DistributionAlgo  =  formatXLVersionV2DistributionAlgo 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									format . XL . Sets  =  make ( [ ] [ ] string ,  numSets ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  i  :=  0 ;  i  <  numSets ;  i ++  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										format . XL . Sets [ i ]  =  make ( [ ] string ,  setLen ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  j  :=  0 ;  j  <  setLen ;  j ++  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											format . XL . Sets [ i ] [ j ]  =  mustGetUUID ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  format 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Returns formatXL.XL.Version information, this code is specifically
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// used to read XL `format.json` and capture any version information
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// that it may have.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  formatXLGetVersion ( formatPath  string )  ( string ,  error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									format  :=  & formatXLVersionDetect { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									b ,  err  :=  ioutil . ReadFile ( formatPath ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  "" ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  =  json . Unmarshal ( b ,  format ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  "" ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  format . XL . Version ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Returns format meta format version from `format.json`. This code
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// is specifically used to detect meta format.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  formatMetaGetFormatBackendXL ( formatPath  string )  ( string ,  error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									meta  :=  & formatMetaV1 { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									b ,  err  :=  ioutil . ReadFile ( formatPath ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  "" ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  =  json . Unmarshal ( b ,  meta ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  "" ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  meta . Version  !=  formatMetaVersionV1  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  "" ,  fmt . Errorf ( ` format.Version expected: %s, got: %s ` ,  formatMetaVersionV1 ,  meta . Version ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  meta . Format ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Migrates all previous versions to latest version of `format.json`,
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// this code calls migration in sequence, such as V1 is migrated to V2
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// first before it V2 migrates to V3.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  formatXLMigrate ( export  string )  error  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									formatPath  :=  pathJoin ( export ,  minioMetaBucket ,  formatConfigFile ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									backend ,  err  :=  formatMetaGetFormatBackendXL ( formatPath ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  backend  !=  formatBackendXL  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  fmt . Errorf ( ` Disk %s: found backend %s, expected %s ` ,  export ,  backend ,  formatBackendXL ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									version ,  err  :=  formatXLGetVersion ( formatPath ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  version  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  formatXLVersionV1 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  =  formatXLMigrateV1ToV2 ( export ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										fallthrough 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  formatXLVersionV2 : 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-16 04:55:23 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  err  =  formatXLMigrateV2ToV3 ( export ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										fallthrough 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  formatXLVersionV3 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// format-V3 is the latest verion.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  fmt . Errorf ( ` %s: unknown format version %s ` ,  export ,  version ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Migrates version V1 of format.json to version V2 of format.json,
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// migration fails upon any error.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  formatXLMigrateV1ToV2 ( export  string )  error  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									formatPath  :=  pathJoin ( export ,  minioMetaBucket ,  formatConfigFile ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									version ,  err  :=  formatXLGetVersion ( formatPath ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  version  !=  formatXLVersionV1  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  fmt . Errorf ( ` Disk %s: format version expected %s, found %s ` ,  export ,  formatXLVersionV1 ,  version ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									formatV1  :=  & formatXLV1 { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									b ,  err  :=  ioutil . ReadFile ( formatPath ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  =  json . Unmarshal ( b ,  formatV1 ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-03 07:34:15 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-03-16 04:55:23 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									formatV2  :=  & formatXLV2 { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									formatV2 . Version  =  formatMetaVersionV1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									formatV2 . Format  =  formatBackendXL 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									formatV2 . XL . Version  =  formatXLVersionV2 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									formatV2 . XL . DistributionAlgo  =  formatXLVersionV2DistributionAlgo 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-20 00:13:00 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									formatV2 . XL . This  =  formatV1 . XL . Disk 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-16 04:55:23 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									formatV2 . XL . Sets  =  make ( [ ] [ ] string ,  1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									formatV2 . XL . Sets [ 0 ]  =  make ( [ ] string ,  len ( formatV1 . XL . JBOD ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									copy ( formatV2 . XL . Sets [ 0 ] ,  formatV1 . XL . JBOD ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									b ,  err  =  json . Marshal ( formatV2 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  ioutil . WriteFile ( formatPath ,  b ,  0644 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2017-08-03 19:37:02 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-03-16 04:55:23 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// Migrates V2 for format.json to V3 (Flat hierarchy for multipart)
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  formatXLMigrateV2ToV3 ( export  string )  error  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									formatPath  :=  pathJoin ( export ,  minioMetaBucket ,  formatConfigFile ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									version ,  err  :=  formatXLGetVersion ( formatPath ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  version  !=  formatXLVersionV2  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  fmt . Errorf ( ` Disk %s: format version expected %s, found %s ` ,  export ,  formatXLVersionV2 ,  version ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									formatV2  :=  & formatXLV2 { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									b ,  err  :=  ioutil . ReadFile ( formatPath ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									err  =  json . Unmarshal ( b ,  formatV2 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-06 12:15:28 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  =  removeAll ( pathJoin ( export ,  minioMetaMultipartBucket ) ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-16 04:55:23 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-06 12:15:28 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  =  mkdirAll ( pathJoin ( export ,  minioMetaMultipartBucket ) ,  0755 ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-16 04:55:23 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// format-V2 struct is exactly same as format-V1 except that version is "3"
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// which indicates the simplified multipart backend.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									formatV3  :=  formatXLV3 { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									formatV3 . Version  =  formatV2 . Version 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									formatV3 . Format  =  formatV2 . Format 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									formatV3 . XL  =  formatV2 . XL 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									formatV3 . XL . Version  =  formatXLVersionV3 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									b ,  err  =  json . Marshal ( formatV3 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  ioutil . WriteFile ( formatPath ,  b ,  0644 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-05-01 11:37:39 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// Returns true, if one of the errors is non-nil and is Unformatted disk.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  hasAnyErrorsUnformatted ( errs  [ ] error )  bool  {  
						 
					
						
							
								
									
										
										
										
											2017-08-03 19:37:02 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									for  _ ,  err  :=  range  errs  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-01 11:37:39 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  err  !=  nil  &&  err  ==  errUnformattedDisk  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// countErrs - count a specific error.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  countErrs ( errs  [ ] error ,  err  error )  int  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  i  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  _ ,  err1  :=  range  errs  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-11 00:36:37 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  err1  ==  err  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											i ++ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  i 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-03 07:34:15 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// Does all errors indicate we need to initialize all disks?.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  shouldInitXLDisks ( errs  [ ] error )  bool  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  countErrs ( errs ,  errUnformattedDisk )  ==  len ( errs ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-04-13 06:43:38 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// Check if unformatted disks are equal to write quorum.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  quorumUnformattedDisks ( errs  [ ] error )  bool  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  countErrs ( errs ,  errUnformattedDisk )  >=  ( len ( errs ) / 2 ) + 1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// loadFormatXLAll - load all format config from all input disks in parallel.
  
						 
					
						
							
								
									
										
										
										
											2018-04-04 12:58:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  loadFormatXLAll ( storageDisks  [ ] StorageAPI )  ( [ ] * formatXLV3 ,  [ ] error )  {  
						 
					
						
							
								
									
										
										
										
											2016-06-03 07:34:15 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// Initialize sync waitgroup.
 
							 
						 
					
						
							
								
									
										
										
										
											2019-09-12 01:22:12 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									var  wg  sync . WaitGroup 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-03 07:34:15 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Initialize list of errors.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-04 12:58:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									var  sErrs  =  make ( [ ] error ,  len ( storageDisks ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-03 07:34:15 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Initialize format configs.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-04 12:58:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									var  formats  =  make ( [ ] * formatXLV3 ,  len ( storageDisks ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-03 07:34:15 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-01-23 06:54:55 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Load format from each disk in parallel
 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-04 12:58:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  index ,  disk  :=  range  storageDisks  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-11 05:38:15 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										if  disk  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											sErrs [ index ]  =  errDiskNotFound 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-03 07:34:15 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										wg . Add ( 1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-23 06:54:55 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Launch go-routine per disk.
 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-03 07:34:15 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										go  func ( index  int ,  disk  StorageAPI )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											defer  wg . Done ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-04 12:58:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											format ,  lErr  :=  loadFormatXL ( disk ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-03 07:34:15 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											if  lErr  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												sErrs [ index ]  =  lErr 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-09 06:30:55 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											formats [ index ]  =  format 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-03 07:34:15 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} ( index ,  disk ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-01-23 06:54:55 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Wait for all go-routines to finish.
 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-03 07:34:15 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									wg . Wait ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Return all formats and nil
 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-09 06:30:55 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									return  formats ,  sErrs 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-03 07:34:15 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-03-16 04:55:23 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  saveFormatXL ( disk  StorageAPI ,  format  interface { } )  error  {  
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Marshal and write to disk.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									formatBytes ,  err  :=  json . Marshal ( format ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  err 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-03 19:37:02 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Purge any existing temporary file, okay to ignore errors here.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-03 13:18:06 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									defer  disk . DeleteFile ( minioMetaBucket ,  formatConfigFileTmp ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-03 19:37:02 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Append file `format.json.tmp`.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  =  disk . AppendFile ( minioMetaBucket ,  formatConfigFileTmp ,  formatBytes ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  err 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-03 19:37:02 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Rename file `format.json.tmp` --> `format.json`.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  disk . RenameFile ( minioMetaBucket ,  formatConfigFileTmp ,  minioMetaBucket ,  formatConfigFile ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-20 17:22:22 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-11-03 02:31:55 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								var  ignoredHiddenDirectories  =  [ ] string {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									minioMetaBucket , 
							 
						 
					
						
							
								
									
										
										
										
											2018-11-29 14:09:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									".snapshot" , 
							 
						 
					
						
							
								
									
										
										
										
											2018-11-03 02:31:55 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"lost+found" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"$RECYCLE.BIN" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"System Volume Information" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  isIgnoreHiddenDirectories ( dir  string )  bool  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  _ ,  ignDir  :=  range  ignoredHiddenDirectories  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  dir  ==  ignDir  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// loadFormatXL - loads format.json from disk.
  
						 
					
						
							
								
									
										
										
										
											2018-03-16 04:55:23 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  loadFormatXL ( disk  StorageAPI )  ( format  * formatXLV3 ,  err  error )  {  
						 
					
						
							
								
									
										
										
										
											2016-06-26 05:51:06 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									buf ,  err  :=  disk . ReadAll ( minioMetaBucket ,  formatConfigFile ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-20 17:22:22 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										// 'file not found' and 'volume not found' as
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// same. 'volume not found' usually means its a fresh disk.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  ==  errFileNotFound  ||  err  ==  errVolumeNotFound  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											var  vols  [ ] VolInfo 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											vols ,  err  =  disk . ListVols ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2018-11-03 02:31:55 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  len ( vols )  >  1  ||  ( len ( vols )  ==  1  &&  ! isIgnoreHiddenDirectories ( vols [ 0 ] . Name ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-23 06:54:55 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												// 'format.json' not found, but we
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// found user data.
 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-20 17:22:22 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												return  nil ,  errCorruptedFormat 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// No other data found, its a fresh disk.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  nil ,  errUnformattedDisk 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-07 15:59:43 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return  nil ,  err 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-05 03:18:20 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-24 17:06:23 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Try to decode format json into formatConfigV1 struct.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-16 04:55:23 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									format  =  & formatXLV3 { } 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-26 05:51:06 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  err  =  json . Unmarshal ( buf ,  format ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-07 15:59:43 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return  nil ,  err 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-05 03:18:20 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-24 17:06:23 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Success.
 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-20 17:22:22 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									return  format ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// Valid formatXL basic versions.
  
						 
					
						
							
								
									
										
										
										
											2018-03-16 04:55:23 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  checkFormatXLValue ( formatXL  * formatXLV3 )  error  {  
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Validate format version and format type.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  formatXL . Version  !=  formatMetaVersionV1  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  fmt . Errorf ( "Unsupported version of backend format [%s] found" ,  formatXL . Version ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-26 18:18:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  formatXL . Format  !=  formatBackendXL  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  fmt . Errorf ( "Unsupported backend format [%s] found" ,  formatXL . Format ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-03 19:37:02 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-16 04:55:23 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  formatXL . XL . Version  !=  formatXLVersionV3  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  fmt . Errorf ( "Unsupported XL backend format found [%s]" ,  formatXL . XL . Version ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-23 06:54:55 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  nil 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-03 19:37:02 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// Check all format values.
  
						 
					
						
							
								
									
										
										
										
											2018-03-16 04:55:23 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  checkFormatXLValues ( formats  [ ] * formatXLV3 )  error  {  
						 
					
						
							
								
									
										
										
										
											2018-02-21 10:42:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  i ,  formatXL  :=  range  formats  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  formatXL  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  :=  checkFormatXLValue ( formatXL ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  len ( formats )  !=  len ( formatXL . XL . Sets ) * len ( formatXL . XL . Sets [ 0 ] )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-21 10:42:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  fmt . Errorf ( "%s disk is already being used in another erasure deployment. (Number of disks specified: %d but the number of disks found in the %s disk's format.json: %d)" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												humanize . Ordinal ( i + 1 ) ,  len ( formats ) ,  humanize . Ordinal ( i + 1 ) ,  len ( formatXL . XL . Sets ) * len ( formatXL . XL . Sets [ 0 ] ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-03 19:37:02 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2017-08-03 19:37:02 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-07-19 11:17:35 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// Get Deployment ID for the XL sets from format.json.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// This need not be in quorum. Even if one of the format.json
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// file has this value, we assume it is valid.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// If more than one format.json's have different id, it is considered a corrupt
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// backend format.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  formatXLGetDeploymentID ( refFormat  * formatXLV3 ,  formats  [ ] * formatXLV3 )  ( string ,  error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  deploymentID  string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  _ ,  format  :=  range  formats  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  format  ==  nil  ||  format . ID  ==  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  reflect . DeepEqual ( format . XL . Sets ,  refFormat . XL . Sets )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// Found an ID in one of the format.json file
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// Set deploymentID for the first time.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  deploymentID  ==  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												deploymentID  =  format . ID 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											}  else  if  deploymentID  !=  format . ID  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// DeploymentID found earlier doesn't match with the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// current format.json's ID.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  "" ,  errCorruptedFormat 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  deploymentID ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// formatXLFixDeploymentID - Add deployment id if it is not present.
  
						 
					
						
							
								
									
										
										
										
											2019-04-03 01:50:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  formatXLFixDeploymentID ( ctx  context . Context ,  endpoints  EndpointList ,  storageDisks  [ ] StorageAPI ,  refFormat  * formatXLV3 )  ( err  error )  {  
						 
					
						
							
								
									
										
										
										
											2018-07-19 11:17:35 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Acquire lock on format.json
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									mutex  :=  newNSLock ( globalIsDistXL ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-06-29 13:09:17 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									formatLock  :=  mutex . NewNSLock ( ctx ,  minioMetaBucket ,  formatConfigFile ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-19 11:17:35 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  =  formatLock . GetLock ( globalHealingTimeout ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									defer  formatLock . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Attempt to load all `format.json` from all disks.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  sErrs  [ ] error 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									formats ,  sErrs  :=  loadFormatXLAll ( storageDisks ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  i ,  sErr  :=  range  sErrs  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  _ ,  ok  :=  formatCriticalErrors [ sErr ] ;  ok  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-03 01:50:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  fmt . Errorf ( "Disk %s: %s" ,  endpoints [ i ] ,  sErr ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-19 11:17:35 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  index  :=  range  formats  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// If the XL sets do not match, set those formats to nil,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// We do not have to update the ID on those format.json file.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  formats [ index ]  !=  nil  &&  ! reflect . DeepEqual ( formats [ index ] . XL . Sets ,  refFormat . XL . Sets )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											formats [ index ]  =  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									refFormat . ID ,  err  =  formatXLGetDeploymentID ( refFormat ,  formats ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// If ID is set, then some other node got the lock
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// before this node could and generated an ID
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// for the deployment. No need to generate one.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  refFormat . ID  !=  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// ID is generated for the first time,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// We set the ID in all the formats and update.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									refFormat . ID  =  mustGetUUID ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  _ ,  format  :=  range  formats  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  format  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											format . ID  =  refFormat . ID 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Deployment ID needs to be set on all the disks.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Save `format.json` across all disks.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  saveFormatXLAll ( ctx ,  storageDisks ,  formats ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Update only the valid local disks which have not been updated before.
  
						 
					
						
							
								
									
										
										
										
											2019-04-03 01:50:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  formatXLFixLocalDeploymentID ( ctx  context . Context ,  endpoints  EndpointList ,  storageDisks  [ ] StorageAPI ,  refFormat  * formatXLV3 )  error  {  
						 
					
						
							
								
									
										
										
										
											2018-07-19 11:17:35 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// If this server was down when the deploymentID was updated
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// then we make sure that we update the local disks with the deploymentID.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  index ,  storageDisk  :=  range  storageDisks  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-03 01:50:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  endpoints [ index ] . IsLocal  &&  storageDisk  !=  nil  &&  storageDisk . IsOnline ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-19 11:17:35 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											format ,  err  :=  loadFormatXL ( storageDisk ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// Disk can be offline etc.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// ignore the errors seen here.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  format . ID  !=  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ! reflect . DeepEqual ( format . XL . Sets ,  refFormat . XL . Sets )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											format . ID  =  refFormat . ID 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  err  :=  saveFormatXL ( storageDisk ,  format ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												logger . LogIf ( ctx ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  fmt . Errorf ( "Unable to save format.json, %s" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// Get backend XL format in quorum `format.json`.
  
						 
					
						
							
								
									
										
										
										
											2018-03-16 04:55:23 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  getFormatXLInQuorum ( formats  [ ] * formatXLV3 )  ( * formatXLV3 ,  error )  {  
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									formatHashes  :=  make ( [ ] string ,  len ( formats ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  i ,  format  :=  range  formats  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  format  ==  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-23 06:54:55 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										h  :=  sha256 . New ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  _ ,  set  :=  range  format . XL . Sets  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											for  _ ,  diskID  :=  range  set  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												h . Write ( [ ] byte ( diskID ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-23 08:18:31 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-02 07:15:56 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										formatHashes [ i ]  =  hex . EncodeToString ( h . Sum ( nil ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-02 07:15:56 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-26 18:18:47 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									formatCountMap  :=  make ( map [ string ] int ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  _ ,  hash  :=  range  formatHashes  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  hash  ==  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										formatCountMap [ hash ] ++ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-02 07:15:56 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									maxHash  :=  "" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									maxCount  :=  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  hash ,  count  :=  range  formatCountMap  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  count  >  maxCount  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											maxCount  =  count 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											maxHash  =  hash 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-29 07:49:59 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  maxCount  <  len ( formats ) / 2  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  errXLReadQuorum 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  i ,  hash  :=  range  formatHashes  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  hash  ==  maxHash  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											format  :=  * formats [ i ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											format . XL . This  =  "" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  & format ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-29 07:49:59 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  nil ,  errXLReadQuorum 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-29 07:49:59 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-03-16 04:55:23 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  formatXLV3Check ( reference  * formatXLV3 ,  format  * formatXLV3 )  error  {  
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									tmpFormat  :=  * format 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									this  :=  tmpFormat . XL . This 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									tmpFormat . XL . This  =  "" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  len ( reference . XL . Sets )  !=  len ( format . XL . Sets )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  fmt . Errorf ( "Expected number of sets %d, got %d" ,  len ( reference . XL . Sets ) ,  len ( format . XL . Sets ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-03 19:37:02 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Make sure that the sets match.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  i  :=  range  reference . XL . Sets  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  len ( reference . XL . Sets [ i ] )  !=  len ( format . XL . Sets [ i ] )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  fmt . Errorf ( "Each set should be of same size, expected %d got %d" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												len ( reference . XL . Sets [ i ] ) ,  len ( format . XL . Sets [ i ] ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-29 07:49:59 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										for  j  :=  range  reference . XL . Sets [ i ]  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  reference . XL . Sets [ i ] [ j ]  !=  format . XL . Sets [ i ] [ j ]  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  fmt . Errorf ( "UUID on positions %d:%d do not match with, expected %s got %s" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													i ,  j ,  reference . XL . Sets [ i ] [ j ] ,  format . XL . Sets [ i ] [ j ] ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-29 07:49:59 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Make sure that the diskID is found in the set.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  i  :=  0 ;  i  <  len ( tmpFormat . XL . Sets ) ;  i ++  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  j  :=  0 ;  j  <  len ( tmpFormat . XL . Sets [ i ] ) ;  j ++  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  this  ==  tmpFormat . XL . Sets [ i ] [ j ]  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  nil 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-29 07:49:59 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  fmt . Errorf ( "Disk ID %s not found in any disk sets %s" ,  this ,  format . XL . Sets ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-29 07:49:59 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// saveFormatXLAll - populates `format.json` on disks in its order.
  
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  saveFormatXLAll ( ctx  context . Context ,  storageDisks  [ ] StorageAPI ,  formats  [ ] * formatXLV3 )  error  {  
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									var  errs  =  make ( [ ] error ,  len ( storageDisks ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-29 07:49:59 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-09-12 01:22:12 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									var  wg  sync . WaitGroup 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-29 07:49:59 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Write `format.json` to all disks.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  index ,  disk  :=  range  storageDisks  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  formats [ index ]  ==  nil  ||  disk  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											errs [ index ]  =  errDiskNotFound 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-29 07:49:59 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										wg . Add ( 1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-16 04:55:23 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										go  func ( index  int ,  disk  StorageAPI ,  format  * formatXLV3 )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											defer  wg . Done ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											errs [ index ]  =  saveFormatXL ( disk ,  format ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ( index ,  disk ,  formats [ index ] ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-29 07:49:59 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Wait for the routines to finish.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									wg . Wait ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-29 07:49:59 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-04-04 12:58:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									writeQuorum  :=  len ( storageDisks ) / 2  +  1 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  reduceWriteQuorumErrs ( ctx ,  errs ,  nil ,  writeQuorum ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-04-04 12:58:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// relinquishes the underlying connection for all storage disks.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  closeStorageDisks ( storageDisks  [ ] StorageAPI )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  _ ,  disk  :=  range  storageDisks  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  disk  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										disk . Close ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// Initialize storage disks based on input arguments.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  initStorageDisks ( endpoints  EndpointList )  ( [ ] StorageAPI ,  error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Bootstrap disks.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									storageDisks  :=  make ( [ ] StorageAPI ,  len ( endpoints ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  index ,  endpoint  :=  range  endpoints  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										storage ,  err  :=  newStorageAPI ( endpoint ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  &&  err  !=  errDiskNotFound  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-20 17:22:22 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											return  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										storageDisks [ index ]  =  storage 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-07 15:59:43 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  storageDisks ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2016-06-02 07:43:31 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-08-03 03:17:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// Runs through the faulty disks and record their errors.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  initDisksWithErrors ( endpoints  EndpointList )  ( [ ] StorageAPI ,  [ ] error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									storageDisks  :=  make ( [ ] StorageAPI ,  len ( endpoints ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  dErrs  =  make ( [ ] error ,  len ( storageDisks ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  index ,  endpoint  :=  range  endpoints  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										storage ,  err  :=  newStorageAPI ( endpoint ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											logger . LogIf ( context . Background ( ) ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											dErrs [ index ]  =  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										storageDisks [ index ]  =  storage 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  storageDisks ,  dErrs 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-03-20 00:13:00 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// formatXLV3ThisEmpty - find out if '.This' field is empty
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// in any of the input `formats`, if yes return true.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  formatXLV3ThisEmpty ( formats  [ ] * formatXLV3 )  bool  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  _ ,  format  :=  range  formats  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  format  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// NOTE: This code is specifically needed when migrating version
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// V1 to V2 to V3, in a scenario such as this we only need to handle
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// single sets since we never used to support multiple sets in releases
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// with V1 format version.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  len ( format . XL . Sets )  >  1  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  format . XL . This  ==  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// fixFormatXLV3 - fix format XL configuration on all disks.
  
						 
					
						
							
								
									
										
										
										
											2018-04-04 12:58:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  fixFormatXLV3 ( storageDisks  [ ] StorageAPI ,  endpoints  EndpointList ,  formats  [ ] * formatXLV3 )  error  {  
						 
					
						
							
								
									
										
										
										
											2018-03-20 00:13:00 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  i ,  format  :=  range  formats  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  format  ==  nil  ||  ! endpoints [ i ] . IsLocal  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// NOTE: This code is specifically needed when migrating version
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// V1 to V2 to V3, in a scenario such as this we only need to handle
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// single sets since we never used to support multiple sets in releases
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// with V1 format version.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  len ( format . XL . Sets )  >  1  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  format . XL . This  ==  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											formats [ i ] . XL . This  =  format . XL . Sets [ 0 ] [ i ] 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-04 12:58:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  err  :=  saveFormatXL ( storageDisks [ i ] ,  formats [ i ] ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-20 00:13:00 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// initFormatXL - save XL format configuration on all disks.
  
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  initFormatXL ( ctx  context . Context ,  storageDisks  [ ] StorageAPI ,  setCount ,  disksPerSet  int )  ( format  * formatXLV3 ,  err  error )  {  
						 
					
						
							
								
									
										
										
										
											2018-03-16 04:55:23 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									format  =  newFormatXLV3 ( setCount ,  disksPerSet ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-04 12:58:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									formats  :=  make ( [ ] * formatXLV3 ,  len ( storageDisks ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-05 03:18:20 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  i  :=  0 ;  i  <  setCount ;  i ++  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  j  :=  0 ;  j  <  disksPerSet ;  j ++  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											newFormat  :=  * format 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											newFormat . XL . This  =  format . XL . Sets [ i ] [ j ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											formats [ i * disksPerSet + j ]  =  & newFormat 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-05 03:18:20 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Initialize meta volume, if volume already exists ignores it.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-04 12:58:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  =  initFormatXLMetaVolume ( storageDisks ,  formats ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  format ,  fmt . Errorf ( "Unable to initialize '.minio.sys' meta volume, %s" ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-04-19 01:35:17 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Save formats `format.json` across all disks.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  =  saveFormatXLAll ( ctx ,  storageDisks ,  formats ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  nil ,  err 
							 
						 
					
						
							
								
									
										
										
										
											2017-04-19 01:35:17 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  format ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2017-04-19 01:35:17 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// Make XL backend meta volumes.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  makeFormatXLMetaVolumes ( disk  StorageAPI )  error  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Attempt to create `.minio.sys`.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  :=  disk . MakeVol ( minioMetaBucket ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-11 00:36:37 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ! IsErrIgnored ( err ,  initMetaVolIgnoredErrs ... )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  err 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-20 17:22:22 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  :=  disk . MakeVol ( minioMetaTmpBucket ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-11 00:36:37 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ! IsErrIgnored ( err ,  initMetaVolIgnoredErrs ... )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  err 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-20 17:22:22 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  :=  disk . MakeVol ( minioMetaMultipartBucket ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-11 00:36:37 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ! IsErrIgnored ( err ,  initMetaVolIgnoredErrs ... )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  err 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-20 17:22:22 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-05 03:18:20 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  nil 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-12 07:18:55 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								var  initMetaVolIgnoredErrs  =  append ( baseIgnoredErrs ,  errVolumeExists )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Initializes meta volume on all input storage disks.
  
						 
					
						
							
								
									
										
										
										
											2018-04-04 12:58:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  initFormatXLMetaVolume ( storageDisks  [ ] StorageAPI ,  formats  [ ] * formatXLV3 )  error  {  
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// This happens for the first time, but keep this here since this
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// is the only place where it can be made expensive optimizing all
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// other calls. Create minio meta volume, if it doesn't exist yet.
 
							 
						 
					
						
							
								
									
										
										
										
											2019-09-12 01:22:12 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									var  wg  sync . WaitGroup 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Initialize errs to collect errors inside go-routine.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  errs  =  make ( [ ] error ,  len ( storageDisks ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Initialize all disks in parallel.
 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-20 17:22:22 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									for  index ,  disk  :=  range  storageDisks  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  formats [ index ]  ==  nil  ||  disk  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// Ignore create meta volume on disks which are not found.
 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-23 08:18:31 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-20 17:22:22 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-23 08:18:31 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										wg . Add ( 1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										go  func ( index  int ,  disk  StorageAPI )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// Indicate this wait group is done.
 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-23 08:18:31 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											defer  wg . Done ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											errs [ index ]  =  makeFormatXLMetaVolumes ( disk ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ( index ,  disk ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-23 08:18:31 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Wait for all cleanup to finish.
 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-23 08:18:31 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									wg . Wait ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Return upon first error.
 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-23 08:18:31 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									for  _ ,  err  :=  range  errs  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  err  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-20 17:22:22 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  toObjectErr ( err ,  minioMetaBucket ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-23 08:18:31 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Return success here.
 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-23 08:18:31 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// Get all UUIDs which are present in reference format should
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// be present in the list of formats provided, those are considered
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// as online UUIDs.
  
						 
					
						
							
								
									
										
										
										
											2018-03-16 04:55:23 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  getOnlineUUIDs ( refFormat  * formatXLV3 ,  formats  [ ] * formatXLV3 )  ( onlineUUIDs  [ ] string )  {  
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  _ ,  format  :=  range  formats  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  format  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  _ ,  set  :=  range  refFormat . XL . Sets  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											for  _ ,  uuid  :=  range  set  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  format . XL . This  ==  uuid  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													onlineUUIDs  =  append ( onlineUUIDs ,  uuid ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-07 15:59:43 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  onlineUUIDs 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2016-06-23 08:18:31 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// Look for all UUIDs which are not present in reference format
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// but are present in the onlineUUIDs list, construct of list such
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// offline UUIDs.
  
						 
					
						
							
								
									
										
										
										
											2018-03-16 04:55:23 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  getOfflineUUIDs ( refFormat  * formatXLV3 ,  formats  [ ] * formatXLV3 )  ( offlineUUIDs  [ ] string )  {  
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									onlineUUIDs  :=  getOnlineUUIDs ( refFormat ,  formats ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  i ,  set  :=  range  refFormat . XL . Sets  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  j ,  uuid  :=  range  set  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											var  found  bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											for  _ ,  onlineUUID  :=  range  onlineUUIDs  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  refFormat . XL . Sets [ i ] [ j ]  ==  onlineUUID  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													found  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ! found  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												offlineUUIDs  =  append ( offlineUUIDs ,  uuid ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-05 03:18:20 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  offlineUUIDs 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-09 06:30:55 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// Mark all UUIDs that are offline.
  
						 
					
						
							
								
									
										
										
										
											2018-03-16 04:55:23 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  markUUIDsOffline ( refFormat  * formatXLV3 ,  formats  [ ] * formatXLV3 )  {  
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									offlineUUIDs  :=  getOfflineUUIDs ( refFormat ,  formats ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  i ,  set  :=  range  refFormat . XL . Sets  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  j  :=  range  set  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											for  _ ,  offlineUUID  :=  range  offlineUUIDs  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  refFormat . XL . Sets [ i ] [ j ]  ==  offlineUUID  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													refFormat . XL . Sets [ i ] [ j ]  =  offlineDiskUUID 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-31 10:22:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2016-08-31 10:22:27 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// Initialize a new set of set formats which will be written to all disks.
  
						 
					
						
							
								
									
										
										
										
											2018-03-16 04:55:23 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  newHealFormatSets ( refFormat  * formatXLV3 ,  setCount ,  disksPerSet  int ,  formats  [ ] * formatXLV3 ,  errs  [ ] error )  [ ] [ ] * formatXLV3  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									newFormats  :=  make ( [ ] [ ] * formatXLV3 ,  setCount ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  i  :=  range  refFormat . XL . Sets  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-16 04:55:23 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										newFormats [ i ]  =  make ( [ ] * formatXLV3 ,  disksPerSet ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  i  :=  range  refFormat . XL . Sets  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  j  :=  range  refFormat . XL . Sets [ i ]  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  errs [ i * disksPerSet + j ]  ==  errUnformattedDisk  ||  errs [ i * disksPerSet + j ]  ==  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-16 04:55:23 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												newFormats [ i ] [ j ]  =  & formatXLV3 { } 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												newFormats [ i ] [ j ] . Version  =  refFormat . Version 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-23 10:32:06 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												newFormats [ i ] [ j ] . ID  =  refFormat . ID 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												newFormats [ i ] [ j ] . Format  =  refFormat . Format 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												newFormats [ i ] [ j ] . XL . Version  =  refFormat . XL . Version 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												newFormats [ i ] [ j ] . XL . DistributionAlgo  =  refFormat . XL . DistributionAlgo 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  errs [ i * disksPerSet + j ]  ==  errUnformattedDisk  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												newFormats [ i ] [ j ] . XL . This  =  "" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												newFormats [ i ] [ j ] . XL . Sets  =  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  errs [ i * disksPerSet + j ]  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												newFormats [ i ] [ j ] . XL . This  =  formats [ i * disksPerSet + j ] . XL . This 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												newFormats [ i ] [ j ] . XL . Sets  =  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  newFormats 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-05 03:18:20 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}