reverse: add longnameParentCache
findLongnameParent has to read the whole directory to find the right file; add a simple cache to avoid most directory scans.
This commit is contained in:
parent
6ffd07f02a
commit
52a6f4f71e
@ -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) {
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user