| @@ -60,7 +60,8 @@ const accessModeMask = (os.O_RDONLY | os.O_WRONLY | os.O_RDWR) | |||
| // Open opens an Inode (of regular file type) for reading. It | |||
| // is optional but recommended to return a FileHandle. | |||
| func (n *DirNode) Open(ctx context.Context, flags uint32) (fh fusefs.FileHandle, fuseFlags uint32, errno syscall.Errno) { | |||
| logger.Tracef("DirNode.Open: %v, %#o", n.dir.Name(), flags) | |||
| log := logger.WithField("F", "DirNode.Open") | |||
| log.Tracef("args: %v, %#o", n.dir.Name(), flags) | |||
| rdwrMode := int(flags) & accessModeMask | |||
| if rdwrMode != os.O_RDONLY { | |||
| @@ -69,6 +70,7 @@ func (n *DirNode) Open(ctx context.Context, flags uint32) (fh fusefs.FileHandle, | |||
| reader, err := n.dir.ReadChildren() | |||
| if err != nil { | |||
| log.Warnf("read children: %v", err) | |||
| return nil, 0, translateError(err) | |||
| } | |||
| @@ -78,10 +80,12 @@ func (n *DirNode) Open(ctx context.Context, flags uint32) (fh fusefs.FileHandle, | |||
| var _ = (fusefs.NodeOpener)((*DirNode)(nil)) | |||
| func (n *DirNode) Lookup(ctx context.Context, name string, out *fuse.EntryOut) (inode *fusefs.Inode, errno syscall.Errno) { | |||
| logger.Tracef("DirNode.Lookup: %v, %v", n.dir.Name(), name) | |||
| log := logger.WithField("F", "DirNode.Lookup") | |||
| log.Tracef("args: %v, %v", n.dir.Name(), name) | |||
| child, err := n.dir.Child(ctx, name) | |||
| if err != nil { | |||
| log.Warnf("child: %v", err) | |||
| return nil, translateError(err) | |||
| } | |||
| @@ -125,8 +129,11 @@ func (s *dirStream) HasNext() bool { | |||
| } | |||
| func (s *dirStream) Next() (fuse.DirEntry, syscall.Errno) { | |||
| log := logger.WithField("F", "dirStream.Next") | |||
| entries, err := s.reader.Next(1) | |||
| if err != nil { | |||
| log.Warnf("next: %v", err) | |||
| return fuse.DirEntry{}, translateError(err) | |||
| } | |||
| entry := entries[0] | |||
| @@ -142,10 +149,11 @@ func (s *dirStream) Close() { | |||
| } | |||
| func (n *DirNode) Readdir(ctx context.Context) (ds fusefs.DirStream, errno syscall.Errno) { | |||
| logger.Tracef("DirNode.Readdir: %v", n.dir.Name()) | |||
| log := logger.WithField("F", "DirNode.Readdir") | |||
| reader, err := n.dir.ReadChildren() | |||
| if err != nil { | |||
| log.Warnf("read children: %v", err) | |||
| return nil, translateError(err) | |||
| } | |||
| @@ -155,10 +163,12 @@ func (n *DirNode) Readdir(ctx context.Context) (ds fusefs.DirStream, errno sysca | |||
| var _ = (fusefs.NodeReaddirer)((*DirNode)(nil)) | |||
| func (n *DirNode) Mkdir(ctx context.Context, name string, mode uint32, out *fuse.EntryOut) (inode *fusefs.Inode, errno syscall.Errno) { | |||
| logger.Tracef("DirNode.Mkdir: %v, %v, %#o", n.dir.Name(), name, mode) | |||
| log := logger.WithField("F", "DirNode.Mkdir") | |||
| log.Tracef("args: %v, %v, %#o", n.dir.Name(), name, mode) | |||
| newDir, err := n.dir.NewDir(ctx, name) | |||
| if err != nil { | |||
| log.Warnf("new dir: %v", err) | |||
| return nil, translateError(err) | |||
| } | |||
| @@ -173,10 +183,12 @@ func (n *DirNode) Mkdir(ctx context.Context, name string, mode uint32, out *fuse | |||
| var _ = (fusefs.NodeMkdirer)((*DirNode)(nil)) | |||
| func (n *DirNode) Create(ctx context.Context, name string, flags uint32, mode uint32, out *fuse.EntryOut) (node *fusefs.Inode, fh fusefs.FileHandle, fuseFlags uint32, errno syscall.Errno) { | |||
| logger.Tracef("DirNode.Create: %v, %v, %#x, %#o", n.dir.Name(), name, flags, mode) | |||
| log := logger.WithField("F", "DirNode.Create") | |||
| logger.Tracef("args: %v, %v, %#x, %#o", n.dir.Name(), name, flags, mode) | |||
| hd, flags, err := n.dir.NewFile(ctx, name, flags) | |||
| if err != nil { | |||
| log.Warnf("new file: %v", err) | |||
| return nil, nil, 0, translateError(err) | |||
| } | |||
| @@ -194,9 +206,16 @@ var _ = (fusefs.NodeCreater)((*DirNode)(nil)) | |||
| // return status is OK, the Inode is removed as child in the | |||
| // FS tree automatically. Default is to return EROFS. | |||
| func (n *DirNode) Unlink(ctx context.Context, name string) (errno syscall.Errno) { | |||
| logger.Tracef("DirNode.Unlink: %v, %v", n.dir.Name(), name) | |||
| log := logger.WithField("F", "DirNode.Unlink") | |||
| log.Tracef("args: %v, %v", n.dir.Name(), name) | |||
| err := n.dir.RemoveChild(ctx, name) | |||
| if err != nil { | |||
| log.Warnf("remove child: %v", err) | |||
| return translateError(err) | |||
| } | |||
| return translateError(n.dir.RemoveChild(ctx, name)) | |||
| return 0 | |||
| } | |||
| var _ = (fusefs.NodeUnlinker)((*DirNode)(nil)) | |||
| @@ -204,21 +223,36 @@ var _ = (fusefs.NodeUnlinker)((*DirNode)(nil)) | |||
| // Rmdir is like Unlink but for directories. | |||
| // Default is to return EROFS. | |||
| func (n *DirNode) Rmdir(ctx context.Context, name string) (errno syscall.Errno) { | |||
| logger.Tracef("DirNode.Rmdir: %v, %v", n.dir.Name(), name) | |||
| log := logger.WithField("F", "DirNode.Rmdir") | |||
| log.Tracef("args: %v, %v", n.dir.Name(), name) | |||
| err := n.dir.RemoveChild(ctx, name) | |||
| if err != nil { | |||
| log.Warnf("remove child: %v", err) | |||
| return translateError(err) | |||
| } | |||
| return translateError(n.dir.RemoveChild(ctx, name)) | |||
| return 0 | |||
| } | |||
| var _ = (fusefs.NodeRmdirer)((*DirNode)(nil)) | |||
| func (n *DirNode) Rename(ctx context.Context, oldName string, newParent fusefs.InodeEmbedder, newName string, flags uint32) (errno syscall.Errno) { | |||
| logger.Tracef("DirNode.Rename: %v/%v->%v, %#o", n.dir.Name(), oldName, newName, flags) | |||
| log := logger.WithField("F", "DirNode.Rename") | |||
| log.Tracef("args: %v/%v->%v, %#o", n.dir.Name(), oldName, newName, flags) | |||
| newParentNode, ok := newParent.(*DirNode) | |||
| if !ok { | |||
| return syscall.ENOTDIR | |||
| } | |||
| return translateError(n.dir.MoveChild(ctx, oldName, newName, newParentNode.dir)) | |||
| err := n.dir.MoveChild(ctx, oldName, newName, newParentNode.dir) | |||
| if err != nil { | |||
| log.Warnf("move child: %v", err) | |||
| return translateError(err) | |||
| } | |||
| return 0 | |||
| } | |||
| var _ = (fusefs.NodeRenamer)((*DirNode)(nil)) | |||
| @@ -31,7 +31,7 @@ func (n *FileNode) Getattr(ctx context.Context, f fusefs.FileHandle, out *fuse.A | |||
| } | |||
| func (n *FileNode) Setattr(ctx context.Context, f fusefs.FileHandle, in *fuse.SetAttrIn, out *fuse.AttrOut) (errno syscall.Errno) { | |||
| logger.Tracef("FileNode.Setattr: %v", n.file.Name()) | |||
| log := logger.WithField("F", "FileNode.Setattr") | |||
| n.fs.fillAttrOut(n.file, out) | |||
| @@ -39,6 +39,7 @@ func (n *FileNode) Setattr(ctx context.Context, f fusefs.FileHandle, in *fuse.Se | |||
| if ok { | |||
| err := n.file.Truncate(size) | |||
| if err != nil { | |||
| log.Warnf("truncate: %v", err) | |||
| return translateError(err) | |||
| } | |||
| out.Size = size | |||
| @@ -48,6 +49,7 @@ func (n *FileNode) Setattr(ctx context.Context, f fusefs.FileHandle, in *fuse.Se | |||
| if ok { | |||
| err := n.file.SetModTime(modTime) | |||
| if err != nil { | |||
| log.Warnf("set mod time: %v", err) | |||
| return translateError(err) | |||
| } | |||
| out.Mtime = uint64(modTime.Unix()) | |||
| @@ -60,10 +62,12 @@ func (n *FileNode) Setattr(ctx context.Context, f fusefs.FileHandle, in *fuse.Se | |||
| var _ = (fusefs.NodeSetattrer)((*FileNode)(nil)) | |||
| func (n *FileNode) Open(ctx context.Context, flags uint32) (fh fusefs.FileHandle, fuseFlags uint32, errno syscall.Errno) { | |||
| logger.Tracef("FileNode.Open: %v, %#o", n.file.Name(), flags) | |||
| log := logger.WithField("F", "FileNode.Open") | |||
| log.Tracef("args: %v", flags) | |||
| hd, flags, err := n.file.Open(flags) | |||
| if err != nil { | |||
| log.Warnf("open: %v", err) | |||
| return nil, 0, translateError(err) | |||
| } | |||
| @@ -641,6 +641,9 @@ type CacheFileHandle struct { | |||
| } | |||
| func (h *CacheFileHandle) ReadAt(buf []byte, off int64) (int, error) { | |||
| log := logger.WithField("F", "CacheFileHandle.ReadAt") | |||
| log.Tracef("buf: %v, off: %v", len(buf), off) | |||
| if !h.readable { | |||
| return 0, fuse.ErrPermission | |||
| } | |||
| @@ -743,6 +746,9 @@ func (h *CacheFileHandle) ReadAt(buf []byte, off int64) (int, error) { | |||
| } | |||
| func (h *CacheFileHandle) WriteAt(buf []byte, off int64) (int, error) { | |||
| log := logger.WithField("F", "CacheFileHandle.WriteAt") | |||
| log.Tracef("buf: %v, off: %v", len(buf), off) | |||
| if !h.writeable { | |||
| return 0, fuse.ErrPermission | |||
| } | |||
| @@ -45,7 +45,11 @@ func (r *FuseDir) Mode() os.FileMode { | |||
| } | |||
| func (r *FuseDir) ModTime() time.Time { | |||
| return r.modTime | |||
| info := r.vfs.cache.Stat(r.pathComps) | |||
| if info == nil { | |||
| return r.modTime | |||
| } | |||
| return info.ModTime | |||
| } | |||
| func (r *FuseDir) IsDir() bool { | |||
| @@ -43,7 +43,12 @@ func (n *FuseFileNode) Name() string { | |||
| } | |||
| func (n *FuseFileNode) Size() int64 { | |||
| return n.size | |||
| info := n.vfs.cache.Stat(n.pathComps) | |||
| if info == nil { | |||
| return n.size | |||
| } | |||
| return info.Size | |||
| } | |||
| func (n *FuseFileNode) Mode() os.FileMode { | |||
| @@ -51,7 +56,12 @@ func (n *FuseFileNode) Mode() os.FileMode { | |||
| } | |||
| func (n *FuseFileNode) ModTime() time.Time { | |||
| return n.modTime | |||
| info := n.vfs.cache.Stat(n.pathComps) | |||
| if info == nil { | |||
| return n.modTime | |||
| } | |||
| return info.ModTime | |||
| } | |||
| func (n *FuseFileNode) IsDir() bool { | |||
| @@ -42,33 +42,33 @@ func RunTests(t *testing.T, mnt *mount.Mount) { | |||
| run.Init() | |||
| logger.Infof("Starting test run") | |||
| ok := t.Run("", func(t *testing.T) { | |||
| // t.Run("TestTouchAndDelete", TestTouchAndDelete) | |||
| // t.Run("TestRenameOpenHandle", TestRenameOpenHandle) | |||
| // t.Run("TestDirLs", TestDirLs) | |||
| // t.Run("TestDirCreateAndRemoveDir", TestDirCreateAndRemoveDir) | |||
| // t.Run("TestDirCreateAndRemoveFile", TestDirCreateAndRemoveFile) | |||
| // t.Run("TestDirRenameFile", TestDirRenameFile) | |||
| // t.Run("TestDirRenameEmptyDir", TestDirRenameEmptyDir) | |||
| // t.Run("TestDirRenameFullDir", TestDirRenameFullDir) | |||
| // t.Run("TestDirModTime", TestDirModTime) | |||
| t.Run("TestTouchAndDelete", TestTouchAndDelete) | |||
| t.Run("TestRenameOpenHandle", TestRenameOpenHandle) | |||
| t.Run("TestDirLs", TestDirLs) | |||
| t.Run("TestDirCreateAndRemoveDir", TestDirCreateAndRemoveDir) | |||
| t.Run("TestDirCreateAndRemoveFile", TestDirCreateAndRemoveFile) | |||
| t.Run("TestDirRenameFile", TestDirRenameFile) | |||
| t.Run("TestDirRenameEmptyDir", TestDirRenameEmptyDir) | |||
| t.Run("TestDirRenameFullDir", TestDirRenameFullDir) | |||
| t.Run("TestDirModTime", TestDirModTime) | |||
| // if enableCacheTests { | |||
| // t.Run("TestDirCacheFlush", TestDirCacheFlush) | |||
| // } | |||
| // t.Run("TestDirCacheFlushOnDirRename", TestDirCacheFlushOnDirRename) | |||
| // t.Run("TestFileModTime", TestFileModTime) | |||
| // t.Run("TestFileModTimeWithOpenWriters", TestFileModTimeWithOpenWriters) | |||
| t.Run("TestFileModTime", TestFileModTime) | |||
| t.Run("TestFileModTimeWithOpenWriters", TestFileModTimeWithOpenWriters) | |||
| // t.Run("TestMount", TestMount) | |||
| // t.Run("TestRoot", TestRoot) | |||
| // t.Run("TestReadByByte", TestReadByByte) | |||
| // t.Run("TestReadChecksum", TestReadChecksum) | |||
| // t.Run("TestReadFileDoubleClose", TestReadFileDoubleClose) | |||
| // t.Run("TestReadSeek", TestReadSeek) | |||
| // t.Run("TestWriteFileNoWrite", TestWriteFileNoWrite) | |||
| // t.Run("TestWriteFileWrite", TestWriteFileWrite) | |||
| // t.Run("TestWriteFileOverwrite", TestWriteFileOverwrite) | |||
| // t.Run("TestWriteFileDoubleClose", TestWriteFileDoubleClose) | |||
| // t.Run("TestWriteFileFsync", TestWriteFileFsync) | |||
| // t.Run("TestWriteFileDup", TestWriteFileDup) | |||
| t.Run("TestRoot", TestRoot) | |||
| t.Run("TestReadByByte", TestReadByByte) | |||
| t.Run("TestReadChecksum", TestReadChecksum) | |||
| t.Run("TestReadFileDoubleClose", TestReadFileDoubleClose) | |||
| t.Run("TestReadSeek", TestReadSeek) | |||
| t.Run("TestWriteFileNoWrite", TestWriteFileNoWrite) | |||
| t.Run("TestWriteFileWrite", TestWriteFileWrite) | |||
| t.Run("TestWriteFileOverwrite", TestWriteFileOverwrite) | |||
| t.Run("TestWriteFileDoubleClose", TestWriteFileDoubleClose) | |||
| t.Run("TestWriteFileFsync", TestWriteFileFsync) | |||
| t.Run("TestWriteFileDup", TestWriteFileDup) | |||
| t.Run("TestWriteFileAppend", TestWriteFileAppend) | |||
| }) | |||
| logger.Infof("Finished test run (ok=%v)", ok) | |||
| @@ -4,7 +4,6 @@ import ( | |||
| "os" | |||
| "runtime" | |||
| "testing" | |||
| "time" | |||
| "github.com/stretchr/testify/assert" | |||
| "github.com/stretchr/testify/require" | |||
| @@ -159,8 +158,6 @@ func TestWriteFileAppend(t *testing.T) { | |||
| err = fh.Close() | |||
| require.NoError(t, err) | |||
| <-time.After(time.Second * 10) | |||
| info, err := run.os.Stat(filepath) | |||
| require.NoError(t, err) | |||
| require.EqualValues(t, len(testData)+len(appendData), info.Size()) | |||