mirror of
				https://github.com/minio/minio.git
				synced 2025-10-29 15:55:00 -04:00 
			
		
		
		
	xl: Fix healing empty directories (#8013)
After some extensive refactors, it turned out empty directories are not healed and heal status is also not reported correctly. This commit fixes it and adds the appropriate unit tests
This commit is contained in:
		
							parent
							
								
									4101d4917c
								
							
						
					
					
						commit
						c5ac901e8d
					
				| @ -501,10 +501,14 @@ func (xl xlObjects) healObjectDir(ctx context.Context, bucket, object string, dr | |||||||
| 			drive = storageDisks[i].String() | 			drive = storageDisks[i].String() | ||||||
| 		} | 		} | ||||||
| 		switch err { | 		switch err { | ||||||
|  | 		case nil: | ||||||
|  | 			hr.Before.Drives[i] = madmin.HealDriveInfo{State: madmin.DriveStateOk} | ||||||
|  | 			hr.After.Drives[i] = madmin.HealDriveInfo{State: madmin.DriveStateOk} | ||||||
| 		case errDiskNotFound: | 		case errDiskNotFound: | ||||||
| 			hr.Before.Drives[i] = madmin.HealDriveInfo{State: madmin.DriveStateOffline} | 			hr.Before.Drives[i] = madmin.HealDriveInfo{State: madmin.DriveStateOffline} | ||||||
| 			hr.After.Drives[i] = madmin.HealDriveInfo{State: madmin.DriveStateOffline} | 			hr.After.Drives[i] = madmin.HealDriveInfo{State: madmin.DriveStateOffline} | ||||||
| 		case errVolumeNotFound: | 		case errVolumeNotFound, errFileNotFound: | ||||||
|  | 			// Bucket or prefix/directory not found | ||||||
| 			hr.Before.Drives[i] = madmin.HealDriveInfo{Endpoint: drive, State: madmin.DriveStateMissing} | 			hr.Before.Drives[i] = madmin.HealDriveInfo{Endpoint: drive, State: madmin.DriveStateMissing} | ||||||
| 			hr.After.Drives[i] = madmin.HealDriveInfo{Endpoint: drive, State: madmin.DriveStateMissing} | 			hr.After.Drives[i] = madmin.HealDriveInfo{Endpoint: drive, State: madmin.DriveStateMissing} | ||||||
| 		default: | 		default: | ||||||
| @ -517,7 +521,8 @@ func (xl xlObjects) healObjectDir(ctx context.Context, bucket, object string, dr | |||||||
| 	} | 	} | ||||||
| 	for i, err := range errs { | 	for i, err := range errs { | ||||||
| 		switch err { | 		switch err { | ||||||
| 		case errVolumeNotFound: | 		case errVolumeNotFound, errFileNotFound: | ||||||
|  | 			// Bucket or prefix/directory not found | ||||||
| 			merr := storageDisks[i].MakeVol(pathJoin(bucket, object)) | 			merr := storageDisks[i].MakeVol(pathJoin(bucket, object)) | ||||||
| 			switch merr { | 			switch merr { | ||||||
| 			case nil, errVolumeExists: | 			case nil, errVolumeExists: | ||||||
|  | |||||||
| @ -250,3 +250,79 @@ func TestHealObjectXL(t *testing.T) { | |||||||
| 		t.Errorf("Expected %v but received %v", InsufficientReadQuorum{}, err) | 		t.Errorf("Expected %v but received %v", InsufficientReadQuorum{}, err) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | // Tests healing of empty directories | ||||||
|  | func TestHealEmptyDirectoryXL(t *testing.T) { | ||||||
|  | 	nDisks := 16 | ||||||
|  | 	fsDirs, err := getRandomDisks(nDisks) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 	defer removeRoots(fsDirs) | ||||||
|  | 
 | ||||||
|  | 	// Everything is fine, should return nil | ||||||
|  | 	obj, _, err := initObjectLayer(mustGetNewEndpointList(fsDirs...)) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	bucket := "bucket" | ||||||
|  | 	object := "empty-dir/" | ||||||
|  | 	var opts ObjectOptions | ||||||
|  | 
 | ||||||
|  | 	err = obj.MakeBucketWithLocation(context.Background(), bucket, "") | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatalf("Failed to make a bucket - %v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Upload an empty directory | ||||||
|  | 	_, err = obj.PutObject(context.Background(), bucket, object, mustGetPutObjReader(t, bytes.NewReader([]byte{}), 0, "", ""), opts) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Remove the object backend files from the first disk. | ||||||
|  | 	xl := obj.(*xlObjects) | ||||||
|  | 	firstDisk := xl.storageDisks[0] | ||||||
|  | 	err = firstDisk.DeleteFile(bucket, object) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatalf("Failed to delete a file - %v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Heal the object | ||||||
|  | 	hr, err := obj.HealObject(context.Background(), bucket, object, false, false, madmin.HealNormalScan) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatalf("Failed to heal object - %v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Check if the empty directory is restored in the first disk | ||||||
|  | 	_, err = firstDisk.StatVol(pathJoin(bucket, object)) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatalf("Expected object to be present but stat failed - %v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Check the state of the object in the first disk (should be missing) | ||||||
|  | 	if hr.Before.Drives[0].State != madmin.DriveStateMissing { | ||||||
|  | 		t.Fatalf("Unexpected drive state: %v", hr.Before.Drives[0].State) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Check the state of all other disks (should be ok) | ||||||
|  | 	for i, h := range append(hr.Before.Drives[1:], hr.After.Drives...) { | ||||||
|  | 		if h.State != madmin.DriveStateOk { | ||||||
|  | 			t.Fatalf("Unexpected drive state (%d): %v", i+1, h.State) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Heal the same object again | ||||||
|  | 	hr, err = obj.HealObject(context.Background(), bucket, object, false, false, madmin.HealNormalScan) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatalf("Failed to heal object - %v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Check that Before & After states are all okay | ||||||
|  | 	for i, h := range append(hr.Before.Drives, hr.After.Drives...) { | ||||||
|  | 		if h.State != madmin.DriveStateOk { | ||||||
|  | 			t.Fatalf("Unexpected drive state (%d): %v", i+1, h.State) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user