16589: Fixes test check.
[arvados.git] / lib / mount / fs.go
index 5b6fc0012f59a00b5da9f93be19906675be164f4..c008b96af664ffa605592a1f61e14e30eb4677d3 100644 (file)
@@ -36,7 +36,7 @@ type keepFS struct {
        root   arvados.CustomFileSystem
        open   map[uint64]*sharedFile
        lastFH uint64
-       sync.Mutex
+       sync.RWMutex
 
        // If non-nil, this channel will be closed by Init() to notify
        // other goroutines that the mount is ready.
@@ -62,8 +62,8 @@ func (fs *keepFS) newFH(f arvados.File) uint64 {
 }
 
 func (fs *keepFS) lookupFH(fh uint64) *sharedFile {
-       fs.Lock()
-       defer fs.Unlock()
+       fs.RLock()
+       defer fs.RUnlock()
        return fs.open[fh]
 }
 
@@ -252,11 +252,18 @@ func (fs *keepFS) Chmod(path string, mode uint32) (errc int) {
        }
        if fi, err := fs.root.Stat(path); err != nil {
                return fs.errCode(err)
-       } else if mode & ^uint32(fuse.S_IFREG|fuse.S_IFDIR|0777) != 0 || (fi.Mode()&os.ModeDir != 0) != (mode&fuse.S_IFDIR != 0) {
+       } else if mode & ^uint32(fuse.S_IFREG|fuse.S_IFDIR|0777) != 0 {
+               // Refuse to set mode bits other than
+               // regfile/dir/perms
+               return -fuse.ENOSYS
+       } else if (fi.Mode()&os.ModeDir != 0) != (mode&fuse.S_IFDIR != 0) {
+               // Refuse to transform a regular file to a dir, or
+               // vice versa
                return -fuse.ENOSYS
-       } else {
-               return 0
        }
+       // As long as the change isn't nonsense, chmod is a no-op,
+       // because we don't save permission bits.
+       return 0
 }
 
 func (fs *keepFS) fillStat(stat *fuse.Stat_t, fi os.FileInfo) {
@@ -320,6 +327,16 @@ func (fs *keepFS) Read(path string, buf []byte, ofst int64, fh uint64) (n int) {
                return fs.errCode(err)
        }
        n, err := f.Read(buf)
+       for err == nil && n < len(buf) {
+               // f is an io.Reader ("If some data is available but
+               // not len(p) bytes, Read conventionally returns what
+               // is available instead of waiting for more") -- but
+               // our caller requires us to either fill buf or reach
+               // EOF.
+               done := n
+               n, err = f.Read(buf[done:])
+               n += done
+       }
        if err != nil && err != io.EOF {
                log.Printf("error reading %q: %s", path, err)
                return fs.errCode(err)