diff options
| author | Jakob Unterwurzacher | 2016-09-24 22:40:00 +0200 | 
|---|---|---|
| committer | Jakob Unterwurzacher | 2016-09-25 16:43:17 +0200 | 
| commit | 52a6f4f71ed464eb64dc05e0768d4af58bd2c195 (patch) | |
| tree | 52740abbd7a29135f6919c66e793ce9c49c0fe2d | |
| parent | 6ffd07f02aaf75f9a6a75982fd8c8cd3f279701b (diff) | |
reverse: add longnameParentCache
findLongnameParent has to read the whole directory to find the
right file; add a simple cache to avoid most directory scans.
| -rw-r--r-- | internal/fusefrontend_reverse/reverse_longnames.go | 51 | ||||
| -rw-r--r-- | internal/fusefrontend_reverse/rfs.go | 15 | 
2 files changed, 56 insertions, 10 deletions
| diff --git a/internal/fusefrontend_reverse/reverse_longnames.go b/internal/fusefrontend_reverse/reverse_longnames.go index 46e1791..487802f 100644 --- a/internal/fusefrontend_reverse/reverse_longnames.go +++ b/internal/fusefrontend_reverse/reverse_longnames.go @@ -3,7 +3,9 @@ package fusefrontend_reverse  import (  	"os"  	"path/filepath" +	"sync"  	"syscall" +	"time"  	"github.com/hanwen/go-fuse/fuse"  	"github.com/hanwen/go-fuse/fuse/nodefs" @@ -15,7 +17,37 @@ const (  	shortNameMax = 176  ) -func (rfs *reverseFS) findLongnameParent(dir string, dirIV []byte, longname string) (string, error) { +type dirIVNameStruct struct { +	dirIV [nametransform.DirIVLen]byte +	name  string +} + +var longnameParentCache map[string]string +var longnameCacheLock sync.Mutex + +// Very simple cache cleaner: Nuke it every hour +func longnameCacheCleaner() { +	for { +		time.Sleep(time.Hour) +		longnameCacheLock.Lock() +		longnameParentCache = map[string]string{} +		longnameCacheLock.Unlock() +	} +} + +func init() { +	longnameParentCache = map[string]string{} +	go longnameCacheCleaner() +} + +// findLongnameParent converts "gocryptfs.longname.XYZ" to the plaintext name +func (rfs *reverseFS) findLongnameParent(dir string, dirIV []byte, longname string) (plaintextName string, err error) { +	longnameCacheLock.Lock() +	hit := longnameParentCache[longname] +	longnameCacheLock.Unlock() +	if hit != "" { +		return hit, nil +	}  	absDir := filepath.Join(rfs.args.Cipherdir, dir)  	dirfd, err := os.Open(absDir)  	if err != nil { @@ -25,20 +57,27 @@ func (rfs *reverseFS) findLongnameParent(dir string, dirIV []byte, longname stri  	if err != nil {  		return "", err  	} -	for _, e := range dirEntries { -		if len(e) <= shortNameMax { +	longnameCacheLock.Lock() +	defer longnameCacheLock.Unlock() +	for _, plaintextName = range dirEntries { +		if len(plaintextName) <= shortNameMax {  			continue  		} -		cName := rfs.nameTransform.EncryptName(e, dirIV) +		cName := rfs.nameTransform.EncryptName(plaintextName, dirIV)  		if len(cName) <= syscall.NAME_MAX {  			panic("logic error or wrong shortNameMax constant?")  		}  		hName := nametransform.HashLongName(cName) +		longnameParentCache[hName] = plaintextName  		if longname == hName { -			return e, nil +			hit = plaintextName  		}  	} -	return "", syscall.ENOENT +	if hit == "" { +		return "", syscall.ENOENT +	} else { +		return hit, nil +	}  }  func (rfs *reverseFS) newNameFile(relPath string) (nodefs.File, fuse.Status) { diff --git a/internal/fusefrontend_reverse/rfs.go b/internal/fusefrontend_reverse/rfs.go index 7305687..9ebf91c 100644 --- a/internal/fusefrontend_reverse/rfs.go +++ b/internal/fusefrontend_reverse/rfs.go @@ -248,9 +248,15 @@ func (rfs *reverseFS) OpenDir(cipherPath string, context *fuse.Context) ([]fuse.  	if entries == nil {  		return nil, status  	} +	// Allocate maximum possible number of virtual files. +	// If all files have long names we need a virtual ".name" file for each, +	// plus one for gocryptfs.diriv. +	virtualFiles := make([]fuse.DirEntry, len(entries)+1)  	// Virtual gocryptfs.diriv file -	dirIVEntry := fuse.DirEntry{syscall.S_IFREG | 0400, nametransform.DirIVFilename} -	virtualFiles := []fuse.DirEntry{dirIVEntry} +	virtualFiles[0] = fuse.DirEntry{syscall.S_IFREG | 0400, nametransform.DirIVFilename} +	// Actually used entries +	nVirtual := 1 +  	// Encrypt names  	dirIV := deriveDirIV(cipherPath)  	for i := range entries { @@ -263,12 +269,13 @@ func (rfs *reverseFS) OpenDir(cipherPath string, context *fuse.Context) ([]fuse.  			if len(cName) > syscall.NAME_MAX {  				cName = nametransform.HashLongName(cName)  				dotNameFile := fuse.DirEntry{syscall.S_IFREG | 0600, cName + nametransform.LongNameSuffix} -				virtualFiles = append(virtualFiles, dotNameFile) +				virtualFiles[nVirtual] = dotNameFile +				nVirtual++  			}  		}  		entries[i].Name = cName  	} -	entries = append(entries, virtualFiles...) +	entries = append(entries, virtualFiles[:nVirtual]...)  	return entries, fuse.OK  } | 
