reverse: add single-entry path cache
Speeds up the "ls -lR" benchmark from 2.6 seconds to 2.0.
This commit is contained in:
parent
ef089c9f80
commit
fe1705c55b
@ -82,18 +82,31 @@ func (rfs *ReverseFS) decryptPath(relPath string) (string, error) {
|
||||
if rfs.args.PlaintextNames || relPath == "" {
|
||||
return relPath, nil
|
||||
}
|
||||
// Check if the parent dir is in the cache
|
||||
cDir := saneDir(relPath)
|
||||
dirIV, pDir := rPathCache.lookup(cDir)
|
||||
if dirIV != nil {
|
||||
cName := filepath.Base(relPath)
|
||||
pName, err := rfs.rDecryptName(cName, dirIV, pDir)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Join(pDir, pName), nil
|
||||
}
|
||||
parts := strings.Split(relPath, "/")
|
||||
var transformedParts []string
|
||||
for i := range parts {
|
||||
// Start at the top and recurse
|
||||
currentCipherDir := filepath.Join(parts[:i]...)
|
||||
currentPlainDir := filepath.Join(transformedParts[:i]...)
|
||||
dirIV := derivePathIV(currentCipherDir, ivPurposeDirIV)
|
||||
dirIV = derivePathIV(currentCipherDir, ivPurposeDirIV)
|
||||
transformedPart, err := rfs.rDecryptName(parts[i], dirIV, currentPlainDir)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
transformedParts = append(transformedParts, transformedPart)
|
||||
}
|
||||
return filepath.Join(transformedParts...), nil
|
||||
pRelPath := filepath.Join(transformedParts...)
|
||||
rPathCache.store(cDir, dirIV, saneDir(pRelPath))
|
||||
return pRelPath, nil
|
||||
}
|
||||
|
41
internal/fusefrontend_reverse/rpath_cache.go
Normal file
41
internal/fusefrontend_reverse/rpath_cache.go
Normal file
@ -0,0 +1,41 @@
|
||||
package fusefrontend_reverse
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// rPathCacheContainer is a simple one entry path cache. Because the dirIV
|
||||
// is generated deterministically from the directory path, there is no need
|
||||
// to ever invalidate entries.
|
||||
type rPathCacheContainer struct {
|
||||
sync.Mutex
|
||||
// Relative ciphertext path to the directory
|
||||
cPath string
|
||||
// Relative plaintext path
|
||||
pPath string
|
||||
// Directory IV of the directory
|
||||
dirIV []byte
|
||||
}
|
||||
|
||||
func (c *rPathCacheContainer) lookup(cPath string) ([]byte, string) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
if cPath == c.cPath {
|
||||
//fmt.Printf("HIT %q\n", cPath)
|
||||
return c.dirIV, c.pPath
|
||||
}
|
||||
//fmt.Printf("MISS %q\n", cPath)
|
||||
return nil, ""
|
||||
}
|
||||
|
||||
// store - write entry for "cPath" into the cache
|
||||
func (c *rPathCacheContainer) store(cPath string, dirIV []byte, pPath string) {
|
||||
//fmt.Printf("STORE %q\n", cPath)
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
c.cPath = cPath
|
||||
c.dirIV = dirIV
|
||||
c.pPath = pPath
|
||||
}
|
||||
|
||||
var rPathCache rPathCacheContainer
|
Loading…
Reference in New Issue
Block a user