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
This commit is contained in:
Jakob Unterwurzacher 2018-10-14 21:55:37 +02:00
parent 932efbd459
commit 0c1ceed1fa
1 changed files with 16 additions and 10 deletions

View File

@ -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