diff options
author | Jakob Unterwurzacher | 2018-10-14 21:55:37 +0200 |
---|---|---|
committer | Jakob Unterwurzacher | 2019-01-01 16:24:09 +0100 |
commit | 0c1ceed1fa55e2a9174050c324f679821a5fca8d (patch) | |
tree | 284819706e7bf81ad0d140c61e1788d3fcb2303c | |
parent | 932efbd4593fe6be6c86f0dafeaea32910b7c246 (diff) |
fusefrontend: make GetAttr() symlink-safe
Use openBackingDir() and Fstatat().
High performance impact, though part of it should be
mitigated by adding DirIV caching to the new code paths.
$ ./benchmark.bash
Testing gocryptfs at /tmp/benchmark.bash.Eou: gocryptfs v1.6-37-ge3914b3-dirty; go-fuse v20170619-66-g6df8ddc; 2018-10-14 go1.11
WRITE: 262144000 bytes (262 MB, 250 MiB) copied, 1.2289 s, 213 MB/s
READ: 262144000 bytes (262 MB, 250 MiB) copied, 1.02616 s, 255 MB/s
UNTAR: 24.490
MD5: 13.120
LS: 3.368
RM: 9.232
-rw-r--r-- | internal/fusefrontend/fs.go | 26 |
1 files changed, 16 insertions, 10 deletions
diff --git a/internal/fusefrontend/fs.go b/internal/fusefrontend/fs.go index 8e443b7..a301231 100644 --- a/internal/fusefrontend/fs.go +++ b/internal/fusefrontend/fs.go @@ -73,30 +73,36 @@ func NewFS(args Args, c *contentenc.ContentEnc, n *nametransform.NameTransform) } // GetAttr implements pathfs.Filesystem. -func (fs *FS) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Status) { - tlog.Debug.Printf("FS.GetAttr('%s')", name) - if fs.isFiltered(name) { +// +// GetAttr is symlink-safe through use of openBackingDir() and Fstatat(). +func (fs *FS) GetAttr(relPath string, context *fuse.Context) (*fuse.Attr, fuse.Status) { + tlog.Debug.Printf("FS.GetAttr(%q)", relPath) + if fs.isFiltered(relPath) { return nil, fuse.EPERM } - cName, err := fs.encryptPath(name) + dirfd, cName, err := fs.openBackingDir(relPath) if err != nil { return nil, fuse.ToStatus(err) } - a, status := fs.FileSystem.GetAttr(cName, context) - if a == nil { - tlog.Debug.Printf("FS.GetAttr failed: %s", status.String()) - return a, status + var st unix.Stat_t + err = syscallcompat.Fstatat(dirfd, cName, &st, unix.AT_SYMLINK_NOFOLLOW) + syscall.Close(dirfd) + if err != nil { + return nil, fuse.ToStatus(err) } + a := &fuse.Attr{} + st2 := syscallcompat.Unix2syscall(st) + a.FromStat(&st2) if a.IsRegular() { a.Size = fs.contentEnc.CipherSizeToPlainSize(a.Size) } else if a.IsSymlink() { - target, _ := fs.Readlink(name, context) + target, _ := fs.Readlink(relPath, context) a.Size = uint64(len(target)) } if fs.args.ForceOwner != nil { a.Owner = *fs.args.ForceOwner } - return a, status + return a, fuse.OK } // mangleOpenFlags is used by Create() and Open() to convert the open flags the user |