local: fix race conditions updating the hashes

This was causing occasional test failures for the -race test of mount
and cmount.
This commit is contained in:
Nick Craig-Wood 2018-03-08 16:31:44 +00:00
parent 70f07fd3ac
commit 6025bb6ad1

View file

@ -66,6 +66,7 @@ type Fs struct {
// do os.Lstat or os.Stat // do os.Lstat or os.Stat
lstat func(name string) (os.FileInfo, error) lstat func(name string) (os.FileInfo, error)
dirNames *mapper // directory name mapping dirNames *mapper // directory name mapping
objectHashesMu sync.Mutex // global lock for Object.hashes
} }
// Object represents a local filesystem object // Object represents a local filesystem object
@ -586,17 +587,17 @@ func (o *Object) Hash(r hash.Type) (string, error) {
return "", errors.Wrap(err, "hash: failed to stat") return "", errors.Wrap(err, "hash: failed to stat")
} }
if !o.modTime.Equal(oldtime) || oldsize != o.size { o.fs.objectHashesMu.Lock()
o.hashes = nil hashes := o.hashes
} o.fs.objectHashesMu.Unlock()
if o.hashes == nil { if !o.modTime.Equal(oldtime) || oldsize != o.size || hashes == nil {
o.hashes = make(map[hash.Type]string) hashes = make(map[hash.Type]string)
in, err := os.Open(o.path) in, err := os.Open(o.path)
if err != nil { if err != nil {
return "", errors.Wrap(err, "hash: failed to open") return "", errors.Wrap(err, "hash: failed to open")
} }
o.hashes, err = hash.Stream(in) hashes, err = hash.Stream(in)
closeErr := in.Close() closeErr := in.Close()
if err != nil { if err != nil {
return "", errors.Wrap(err, "hash: failed to read") return "", errors.Wrap(err, "hash: failed to read")
@ -604,8 +605,11 @@ func (o *Object) Hash(r hash.Type) (string, error) {
if closeErr != nil { if closeErr != nil {
return "", errors.Wrap(closeErr, "hash: failed to close") return "", errors.Wrap(closeErr, "hash: failed to close")
} }
o.fs.objectHashesMu.Lock()
o.hashes = hashes
o.fs.objectHashesMu.Unlock()
} }
return o.hashes[r], nil return hashes[r], nil
} }
// Size returns the size of an object in bytes // Size returns the size of an object in bytes
@ -691,7 +695,9 @@ func (file *localOpenFile) Close() (err error) {
err = file.in.Close() err = file.in.Close()
if err == nil { if err == nil {
if file.hash.Size() == file.o.Size() { if file.hash.Size() == file.o.Size() {
file.o.fs.objectHashesMu.Lock()
file.o.hashes = file.hash.Sums() file.o.hashes = file.hash.Sums()
file.o.fs.objectHashesMu.Unlock()
} }
} }
return err return err
@ -788,7 +794,9 @@ func (o *Object) Update(in io.Reader, src fs.ObjectInfo, options ...fs.OpenOptio
} }
// All successful so update the hashes // All successful so update the hashes
o.fs.objectHashesMu.Lock()
o.hashes = hash.Sums() o.hashes = hash.Sums()
o.fs.objectHashesMu.Unlock()
// Set the mtime // Set the mtime
err = o.SetModTime(src.ModTime()) err = o.SetModTime(src.ModTime())