diff options
author | Jakob Unterwurzacher | 2015-11-29 21:41:38 +0100 |
---|---|---|
committer | Jakob Unterwurzacher | 2015-11-29 21:41:38 +0100 |
commit | 20b058a33335f48812864513cc13ea0a276aaaa3 (patch) | |
tree | 60baeaf7f3fe89e896a3a84a934079769d865215 /cryptfs/names_diriv.go | |
parent | 1d0a442405e8fc7a0742a8f8db2ea0f874f750a5 (diff) |
Add single-element cache for DirIV lookup
Another 3x performance boost for applications that walk the
directory tree.
Excerpt from performance.txt:
VERSION UNTAR LS RM
v0.4 48 1.5 5
v0.5-rc1 56 7 19
v0.5-rc1-1 54 4.1 9
v0.5-rc1-2 45 1.7 3.4 <---- THIS VERSION
Diffstat (limited to 'cryptfs/names_diriv.go')
-rw-r--r-- | cryptfs/names_diriv.go | 59 |
1 files changed, 57 insertions, 2 deletions
diff --git a/cryptfs/names_diriv.go b/cryptfs/names_diriv.go index ae8545b..9012e48 100644 --- a/cryptfs/names_diriv.go +++ b/cryptfs/names_diriv.go @@ -5,8 +5,47 @@ import ( "io/ioutil" "path/filepath" "strings" + "sync" ) +// A simple one-entry DirIV cache +type DirIVCache struct { + // Invalidated? + cleared bool + // The DirIV + iv []byte + // Directory the DirIV belongs to + dir string + // Ecrypted version of "dir" + translatedDir string + // Synchronisation + lock sync.RWMutex +} + +func (c *DirIVCache) lookup(dir string) (bool, []byte, string) { + c.lock.RLock() + defer c.lock.RUnlock() + if !c.cleared && c.dir == dir { + return true, c.iv, c.translatedDir + } + return false, nil, "" +} + +func (c *DirIVCache) store(dir string, iv []byte, translatedDir string) { + c.lock.Lock() + defer c.lock.Unlock() + c.cleared = false + c.iv = iv + c.dir = dir + c.translatedDir = translatedDir +} + +func (c *DirIVCache) Clear() { + c.lock.Lock() + defer c.lock.Unlock() + c.cleared = true +} + // readDirIV - read the "gocryptfs.diriv" file from "dir" (absolute ciphertext path) func (be *CryptFS) ReadDirIV(dir string) (iv []byte, err error) { ivfile := filepath.Join(dir, DIRIV_FILENAME) @@ -41,11 +80,23 @@ func (be *CryptFS) EncryptPathDirIV(plainPath string, rootDir string) (string, e if plainPath == "" { return plainPath, nil } + // Check if the DirIV is cached + parentDir := filepath.Dir(plainPath) + found, iv, cParentDir := be.DirIVCacheEnc.lookup(parentDir) + if found { + //fmt.Print("h") + baseName := filepath.Base(plainPath) + cBaseName := be.encryptName(baseName, iv) + cPath := cParentDir + "/" + cBaseName + return cPath, nil + } + // Walk the directory tree var wd = rootDir var encryptedNames []string + var err error plainNames := strings.Split(plainPath, "/") for _, plainName := range plainNames { - iv, err := be.ReadDirIV(wd) + iv, err = be.ReadDirIV(wd) if err != nil { return "", err } @@ -53,7 +104,11 @@ func (be *CryptFS) EncryptPathDirIV(plainPath string, rootDir string) (string, e encryptedNames = append(encryptedNames, encryptedName) wd = filepath.Join(wd, encryptedName) } - return filepath.Join(encryptedNames...), nil + // Cache the final DirIV + cPath := strings.Join(encryptedNames, "/") + cParentDir = filepath.Dir(cPath) + be.DirIVCacheEnc.store(parentDir, iv, cParentDir) + return cPath, nil } // DecryptPathDirIV - encrypt path using CBC with DirIV |