erasure: healVolume err should be different from shadowed version. (#1590)

Multiple go-routines updating the same shadowed variable can
cause a data race, avoid it by using its own err variable.

Fixes #1589
This commit is contained in:
Harshavardhana 2016-05-11 01:36:09 -07:00 committed by Anand Babu (AB) Periasamy
parent 49141eb3e4
commit 72748d2073
2 changed files with 12 additions and 6 deletions

View file

@ -51,11 +51,11 @@ func (xl XL) ReadFile(volume, path string, startOffset int64) (io.ReadCloser, er
// Heal in background safely, since we already have read
// quorum disks. Let the reads continue.
go func() {
if err = xl.healFile(volume, path); err != nil {
if hErr := xl.healFile(volume, path); hErr != nil {
log.WithFields(logrus.Fields{
"volume": volume,
"path": path,
}).Errorf("healFile failed with %s", err)
}).Errorf("healFile failed with %s", hErr)
return
}
}()

View file

@ -311,6 +311,10 @@ func (xl XL) listAllVolumeInfo(volume string) ([]VolInfo, bool, error) {
// healVolume - heals any missing volumes.
func (xl XL) healVolume(volume string) error {
// Acquire a read lock.
nsMutex.RLock(volume, "")
defer nsMutex.RUnlock(volume, "")
// Lists volume info for all online disks.
volsInfo, heal, err := xl.listAllVolumeInfo(volume)
if err != nil {
@ -345,7 +349,9 @@ func (xl XL) StatVol(volume string) (volInfo VolInfo, err error) {
if !isValidVolname(volume) {
return VolInfo{}, errInvalidArgument
}
nsMutex.RLock(volume, "")
volsInfo, heal, err := xl.listAllVolumeInfo(volume)
nsMutex.RUnlock(volume, "")
if err != nil {
log.WithFields(logrus.Fields{
"volume": volume,
@ -355,10 +361,10 @@ func (xl XL) StatVol(volume string) (volInfo VolInfo, err error) {
if heal {
go func() {
if err = xl.healVolume(volume); err != nil {
if herr := xl.healVolume(volume); herr != nil {
log.WithFields(logrus.Fields{
"volume": volume,
}).Errorf("healVolume failed with %s", err)
}).Errorf("healVolume failed with %s", herr)
return
}
}()
@ -436,11 +442,11 @@ func (xl XL) StatFile(volume, path string) (FileInfo, error) {
if heal {
// Heal in background safely, since we already have read quorum disks.
go func() {
if err = xl.healFile(volume, path); err != nil {
if hErr := xl.healFile(volume, path); hErr != nil {
log.WithFields(logrus.Fields{
"volume": volume,
"path": path,
}).Errorf("healFile failed with %s", err)
}).Errorf("healFile failed with %s", hErr)
return
}
}()