nametransform: implement ReadDirIV without Openat

As ReadDirIV operates on a path anyway, opening the directory
has no clear safety advantage w.r.t. concurrent renames.

If the backing directory is a reverse-mounted gocryptfs filesystem,
each directory open is an OPENDIR, and this causes a full directory
read!

This patch improves the "ls -lR" performance of an

  DIR --> gocryptfs-reverse --> gocryptfs

chain by a factor of ~10.

OPENDIR counts for ls -lR:
  Before 15570
  After   2745
This commit is contained in:
Jakob Unterwurzacher 2016-09-21 23:22:13 +02:00
parent 01c18dbcab
commit b34a665da4
1 changed files with 7 additions and 4 deletions

View File

@ -24,13 +24,12 @@ const (
// ReadDirIV - read the "gocryptfs.diriv" file from "dir" (absolute ciphertext path)
// This function is exported because it allows for an efficient readdir implementation.
func ReadDirIV(dir string) (iv []byte, err error) {
dirfd, err := os.Open(dir)
fd, err := os.Open(filepath.Join(dir, DirIVFilename))
if err != nil {
return nil, err
}
defer dirfd.Close()
return ReadDirIVAt(dirfd)
defer fd.Close()
return fdReadDirIV(fd)
}
// ReadDirIVAt reads "gocryptfs.diriv" from the directory that is opened as "dirfd".
@ -44,7 +43,11 @@ func ReadDirIVAt(dirfd *os.File) (iv []byte, err error) {
}
fd := os.NewFile(uintptr(fdRaw), DirIVFilename)
defer fd.Close()
return fdReadDirIV(fd)
}
// fdReadDirIV reads and verifies the DirIV from an opened gocryptfs.diriv file.
func fdReadDirIV(fd *os.File) (iv []byte, err error) {
// We want to detect if the file is bigger than DirIVLen, so
// make the buffer 1 byte bigger than neccessary.
iv = make([]byte, DirIVLen+1)