XL: ListVols should provide consistent view. (#1648)

Additionally get list of all volumes in parallel for aggregation
and quorum verification.

Fixes #1647
master
Harshavardhana 9 years ago
parent 498ce1e9bb
commit 7de206cb85
  1. 56
      xl-erasure-v1.go

@ -262,48 +262,58 @@ 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 emptyCount := 0
// Success vols map carries successful results of ListVols from
// each disks. // Initialize sync waitgroup.
var successVolsMap = make(map[int][]VolInfo) var wg = &sync.WaitGroup{}
// Success vols map carries successful results of ListVols from each disks.
var successVols = make([][]VolInfo, len(xl.storageDisks))
for index, disk := range xl.storageDisks { for index, disk := range xl.storageDisks {
var vlsInfo []VolInfo wg.Add(1) // Add each go-routine to wait for.
vlsInfo, err = disk.ListVols() go func(index int, disk StorageAPI) {
if err == nil { // Indicate wait group as finished.
if len(vlsInfo) == 0 { defer wg.Done()
emptyCount++
} else { // Initiate listing.
successVolsMap[index] = vlsInfo vlsInfo, lErr := disk.ListVols()
if lErr == nil {
if len(vlsInfo) == 0 {
emptyCount++ // Calculate empty count specially.
} else {
successVols[index] = vlsInfo
}
} }
} }(index, disk)
} }
// For all the list volumes running in parallel to finish.
wg.Wait()
// If all list operations resulted in an empty count which is same // If all list operations resulted in an empty count which is same
// as your total storage disks, then it is a valid case return // as your total storage disks, then it is a valid case return
// success with empty vols. // success with empty vols.
if emptyCount == len(xl.storageDisks) { if emptyCount == len(xl.storageDisks) {
return []VolInfo{}, nil return []VolInfo{}, nil
} else if len(successVolsMap) < xl.readQuorum { } else if len(successVols) < xl.readQuorum {
// If there is data and not empty, then we attempt quorum verification. // If there is data and not empty, then we attempt quorum verification.
// Verify if we have enough quorum to list vols. // Verify if we have enough quorum to list vols.
return nil, errReadQuorum return nil, errReadQuorum
} }
var total, free int64 var total, free int64
// Loop through success vols map and get aggregated usage values. // Loop through success vols and get aggregated usage values.
for index := range xl.storageDisks { for _, vlsInfo := range successVols {
if _, ok := successVolsMap[index]; ok { free += vlsInfo[0].Free
volsInfo = successVolsMap[index] total += vlsInfo[0].Total
free += volsInfo[0].Free
total += volsInfo[0].Total
}
} }
// Save the updated usage values back into the vols. // Save the updated usage values back into the vols.
for index := range volsInfo { for _, volInfo := range successVols[0] {
volsInfo[index].Free = free volInfo.Free = free
volsInfo[index].Total = total volInfo.Total = total
volsInfo = append(volsInfo, volInfo)
} }
// TODO: the assumption here is that volumes across all disks in // NOTE: The assumption here is that volumes across all disks in
// readQuorum have consistent view i.e they all have same number // readQuorum have consistent view i.e they all have same number
// of buckets. This is essentially not verified since healing // of buckets. This is essentially not verified since healing
// should take care of this. // should take care of this.

Loading…
Cancel
Save