fusefrontend: don't always clear the dircache in Rename

When filename encryption is on, we do know when we
overwrite a directory, and can clear only in this case.

sshfs-benchmark.bash:    sshfs  gocryptfs-on-sshfs
git init                  1.74                7.80
rsync                     6.19               11.63
This commit is contained in:
Jakob Unterwurzacher 2020-05-24 20:19:27 +02:00
parent 2a9b99a0ef
commit cb8872577d

View File

@ -533,7 +533,6 @@ func (fs *FS) Symlink(target string, linkName string, context *fuse.Context) (co
// //
// Symlink-safe through Renameat(). // Symlink-safe through Renameat().
func (fs *FS) Rename(oldPath string, newPath string, context *fuse.Context) (code fuse.Status) { func (fs *FS) Rename(oldPath string, newPath string, context *fuse.Context) (code fuse.Status) {
defer fs.dirCache.Clear()
if fs.isFiltered(newPath) { if fs.isFiltered(newPath) {
return fuse.EPERM return fuse.EPERM
} }
@ -549,6 +548,9 @@ func (fs *FS) Rename(oldPath string, newPath string, context *fuse.Context) (cod
defer syscall.Close(newDirfd) defer syscall.Close(newDirfd)
// Easy case. // Easy case.
if fs.args.PlaintextNames { if fs.args.PlaintextNames {
// The rename may replace another directory. Make sure we drop the
// deleted directory from the cache.
defer fs.dirCache.Clear()
return fuse.ToStatus(syscallcompat.Renameat(oldDirfd, oldCName, newDirfd, newCName)) return fuse.ToStatus(syscallcompat.Renameat(oldDirfd, oldCName, newDirfd, newCName))
} }
// Long destination file name: create .name file // Long destination file name: create .name file
@ -575,6 +577,11 @@ func (fs *FS) Rename(oldPath string, newPath string, context *fuse.Context) (cod
// again. // again.
tlog.Debug.Printf("Rename: Handling ENOTEMPTY") tlog.Debug.Printf("Rename: Handling ENOTEMPTY")
if fs.Rmdir(newPath, context) == fuse.OK { if fs.Rmdir(newPath, context) == fuse.OK {
// The rename replaced another directory. Make sure we drop the
// deleted directory from the cache (note: fs.Rmdir also clears it,
// but this is not guaranteed forever, and a double clear does no
// harm).
defer fs.dirCache.Clear()
err = syscallcompat.Renameat(oldDirfd, oldCName, newDirfd, newCName) err = syscallcompat.Renameat(oldDirfd, oldCName, newDirfd, newCName)
} }
} }