aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Unterwurzacher2015-11-29 19:57:48 +0100
committerJakob Unterwurzacher2015-11-29 20:03:37 +0100
commit1d0a442405e8fc7a0742a8f8db2ea0f874f750a5 (patch)
treeb2ff9e44da9792f7a0abbc9abdf99f6a6e2cef2e
parent6f764b386786b92023fa696594105f702226b3ff (diff)
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
-rw-r--r--cryptfs/cryptfs_names.go4
-rw-r--r--cryptfs/names_diriv.go12
-rw-r--r--pathfs_frontend/fs.go58
-rw-r--r--performance.txt10
4 files changed, 50 insertions, 34 deletions
diff --git a/cryptfs/cryptfs_names.go b/cryptfs/cryptfs_names.go
index 2a5f158..8f8486b 100644
--- a/cryptfs/cryptfs_names.go
+++ b/cryptfs/cryptfs_names.go
@@ -17,7 +17,7 @@ const (
)
// 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
// by passing these through unchanged
@@ -91,7 +91,7 @@ func (be *CryptFS) TranslatePathZeroIV(path string, op int) (string, error) {
if op == OpEncrypt {
newPart = be.encryptName(part, zeroIV)
} else {
- newPart, err = be.decryptName(part, zeroIV)
+ newPart, err = be.DecryptName(part, zeroIV)
if err != nil {
return "", err
}
diff --git a/cryptfs/names_diriv.go b/cryptfs/names_diriv.go
index be7a2b1..ae8545b 100644
--- a/cryptfs/names_diriv.go
+++ b/cryptfs/names_diriv.go
@@ -7,8 +7,8 @@ import (
"strings"
)
-// readDirIV - read the "gocryptfs.diriv" file from "dir" (absolute path)
-func (be *CryptFS) readDirIV(dir string) (iv []byte, err error) {
+// 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)
Debug.Printf("readDirIV: reading %s\n", ivfile)
iv, err = ioutil.ReadFile(ivfile)
@@ -22,7 +22,7 @@ func (be *CryptFS) readDirIV(dir string) (iv []byte, err error) {
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,
// and also the automated tests.
func WriteDirIV(dir string) error {
@@ -45,7 +45,7 @@ func (be *CryptFS) EncryptPathDirIV(plainPath string, rootDir string) (string, e
var encryptedNames []string
plainNames := strings.Split(plainPath, "/")
for _, plainName := range plainNames {
- iv, err := be.readDirIV(wd)
+ iv, err := be.ReadDirIV(wd)
if err != nil {
return "", err
}
@@ -66,11 +66,11 @@ func (be *CryptFS) DecryptPathDirIV(encryptedPath string, rootDir string) (strin
encryptedNames := strings.Split(encryptedPath, "/")
Debug.Printf("DecryptPathDirIV: decrypting %v\n", encryptedNames)
for _, encryptedName := range encryptedNames {
- iv, err := be.readDirIV(wd)
+ iv, err := be.ReadDirIV(wd)
if err != nil {
return "", err
}
- plainName, err := be.decryptName(encryptedName, iv)
+ plainName, err := be.DecryptName(encryptedName, iv)
if err != nil {
return "", err
}
diff --git a/pathfs_frontend/fs.go b/pathfs_frontend/fs.go
index e68e6bc..fe9a8b0 100644
--- a/pathfs_frontend/fs.go
+++ b/pathfs_frontend/fs.go
@@ -75,35 +75,41 @@ func (fs *FS) OpenDir(dirName string, context *fuse.Context) ([]fuse.DirEntry, f
if err != nil {
return nil, fuse.ToStatus(err)
}
+ // Read ciphertext directory
cipherEntries, status := fs.FileSystem.OpenDir(cDirName, context)
+ if cipherEntries == nil {
+ return nil, status
+ }
+ // Get DirIV (stays zero if DirIV if off)
+ cachedIV := make([]byte, cryptfs.DIRIV_LEN)
+ if fs.args.DirIV {
+ // Read the DirIV once and use it for all later name decryptions
+ cDirAbsPath := filepath.Join(fs.args.Cipherdir, cDirName)
+ cachedIV, err = fs.CryptFS.ReadDirIV(cDirAbsPath)
+ if err != nil {
+ return nil, fuse.ToStatus(err)
+ }
+ }
+ // Decrypt filenames
var plain []fuse.DirEntry
- if cipherEntries != nil {
- 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
- 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])
+ 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
}
diff --git a/performance.txt b/performance.txt
new file mode 100644
index 0000000..55678c3
--- /dev/null
+++ b/performance.txt
@@ -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