mirror of
https://github.com/minio/minio.git
synced 2025-04-01 02:03:42 -04:00
xl: StatVol and ListVols should handle cases when disks are missing. (#1703)
Remove unnecessary code, handle cases of missing disk.
This commit is contained in:
parent
6015a7a3cd
commit
f76d975304
118
xl-erasure-v1.go
118
xl-erasure-v1.go
@ -188,8 +188,6 @@ func (xl XL) DeleteVol(volume string) error {
|
|||||||
|
|
||||||
// ListVols - list volumes.
|
// ListVols - list volumes.
|
||||||
func (xl XL) ListVols() (volsInfo []VolInfo, err error) {
|
func (xl XL) ListVols() (volsInfo []VolInfo, err error) {
|
||||||
emptyCount := 0
|
|
||||||
|
|
||||||
// Initialize sync waitgroup.
|
// Initialize sync waitgroup.
|
||||||
var wg = &sync.WaitGroup{}
|
var wg = &sync.WaitGroup{}
|
||||||
|
|
||||||
@ -202,45 +200,37 @@ func (xl XL) ListVols() (volsInfo []VolInfo, err error) {
|
|||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
// Initiate listing.
|
// Initiate listing.
|
||||||
vlsInfo, lErr := disk.ListVols()
|
vlsInfo, _ := disk.ListVols()
|
||||||
if lErr == nil {
|
|
||||||
if len(vlsInfo) == 0 {
|
|
||||||
emptyCount++ // Calculate empty count specially.
|
|
||||||
} else {
|
|
||||||
successVols[index] = vlsInfo
|
successVols[index] = vlsInfo
|
||||||
}
|
|
||||||
}
|
|
||||||
}(index, disk)
|
}(index, disk)
|
||||||
}
|
}
|
||||||
|
|
||||||
// For all the list volumes running in parallel to finish.
|
// For all the list volumes running in parallel to finish.
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|
||||||
// If all list operations resulted in an empty count which is same
|
|
||||||
// as your total storage disks, then it is a valid case return
|
|
||||||
// success with empty vols.
|
|
||||||
if emptyCount == len(xl.storageDisks) {
|
|
||||||
return []VolInfo{}, nil
|
|
||||||
} else if len(successVols) < xl.readQuorum {
|
|
||||||
// If there is data and not empty, then we attempt quorum verification.
|
|
||||||
// Verify if we have enough quorum to list vols.
|
|
||||||
return nil, errReadQuorum
|
|
||||||
}
|
|
||||||
|
|
||||||
var total, free int64
|
|
||||||
// Loop through success vols and get aggregated usage values.
|
// Loop through success vols and get aggregated usage values.
|
||||||
for _, vlsInfo := range successVols {
|
var vlsInfo []VolInfo
|
||||||
if len(vlsInfo) == 0 {
|
var total, free int64
|
||||||
|
for _, vlsInfo = range successVols {
|
||||||
|
if len(vlsInfo) <= 1 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
free += vlsInfo[0].Free
|
var vlInfo VolInfo
|
||||||
total += vlsInfo[0].Total
|
for _, vlInfo = range vlsInfo {
|
||||||
|
if vlInfo.Name == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
free += vlInfo.Free
|
||||||
|
total += vlInfo.Total
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save the updated usage values back into the vols.
|
// Save the updated usage values back into the vols.
|
||||||
for _, volInfo := range successVols[0] {
|
for _, vlInfo := range vlsInfo {
|
||||||
volInfo.Free = free
|
vlInfo.Free = free
|
||||||
volInfo.Total = total
|
vlInfo.Total = total
|
||||||
volsInfo = append(volsInfo, volInfo)
|
volsInfo = append(volsInfo, vlInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: The assumption here is that volumes across all disks in
|
// NOTE: The assumption here is that volumes across all disks in
|
||||||
@ -252,10 +242,10 @@ func (xl XL) ListVols() (volsInfo []VolInfo, err error) {
|
|||||||
|
|
||||||
// getAllVolInfo - list bucket volume info from all disks.
|
// getAllVolInfo - list bucket volume info from all disks.
|
||||||
// Returns error slice indicating the failed volume stat operations.
|
// Returns error slice indicating the failed volume stat operations.
|
||||||
func (xl XL) getAllVolInfo(volume string) (volsInfo []VolInfo, errs []error) {
|
func (xl XL) getAllVolInfo(volume string) ([]VolInfo, []error) {
|
||||||
// Create errs and volInfo slices of storageDisks size.
|
// Create errs and volInfo slices of storageDisks size.
|
||||||
errs = make([]error, len(xl.storageDisks))
|
var errs = make([]error, len(xl.storageDisks))
|
||||||
volsInfo = make([]VolInfo, len(xl.storageDisks))
|
var volsInfo = make([]VolInfo, len(xl.storageDisks))
|
||||||
|
|
||||||
// Allocate a new waitgroup.
|
// Allocate a new waitgroup.
|
||||||
var wg = &sync.WaitGroup{}
|
var wg = &sync.WaitGroup{}
|
||||||
@ -287,7 +277,6 @@ func (xl XL) getAllVolInfo(volume string) (volsInfo []VolInfo, errs []error) {
|
|||||||
// - error if any.
|
// - error if any.
|
||||||
func (xl XL) listAllVolInfo(volume string) ([]VolInfo, bool, error) {
|
func (xl XL) listAllVolInfo(volume string) ([]VolInfo, bool, error) {
|
||||||
volsInfo, errs := xl.getAllVolInfo(volume)
|
volsInfo, errs := xl.getAllVolInfo(volume)
|
||||||
volsInfo = removeDuplicateVols(volsInfo)
|
|
||||||
notFoundCount := 0
|
notFoundCount := 0
|
||||||
for _, err := range errs {
|
for _, err := range errs {
|
||||||
if err == errVolumeNotFound {
|
if err == errVolumeNotFound {
|
||||||
@ -327,75 +316,42 @@ func (xl XL) listAllVolInfo(volume string) ([]VolInfo, bool, error) {
|
|||||||
return volsInfo, heal, nil
|
return volsInfo, heal, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// healVolume - heals any missing volumes.
|
|
||||||
func (xl XL) healVolume(volume string) error {
|
|
||||||
// Lists volume info for all online disks.
|
|
||||||
volsInfo, heal, err := xl.listAllVolInfo(volume)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !heal {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
// Create volume if missing on online disks.
|
|
||||||
for index, volInfo := range volsInfo {
|
|
||||||
if volInfo.Name != "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// Volinfo name would be an empty string, create it.
|
|
||||||
if err = xl.storageDisks[index].MakeVol(volume); err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Removes any duplicate vols.
|
|
||||||
func removeDuplicateVols(volsInfo []VolInfo) []VolInfo {
|
|
||||||
// Use map to record duplicates as we find them.
|
|
||||||
result := []VolInfo{}
|
|
||||||
|
|
||||||
m := make(map[string]VolInfo)
|
|
||||||
for _, v := range volsInfo {
|
|
||||||
if _, found := m[v.Name]; !found {
|
|
||||||
m[v.Name] = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result = make([]VolInfo, 0, len(m))
|
|
||||||
for _, v := range m {
|
|
||||||
result = append(result, v)
|
|
||||||
}
|
|
||||||
// Return the new slice.
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// StatVol - get volume stat info.
|
// StatVol - get volume stat info.
|
||||||
func (xl XL) StatVol(volume string) (volInfo VolInfo, err error) {
|
func (xl XL) StatVol(volume string) (volInfo VolInfo, err error) {
|
||||||
if !isValidVolname(volume) {
|
if !isValidVolname(volume) {
|
||||||
return VolInfo{}, errInvalidArgument
|
return VolInfo{}, errInvalidArgument
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// List and figured out if we need healing.
|
||||||
volsInfo, heal, err := xl.listAllVolInfo(volume)
|
volsInfo, heal, err := xl.listAllVolInfo(volume)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return VolInfo{}, err
|
return VolInfo{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Heal for missing entries.
|
||||||
if heal {
|
if heal {
|
||||||
go func() {
|
go func() {
|
||||||
hErr := xl.healVolume(volume)
|
// Create volume if missing on disks.
|
||||||
errorIf(hErr, "Unable to heal volume "+volume+".")
|
for index, volInfo := range volsInfo {
|
||||||
|
if volInfo.Name != "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Volinfo name would be an empty string, create it.
|
||||||
|
xl.storageDisks[index].MakeVol(volume)
|
||||||
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loop through all statVols, calculate the actual usage values.
|
// Loop through all statVols, calculate the actual usage values.
|
||||||
var total, free int64
|
var total, free int64
|
||||||
for _, volInfo := range volsInfo {
|
for _, volInfo = range volsInfo {
|
||||||
|
if volInfo.Name == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
free += volInfo.Free
|
free += volInfo.Free
|
||||||
total += volInfo.Total
|
total += volInfo.Total
|
||||||
}
|
}
|
||||||
// Filter volsInfo and update the volInfo.
|
// Update the aggregated values.
|
||||||
volInfo = volsInfo[0]
|
|
||||||
volInfo.Free = free
|
volInfo.Free = free
|
||||||
volInfo.Total = total
|
volInfo.Total = total
|
||||||
return volInfo, nil
|
return volInfo, nil
|
||||||
|
Loading…
x
Reference in New Issue
Block a user