From b34a665da4a15762fc2e21e125ba705f691ec5d7 Mon Sep 17 00:00:00 2001 From: Jakob Unterwurzacher Date: Wed, 21 Sep 2016 23:22:13 +0200 Subject: [PATCH] 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 --- internal/nametransform/diriv.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/internal/nametransform/diriv.go b/internal/nametransform/diriv.go index 11bd729..66548f1 100644 --- a/internal/nametransform/diriv.go +++ b/internal/nametransform/diriv.go @@ -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)