OpenDir performance: Read DirIV once and reuse it for all names
Formerly, we called decryptPath for every name. That resulted in a directory walk that reads in all diriv files on the way. Massive improvement for RM and LS (check performance.txt for details) VERSION UNTAR RM LS v0.4 48 5 1.5 v0.5-rc1 56 19 7 v0.5-rc1-1 54 9 4.1 <---- THIS VERSION
This commit is contained in:
parent
6f764b3867
commit
1d0a442405
@ -17,7 +17,7 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// DecryptName - decrypt base64-encoded encrypted filename "cipherName"
|
// DecryptName - decrypt base64-encoded encrypted filename "cipherName"
|
||||||
func (be *CryptFS) decryptName(cipherName string, iv []byte) (string, error) {
|
func (be *CryptFS) DecryptName(cipherName string, iv []byte) (string, error) {
|
||||||
|
|
||||||
// Make sure relative symlinks still work after encryption
|
// Make sure relative symlinks still work after encryption
|
||||||
// by passing these through unchanged
|
// by passing these through unchanged
|
||||||
@ -91,7 +91,7 @@ func (be *CryptFS) TranslatePathZeroIV(path string, op int) (string, error) {
|
|||||||
if op == OpEncrypt {
|
if op == OpEncrypt {
|
||||||
newPart = be.encryptName(part, zeroIV)
|
newPart = be.encryptName(part, zeroIV)
|
||||||
} else {
|
} else {
|
||||||
newPart, err = be.decryptName(part, zeroIV)
|
newPart, err = be.DecryptName(part, zeroIV)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// readDirIV - read the "gocryptfs.diriv" file from "dir" (absolute path)
|
// readDirIV - read the "gocryptfs.diriv" file from "dir" (absolute ciphertext path)
|
||||||
func (be *CryptFS) readDirIV(dir string) (iv []byte, err error) {
|
func (be *CryptFS) ReadDirIV(dir string) (iv []byte, err error) {
|
||||||
ivfile := filepath.Join(dir, DIRIV_FILENAME)
|
ivfile := filepath.Join(dir, DIRIV_FILENAME)
|
||||||
Debug.Printf("readDirIV: reading %s\n", ivfile)
|
Debug.Printf("readDirIV: reading %s\n", ivfile)
|
||||||
iv, err = ioutil.ReadFile(ivfile)
|
iv, err = ioutil.ReadFile(ivfile)
|
||||||
@ -22,7 +22,7 @@ func (be *CryptFS) readDirIV(dir string) (iv []byte, err error) {
|
|||||||
return iv, nil
|
return iv, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteDirIV - create diriv file inside "dir" (absolute path)
|
// WriteDirIV - create diriv file inside "dir" (absolute ciphertext path)
|
||||||
// This function is exported because it is used from pathfs_frontend, main,
|
// This function is exported because it is used from pathfs_frontend, main,
|
||||||
// and also the automated tests.
|
// and also the automated tests.
|
||||||
func WriteDirIV(dir string) error {
|
func WriteDirIV(dir string) error {
|
||||||
@ -45,7 +45,7 @@ func (be *CryptFS) EncryptPathDirIV(plainPath string, rootDir string) (string, e
|
|||||||
var encryptedNames []string
|
var encryptedNames []string
|
||||||
plainNames := strings.Split(plainPath, "/")
|
plainNames := strings.Split(plainPath, "/")
|
||||||
for _, plainName := range plainNames {
|
for _, plainName := range plainNames {
|
||||||
iv, err := be.readDirIV(wd)
|
iv, err := be.ReadDirIV(wd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@ -66,11 +66,11 @@ func (be *CryptFS) DecryptPathDirIV(encryptedPath string, rootDir string) (strin
|
|||||||
encryptedNames := strings.Split(encryptedPath, "/")
|
encryptedNames := strings.Split(encryptedPath, "/")
|
||||||
Debug.Printf("DecryptPathDirIV: decrypting %v\n", encryptedNames)
|
Debug.Printf("DecryptPathDirIV: decrypting %v\n", encryptedNames)
|
||||||
for _, encryptedName := range encryptedNames {
|
for _, encryptedName := range encryptedNames {
|
||||||
iv, err := be.readDirIV(wd)
|
iv, err := be.ReadDirIV(wd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
plainName, err := be.decryptName(encryptedName, iv)
|
plainName, err := be.DecryptName(encryptedName, iv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
@ -75,36 +75,42 @@ func (fs *FS) OpenDir(dirName string, context *fuse.Context) ([]fuse.DirEntry, f
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fuse.ToStatus(err)
|
return nil, fuse.ToStatus(err)
|
||||||
}
|
}
|
||||||
|
// Read ciphertext directory
|
||||||
cipherEntries, status := fs.FileSystem.OpenDir(cDirName, context)
|
cipherEntries, status := fs.FileSystem.OpenDir(cDirName, context)
|
||||||
var plain []fuse.DirEntry
|
if cipherEntries == nil {
|
||||||
if cipherEntries != nil {
|
return nil, status
|
||||||
for i := range cipherEntries {
|
}
|
||||||
cName := cipherEntries[i].Name
|
// Get DirIV (stays zero if DirIV if off)
|
||||||
if dirName == "" && cName == cryptfs.ConfDefaultName {
|
cachedIV := make([]byte, cryptfs.DIRIV_LEN)
|
||||||
// silently ignore "gocryptfs.conf" in the top level dir
|
if fs.args.DirIV {
|
||||||
continue
|
// Read the DirIV once and use it for all later name decryptions
|
||||||
}
|
cDirAbsPath := filepath.Join(fs.args.Cipherdir, cDirName)
|
||||||
if fs.args.DirIV && cName == cryptfs.DIRIV_FILENAME {
|
cachedIV, err = fs.CryptFS.ReadDirIV(cDirAbsPath)
|
||||||
// silently ignore "gocryptfs.diriv" everywhere if dirIV is enabled
|
if err != nil {
|
||||||
continue
|
return nil, fuse.ToStatus(err)
|
||||||
}
|
|
||||||
var name string
|
|
||||||
if !fs.args.DirIV {
|
|
||||||
name, err = fs.decryptPath(cName)
|
|
||||||
} else {
|
|
||||||
// When dirIV is enabled we need the full path to be able to decrypt it
|
|
||||||
cPath := filepath.Join(cDirName, cName)
|
|
||||||
name, err = fs.decryptPath(cPath)
|
|
||||||
name = filepath.Base(name)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
cryptfs.Warn.Printf("Invalid name \"%s\" in dir \"%s\": %s\n", cName, dirName, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
cipherEntries[i].Name = name
|
|
||||||
plain = append(plain, cipherEntries[i])
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Decrypt filenames
|
||||||
|
var plain []fuse.DirEntry
|
||||||
|
for i := range cipherEntries {
|
||||||
|
cName := cipherEntries[i].Name
|
||||||
|
if dirName == "" && cName == cryptfs.ConfDefaultName {
|
||||||
|
// silently ignore "gocryptfs.conf" in the top level dir
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if fs.args.DirIV && cName == cryptfs.DIRIV_FILENAME {
|
||||||
|
// silently ignore "gocryptfs.diriv" everywhere if dirIV is enabled
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var name string
|
||||||
|
name, err = fs.CryptFS.DecryptName(cName, cachedIV)
|
||||||
|
if err != nil {
|
||||||
|
cryptfs.Warn.Printf("Invalid name \"%s\" in dir \"%s\": %s\n", cName, dirName, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
cipherEntries[i].Name = name
|
||||||
|
plain = append(plain, cipherEntries[i])
|
||||||
|
}
|
||||||
return plain, status
|
return plain, status
|
||||||
}
|
}
|
||||||
|
|
||||||
|
10
performance.txt
Normal file
10
performance.txt
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
All test performed on tmpfs, /tmp/a mounted on /tmp/b.
|
||||||
|
|
||||||
|
UNTAR: tar xfz ../linux-3.0.tar.gz
|
||||||
|
LS: ls -lR > /dev/null
|
||||||
|
RM: rm -rf linux-3.0
|
||||||
|
|
||||||
|
VERSION UNTAR LS RM
|
||||||
|
v0.4 48 1.5 5
|
||||||
|
v0.5-rc1 56 7 19
|
||||||
|
v0.5-rc1-1 54 4.1 9
|
Loading…
Reference in New Issue
Block a user