Commit 719d3d2b authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

unionfs: hide types AutoUnionFs, UnionFs, DirCache, CachingFileSystem

parent 3c0c2f7e
...@@ -16,8 +16,8 @@ import ( ...@@ -16,8 +16,8 @@ import (
) )
type knownFs struct { type knownFs struct {
*UnionFs unionFS pathfs.FileSystem
*pathfs.PathNodeFs nodeFS *pathfs.PathNodeFs
} }
// Creates unions for all files under a given directory, // Creates unions for all files under a given directory,
...@@ -25,7 +25,7 @@ type knownFs struct { ...@@ -25,7 +25,7 @@ type knownFs struct {
// D/READONLY symlink. // D/READONLY symlink.
// //
// A union for A/B/C will placed under directory A-B-C. // A union for A/B/C will placed under directory A-B-C.
type AutoUnionFs struct { type autoUnionFs struct {
pathfs.FileSystem pathfs.FileSystem
debug bool debug bool
...@@ -64,11 +64,19 @@ const ( ...@@ -64,11 +64,19 @@ const (
_SCAN_CONFIG = ".scan_config" _SCAN_CONFIG = ".scan_config"
) )
func NewAutoUnionFs(directory string, options AutoUnionFsOptions) *AutoUnionFs { // A pathfs.FileSystem that we can hookup with MountState and
// FileSystemConnector
type RootFileSystem interface {
SetMountState(state *fuse.MountState)
SetFileSystemConnector(conn *fuse.FileSystemConnector)
pathfs.FileSystem
}
func NewAutoUnionFs(directory string, options AutoUnionFsOptions) RootFileSystem {
if options.HideReadonly { if options.HideReadonly {
options.HiddenFiles = append(options.HiddenFiles, _READONLY) options.HiddenFiles = append(options.HiddenFiles, _READONLY)
} }
a := &AutoUnionFs{ a := &autoUnionFs{
knownFileSystems: make(map[string]knownFs), knownFileSystems: make(map[string]knownFs),
nameRootMap: make(map[string]string), nameRootMap: make(map[string]string),
options: &options, options: &options,
...@@ -83,18 +91,18 @@ func NewAutoUnionFs(directory string, options AutoUnionFsOptions) *AutoUnionFs { ...@@ -83,18 +91,18 @@ func NewAutoUnionFs(directory string, options AutoUnionFsOptions) *AutoUnionFs {
return a return a
} }
func (fs *AutoUnionFs) String() string { func (fs *autoUnionFs) String() string {
return fmt.Sprintf("AutoUnionFs(%s)", fs.root) return fmt.Sprintf("autoUnionFs(%s)", fs.root)
} }
func (fs *AutoUnionFs) OnMount(nodeFs *pathfs.PathNodeFs) { func (fs *autoUnionFs) OnMount(nodeFs *pathfs.PathNodeFs) {
fs.nodeFs = nodeFs fs.nodeFs = nodeFs
if fs.options.UpdateOnMount { if fs.options.UpdateOnMount {
time.AfterFunc(100*time.Millisecond, func() { fs.updateKnownFses() }) time.AfterFunc(100*time.Millisecond, func() { fs.updateKnownFses() })
} }
} }
func (fs *AutoUnionFs) addAutomaticFs(roots []string) { func (fs *autoUnionFs) addAutomaticFs(roots []string) {
relative := strings.TrimLeft(strings.Replace(roots[0], fs.root, "", -1), "/") relative := strings.TrimLeft(strings.Replace(roots[0], fs.root, "", -1), "/")
name := strings.Replace(relative, "/", "-", -1) name := strings.Replace(relative, "/", "-", -1)
...@@ -103,7 +111,7 @@ func (fs *AutoUnionFs) addAutomaticFs(roots []string) { ...@@ -103,7 +111,7 @@ func (fs *AutoUnionFs) addAutomaticFs(roots []string) {
} }
} }
func (fs *AutoUnionFs) createFs(name string, roots []string) fuse.Status { func (fs *autoUnionFs) createFs(name string, roots []string) fuse.Status {
fs.lock.Lock() fs.lock.Lock()
defer fs.lock.Unlock() defer fs.lock.Unlock()
...@@ -116,7 +124,7 @@ func (fs *AutoUnionFs) createFs(name string, roots []string) fuse.Status { ...@@ -116,7 +124,7 @@ func (fs *AutoUnionFs) createFs(name string, roots []string) fuse.Status {
} }
known := fs.knownFileSystems[name] known := fs.knownFileSystems[name]
if known.UnionFs != nil { if known.unionFS != nil {
log.Println("Already have a workspace:", name) log.Println("Already have a workspace:", name)
return fuse.EBUSY return fuse.EBUSY
} }
...@@ -140,12 +148,12 @@ func (fs *AutoUnionFs) createFs(name string, roots []string) fuse.Status { ...@@ -140,12 +148,12 @@ func (fs *AutoUnionFs) createFs(name string, roots []string) fuse.Status {
return code return code
} }
func (fs *AutoUnionFs) rmFs(name string) (code fuse.Status) { func (fs *autoUnionFs) rmFs(name string) (code fuse.Status) {
fs.lock.Lock() fs.lock.Lock()
defer fs.lock.Unlock() defer fs.lock.Unlock()
known := fs.knownFileSystems[name] known := fs.knownFileSystems[name]
if known.UnionFs == nil { if known.unionFS == nil {
return fuse.ENOENT return fuse.ENOENT
} }
...@@ -160,7 +168,7 @@ func (fs *AutoUnionFs) rmFs(name string) (code fuse.Status) { ...@@ -160,7 +168,7 @@ func (fs *AutoUnionFs) rmFs(name string) (code fuse.Status) {
return code return code
} }
func (fs *AutoUnionFs) addFs(name string, roots []string) (code fuse.Status) { func (fs *autoUnionFs) addFs(name string, roots []string) (code fuse.Status) {
if name == _CONFIG || name == _STATUS || name == _SCAN_CONFIG { if name == _CONFIG || name == _STATUS || name == _SCAN_CONFIG {
log.Printf("Illegal name %q for overlay: %v", name, roots) log.Printf("Illegal name %q for overlay: %v", name, roots)
return fuse.EINVAL return fuse.EINVAL
...@@ -168,7 +176,7 @@ func (fs *AutoUnionFs) addFs(name string, roots []string) (code fuse.Status) { ...@@ -168,7 +176,7 @@ func (fs *AutoUnionFs) addFs(name string, roots []string) (code fuse.Status) {
return fs.createFs(name, roots) return fs.createFs(name, roots)
} }
func (fs *AutoUnionFs) getRoots(path string) []string { func (fs *autoUnionFs) getRoots(path string) []string {
ro := filepath.Join(path, _READONLY) ro := filepath.Join(path, _READONLY)
fi, err := os.Lstat(ro) fi, err := os.Lstat(ro)
fiDir, errDir := os.Stat(ro) fiDir, errDir := os.Stat(ro)
...@@ -184,7 +192,7 @@ func (fs *AutoUnionFs) getRoots(path string) []string { ...@@ -184,7 +192,7 @@ func (fs *AutoUnionFs) getRoots(path string) []string {
return nil return nil
} }
func (fs *AutoUnionFs) visit(path string, fi os.FileInfo, err error) error { func (fs *autoUnionFs) visit(path string, fi os.FileInfo, err error) error {
if fi != nil && fi.IsDir() { if fi != nil && fi.IsDir() {
roots := fs.getRoots(path) roots := fs.getRoots(path)
if roots != nil { if roots != nil {
...@@ -194,7 +202,7 @@ func (fs *AutoUnionFs) visit(path string, fi os.FileInfo, err error) error { ...@@ -194,7 +202,7 @@ func (fs *AutoUnionFs) visit(path string, fi os.FileInfo, err error) error {
return nil return nil
} }
func (fs *AutoUnionFs) updateKnownFses() { func (fs *autoUnionFs) updateKnownFses() {
log.Println("Looking for new filesystems") log.Println("Looking for new filesystems")
// We unroll the first level of entries in the root manually in order // We unroll the first level of entries in the root manually in order
// to allow symbolic links on that level. // to allow symbolic links on that level.
...@@ -215,7 +223,7 @@ func (fs *AutoUnionFs) updateKnownFses() { ...@@ -215,7 +223,7 @@ func (fs *AutoUnionFs) updateKnownFses() {
log.Println("Done looking") log.Println("Done looking")
} }
func (fs *AutoUnionFs) Readlink(path string, context *fuse.Context) (out string, code fuse.Status) { func (fs *autoUnionFs) Readlink(path string, context *fuse.Context) (out string, code fuse.Status) {
comps := strings.Split(path, string(filepath.Separator)) comps := strings.Split(path, string(filepath.Separator))
if comps[0] == _STATUS && comps[1] == _ROOT { if comps[0] == _STATUS && comps[1] == _ROOT {
return fs.root, fuse.OK return fs.root, fuse.OK
...@@ -241,13 +249,13 @@ func (fs *AutoUnionFs) Readlink(path string, context *fuse.Context) (out string, ...@@ -241,13 +249,13 @@ func (fs *AutoUnionFs) Readlink(path string, context *fuse.Context) (out string,
return "", fuse.ENOENT return "", fuse.ENOENT
} }
func (fs *AutoUnionFs) getUnionFs(name string) *UnionFs { func (fs *autoUnionFs) getUnionFs(name string) pathfs.FileSystem {
fs.lock.RLock() fs.lock.RLock()
defer fs.lock.RUnlock() defer fs.lock.RUnlock()
return fs.knownFileSystems[name].UnionFs return fs.knownFileSystems[name].unionFS
} }
func (fs *AutoUnionFs) Symlink(pointedTo string, linkName string, context *fuse.Context) (code fuse.Status) { func (fs *autoUnionFs) Symlink(pointedTo string, linkName string, context *fuse.Context) (code fuse.Status) {
comps := strings.Split(linkName, "/") comps := strings.Split(linkName, "/")
if len(comps) != 2 { if len(comps) != 2 {
return fuse.EPERM return fuse.EPERM
...@@ -270,7 +278,7 @@ func (fs *AutoUnionFs) Symlink(pointedTo string, linkName string, context *fuse. ...@@ -270,7 +278,7 @@ func (fs *AutoUnionFs) Symlink(pointedTo string, linkName string, context *fuse.
return fuse.EPERM return fuse.EPERM
} }
func (fs *AutoUnionFs) SetDebug(b bool) { func (fs *autoUnionFs) SetDebug(b bool) {
// Officially, this should use locking, but we don't care // Officially, this should use locking, but we don't care
// about race conditions here. // about race conditions here.
fs.debug = b fs.debug = b
...@@ -279,11 +287,11 @@ func (fs *AutoUnionFs) SetDebug(b bool) { ...@@ -279,11 +287,11 @@ func (fs *AutoUnionFs) SetDebug(b bool) {
fs.mountState.SetDebug(b) fs.mountState.SetDebug(b)
} }
func (fs *AutoUnionFs) hasDebug() bool { func (fs *autoUnionFs) hasDebug() bool {
return fs.debug return fs.debug
} }
func (fs *AutoUnionFs) Unlink(path string, context *fuse.Context) (code fuse.Status) { func (fs *autoUnionFs) Unlink(path string, context *fuse.Context) (code fuse.Status) {
comps := strings.Split(path, "/") comps := strings.Split(path, "/")
if len(comps) != 2 { if len(comps) != 2 {
return fuse.EPERM return fuse.EPERM
...@@ -303,11 +311,11 @@ func (fs *AutoUnionFs) Unlink(path string, context *fuse.Context) (code fuse.Sta ...@@ -303,11 +311,11 @@ func (fs *AutoUnionFs) Unlink(path string, context *fuse.Context) (code fuse.Sta
} }
// Must define this, because ENOSYS will suspend all GetXAttr calls. // Must define this, because ENOSYS will suspend all GetXAttr calls.
func (fs *AutoUnionFs) GetXAttr(name string, attr string, context *fuse.Context) ([]byte, fuse.Status) { func (fs *autoUnionFs) GetXAttr(name string, attr string, context *fuse.Context) ([]byte, fuse.Status) {
return nil, fuse.ENODATA return nil, fuse.ENODATA
} }
func (fs *AutoUnionFs) GetAttr(path string, context *fuse.Context) (*fuse.Attr, fuse.Status) { func (fs *autoUnionFs) GetAttr(path string, context *fuse.Context) (*fuse.Attr, fuse.Status) {
if path == "" || path == _CONFIG || path == _STATUS { if path == "" || path == _CONFIG || path == _STATUS {
a := &fuse.Attr{ a := &fuse.Attr{
Mode: fuse.S_IFDIR | 0755, Mode: fuse.S_IFDIR | 0755,
...@@ -368,7 +376,7 @@ func (fs *AutoUnionFs) GetAttr(path string, context *fuse.Context) (*fuse.Attr, ...@@ -368,7 +376,7 @@ func (fs *AutoUnionFs) GetAttr(path string, context *fuse.Context) (*fuse.Attr,
return nil, fuse.ENOENT return nil, fuse.ENOENT
} }
func (fs *AutoUnionFs) StatusDir() (stream []fuse.DirEntry, status fuse.Status) { func (fs *autoUnionFs) StatusDir() (stream []fuse.DirEntry, status fuse.Status) {
stream = make([]fuse.DirEntry, 0, 10) stream = make([]fuse.DirEntry, 0, 10)
stream = []fuse.DirEntry{ stream = []fuse.DirEntry{
{Name: _VERSION, Mode: fuse.S_IFREG | 0644}, {Name: _VERSION, Mode: fuse.S_IFREG | 0644},
...@@ -383,17 +391,17 @@ func (fs *AutoUnionFs) StatusDir() (stream []fuse.DirEntry, status fuse.Status) ...@@ -383,17 +391,17 @@ func (fs *AutoUnionFs) StatusDir() (stream []fuse.DirEntry, status fuse.Status)
// SetMountState stores the MountState, which is necessary for // SetMountState stores the MountState, which is necessary for
// retrieving debug data. // retrieving debug data.
func (fs *AutoUnionFs) SetMountState(state *fuse.MountState) { func (fs *autoUnionFs) SetMountState(state *fuse.MountState) {
fs.mountState = state fs.mountState = state
} }
func (fs *AutoUnionFs) SetFileSystemConnector(conn *fuse.FileSystemConnector) { func (fs *autoUnionFs) SetFileSystemConnector(conn *fuse.FileSystemConnector) {
fs.connector = conn fs.connector = conn
} }
func (fs *AutoUnionFs) DebugData() string { func (fs *autoUnionFs) DebugData() string {
if fs.mountState == nil { if fs.mountState == nil {
return "AutoUnionFs.mountState not set" return "autoUnionFs.mountState not set"
} }
setting := fs.mountState.KernelSettings() setting := fs.mountState.KernelSettings()
msg := fmt.Sprintf( msg := fmt.Sprintf(
...@@ -411,7 +419,7 @@ func (fs *AutoUnionFs) DebugData() string { ...@@ -411,7 +419,7 @@ func (fs *AutoUnionFs) DebugData() string {
return msg return msg
} }
func (fs *AutoUnionFs) Open(path string, flags uint32, context *fuse.Context) (fuse.File, fuse.Status) { func (fs *autoUnionFs) Open(path string, flags uint32, context *fuse.Context) (fuse.File, fuse.Status) {
if path == filepath.Join(_STATUS, _DEBUG) { if path == filepath.Join(_STATUS, _DEBUG) {
if flags&fuse.O_ANYWRITE != 0 { if flags&fuse.O_ANYWRITE != 0 {
return nil, fuse.EPERM return nil, fuse.EPERM
...@@ -434,7 +442,7 @@ func (fs *AutoUnionFs) Open(path string, flags uint32, context *fuse.Context) (f ...@@ -434,7 +442,7 @@ func (fs *AutoUnionFs) Open(path string, flags uint32, context *fuse.Context) (f
return nil, fuse.ENOENT return nil, fuse.ENOENT
} }
func (fs *AutoUnionFs) Truncate(name string, offset uint64, context *fuse.Context) (code fuse.Status) { func (fs *autoUnionFs) Truncate(name string, offset uint64, context *fuse.Context) (code fuse.Status) {
if name != filepath.Join(_CONFIG, _SCAN_CONFIG) { if name != filepath.Join(_CONFIG, _SCAN_CONFIG) {
log.Println("Huh? Truncating unsupported write file", name) log.Println("Huh? Truncating unsupported write file", name)
return fuse.EPERM return fuse.EPERM
...@@ -442,7 +450,7 @@ func (fs *AutoUnionFs) Truncate(name string, offset uint64, context *fuse.Contex ...@@ -442,7 +450,7 @@ func (fs *AutoUnionFs) Truncate(name string, offset uint64, context *fuse.Contex
return fuse.OK return fuse.OK
} }
func (fs *AutoUnionFs) OpenDir(name string, context *fuse.Context) (stream []fuse.DirEntry, status fuse.Status) { func (fs *autoUnionFs) OpenDir(name string, context *fuse.Context) (stream []fuse.DirEntry, status fuse.Status) {
switch name { switch name {
case _STATUS: case _STATUS:
return fs.StatusDir() return fs.StatusDir()
...@@ -481,6 +489,6 @@ func (fs *AutoUnionFs) OpenDir(name string, context *fuse.Context) (stream []fus ...@@ -481,6 +489,6 @@ func (fs *AutoUnionFs) OpenDir(name string, context *fuse.Context) (stream []fus
return stream, status return stream, status
} }
func (fs *AutoUnionFs) StatFs(name string) *fuse.StatfsOut { func (fs *autoUnionFs) StatFs(name string) *fuse.StatfsOut {
return &fuse.StatfsOut{} return &fuse.StatfsOut{}
} }
...@@ -35,7 +35,7 @@ type linkResponse struct { ...@@ -35,7 +35,7 @@ type linkResponse struct {
} }
// Caches filesystem metadata. // Caches filesystem metadata.
type CachingFileSystem struct { type cachingFileSystem struct {
pathfs.FileSystem pathfs.FileSystem
attributes *TimedCache attributes *TimedCache
...@@ -80,8 +80,8 @@ func readLink(fs pathfs.FileSystem, name string) *linkResponse { ...@@ -80,8 +80,8 @@ func readLink(fs pathfs.FileSystem, name string) *linkResponse {
} }
} }
func NewCachingFileSystem(fs pathfs.FileSystem, ttl time.Duration) *CachingFileSystem { func NewCachingFileSystem(fs pathfs.FileSystem, ttl time.Duration) pathfs.FileSystem {
c := new(CachingFileSystem) c := new(cachingFileSystem)
c.FileSystem = fs c.FileSystem = fs
c.attributes = NewTimedCache(func(n string) (interface{}, bool) { c.attributes = NewTimedCache(func(n string) (interface{}, bool) {
a := getAttr(fs, n) a := getAttr(fs, n)
...@@ -102,13 +102,13 @@ func NewCachingFileSystem(fs pathfs.FileSystem, ttl time.Duration) *CachingFileS ...@@ -102,13 +102,13 @@ func NewCachingFileSystem(fs pathfs.FileSystem, ttl time.Duration) *CachingFileS
return c return c
} }
func (fs *CachingFileSystem) DropCache() { func (fs *cachingFileSystem) DropCache() {
for _, c := range []*TimedCache{fs.attributes, fs.dirs, fs.links, fs.xattr} { for _, c := range []*TimedCache{fs.attributes, fs.dirs, fs.links, fs.xattr} {
c.DropAll(nil) c.DropAll(nil)
} }
} }
func (fs *CachingFileSystem) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Status) { func (fs *cachingFileSystem) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Status) {
if name == _DROP_CACHE { if name == _DROP_CACHE {
return &fuse.Attr{ return &fuse.Attr{
Mode: fuse.S_IFREG | 0777, Mode: fuse.S_IFREG | 0777,
...@@ -119,27 +119,27 @@ func (fs *CachingFileSystem) GetAttr(name string, context *fuse.Context) (*fuse. ...@@ -119,27 +119,27 @@ func (fs *CachingFileSystem) GetAttr(name string, context *fuse.Context) (*fuse.
return r.Attr, r.Status return r.Attr, r.Status
} }
func (fs *CachingFileSystem) GetXAttr(name string, attr string, context *fuse.Context) ([]byte, fuse.Status) { func (fs *cachingFileSystem) GetXAttr(name string, attr string, context *fuse.Context) ([]byte, fuse.Status) {
key := name + _XATTRSEP + attr key := name + _XATTRSEP + attr
r := fs.xattr.Get(key).(*xattrResponse) r := fs.xattr.Get(key).(*xattrResponse)
return r.data, r.Status return r.data, r.Status
} }
func (fs *CachingFileSystem) Readlink(name string, context *fuse.Context) (string, fuse.Status) { func (fs *cachingFileSystem) Readlink(name string, context *fuse.Context) (string, fuse.Status) {
r := fs.links.Get(name).(*linkResponse) r := fs.links.Get(name).(*linkResponse)
return r.linkContent, r.Status return r.linkContent, r.Status
} }
func (fs *CachingFileSystem) OpenDir(name string, context *fuse.Context) (stream []fuse.DirEntry, status fuse.Status) { func (fs *cachingFileSystem) OpenDir(name string, context *fuse.Context) (stream []fuse.DirEntry, status fuse.Status) {
r := fs.dirs.Get(name).(*dirResponse) r := fs.dirs.Get(name).(*dirResponse)
return r.entries, r.Status return r.entries, r.Status
} }
func (fs *CachingFileSystem) String() string { func (fs *cachingFileSystem) String() string {
return fmt.Sprintf("CachingFileSystem(%v)", fs.FileSystem) return fmt.Sprintf("cachingFileSystem(%v)", fs.FileSystem)
} }
func (fs *CachingFileSystem) Open(name string, flags uint32, context *fuse.Context) (f fuse.File, status fuse.Status) { func (fs *cachingFileSystem) Open(name string, flags uint32, context *fuse.Context) (f fuse.File, status fuse.Status) {
if flags&fuse.O_ANYWRITE != 0 && name == _DROP_CACHE { if flags&fuse.O_ANYWRITE != 0 && name == _DROP_CACHE {
log.Println("Dropping cache for", fs) log.Println("Dropping cache for", fs)
fs.DropCache() fs.DropCache()
......
...@@ -6,7 +6,7 @@ import ( ...@@ -6,7 +6,7 @@ import (
"github.com/hanwen/go-fuse/fuse/pathfs" "github.com/hanwen/go-fuse/fuse/pathfs"
) )
func NewUnionFsFromRoots(roots []string, opts *UnionFsOptions, roCaching bool) (*UnionFs, error) { func NewUnionFsFromRoots(roots []string, opts *UnionFsOptions, roCaching bool) (pathfs.FileSystem, error) {
fses := make([]pathfs.FileSystem, 0) fses := make([]pathfs.FileSystem, 0)
for i, r := range roots { for i, r := range roots {
var fs pathfs.FileSystem var fs pathfs.FileSystem
......
...@@ -10,7 +10,7 @@ import ( ...@@ -10,7 +10,7 @@ import (
) )
// newDirnameMap reads the contents of the given directory. On error, // newDirnameMap reads the contents of the given directory. On error,
// returns a nil map. This forces reloads in the DirCache until we // returns a nil map. This forces reloads in the dirCache until we
// succeed. // succeed.
func newDirnameMap(fs pathfs.FileSystem, dir string) map[string]bool { func newDirnameMap(fs pathfs.FileSystem, dir string) map[string]bool {
stream, code := fs.OpenDir(dir, nil) stream, code := fs.OpenDir(dir, nil)
...@@ -33,11 +33,11 @@ func newDirnameMap(fs pathfs.FileSystem, dir string) map[string]bool { ...@@ -33,11 +33,11 @@ func newDirnameMap(fs pathfs.FileSystem, dir string) map[string]bool {
return result return result
} }
// DirCache caches names in a directory for some time. // dirCache caches names in a directory for some time.
// //
// If called when the cache is expired, the filenames are read afresh in // If called when the cache is expired, the filenames are read afresh in
// the background. // the background.
type DirCache struct { type dirCache struct {
dir string dir string
ttl time.Duration ttl time.Duration
fs pathfs.FileSystem fs pathfs.FileSystem
...@@ -49,7 +49,7 @@ type DirCache struct { ...@@ -49,7 +49,7 @@ type DirCache struct {
updateRunning bool updateRunning bool
} }
func (c *DirCache) setMap(newMap map[string]bool) { func (c *dirCache) setMap(newMap map[string]bool) {
c.lock.Lock() c.lock.Lock()
defer c.lock.Unlock() defer c.lock.Unlock()
...@@ -59,7 +59,7 @@ func (c *DirCache) setMap(newMap map[string]bool) { ...@@ -59,7 +59,7 @@ func (c *DirCache) setMap(newMap map[string]bool) {
func() { c.DropCache() }) func() { c.DropCache() })
} }
func (c *DirCache) DropCache() { func (c *dirCache) DropCache() {
c.lock.Lock() c.lock.Lock()
defer c.lock.Unlock() defer c.lock.Unlock()
c.names = nil c.names = nil
...@@ -67,7 +67,7 @@ func (c *DirCache) DropCache() { ...@@ -67,7 +67,7 @@ func (c *DirCache) DropCache() {
// Try to refresh: if another update is already running, do nothing, // Try to refresh: if another update is already running, do nothing,
// otherwise, read the directory and set it. // otherwise, read the directory and set it.
func (c *DirCache) maybeRefresh() { func (c *dirCache) maybeRefresh() {
c.lock.Lock() c.lock.Lock()
defer c.lock.Unlock() defer c.lock.Unlock()
if c.updateRunning { if c.updateRunning {
...@@ -80,7 +80,7 @@ func (c *DirCache) maybeRefresh() { ...@@ -80,7 +80,7 @@ func (c *DirCache) maybeRefresh() {
}() }()
} }
func (c *DirCache) RemoveEntry(name string) { func (c *dirCache) RemoveEntry(name string) {
c.lock.Lock() c.lock.Lock()
defer c.lock.Unlock() defer c.lock.Unlock()
if c.names == nil { if c.names == nil {
...@@ -91,7 +91,7 @@ func (c *DirCache) RemoveEntry(name string) { ...@@ -91,7 +91,7 @@ func (c *DirCache) RemoveEntry(name string) {
delete(c.names, name) delete(c.names, name)
} }
func (c *DirCache) AddEntry(name string) { func (c *dirCache) AddEntry(name string) {
c.lock.Lock() c.lock.Lock()
defer c.lock.Unlock() defer c.lock.Unlock()
if c.names == nil { if c.names == nil {
...@@ -102,15 +102,15 @@ func (c *DirCache) AddEntry(name string) { ...@@ -102,15 +102,15 @@ func (c *DirCache) AddEntry(name string) {
c.names[name] = true c.names[name] = true
} }
func NewDirCache(fs pathfs.FileSystem, dir string, ttl time.Duration) *DirCache { func newDirCache(fs pathfs.FileSystem, dir string, ttl time.Duration) *dirCache {
dc := new(DirCache) dc := new(dirCache)
dc.dir = dir dc.dir = dir
dc.fs = fs dc.fs = fs
dc.ttl = ttl dc.ttl = ttl
return dc return dc
} }
func (c *DirCache) HasEntry(name string) (mapPresent bool, found bool) { func (c *dirCache) HasEntry(name string) (mapPresent bool, found bool) {
c.lock.RLock() c.lock.RLock()
defer c.lock.RUnlock() defer c.lock.RUnlock()
......
...@@ -56,14 +56,14 @@ func filePathHash(path string) string { ...@@ -56,14 +56,14 @@ func filePathHash(path string) string {
answer is-deleted queries quickly. answer is-deleted queries quickly.
*/ */
type UnionFs struct { type unionFS struct {
pathfs.FileSystem pathfs.FileSystem
// The same, but as interfaces. // The same, but as interfaces.
fileSystems []pathfs.FileSystem fileSystems []pathfs.FileSystem
// A file-existence cache. // A file-existence cache.
deletionCache *DirCache deletionCache *dirCache
// A file -> branch cache. // A file -> branch cache.
branchCache *TimedCache branchCache *TimedCache
...@@ -86,8 +86,8 @@ const ( ...@@ -86,8 +86,8 @@ const (
_DROP_CACHE = ".drop_cache" _DROP_CACHE = ".drop_cache"
) )
func NewUnionFs(fileSystems []pathfs.FileSystem, options UnionFsOptions) *UnionFs { func NewUnionFs(fileSystems []pathfs.FileSystem, options UnionFsOptions) pathfs.FileSystem {
g := &UnionFs{ g := &unionFS{
options: &options, options: &options,
fileSystems: fileSystems, fileSystems: fileSystems,
FileSystem: pathfs.NewDefaultFileSystem(), FileSystem: pathfs.NewDefaultFileSystem(),
...@@ -100,7 +100,7 @@ func NewUnionFs(fileSystems []pathfs.FileSystem, options UnionFsOptions) *UnionF ...@@ -100,7 +100,7 @@ func NewUnionFs(fileSystems []pathfs.FileSystem, options UnionFsOptions) *UnionF
return nil return nil
} }
g.deletionCache = NewDirCache(writable, options.DeletionDirName, options.DeletionCacheTTL) g.deletionCache = newDirCache(writable, options.DeletionDirName, options.DeletionCacheTTL)
g.branchCache = NewTimedCache( g.branchCache = NewTimedCache(
func(n string) (interface{}, bool) { return g.getBranchAttrNoCache(n), true }, func(n string) (interface{}, bool) { return g.getBranchAttrNoCache(n), true },
options.BranchCacheTTL) options.BranchCacheTTL)
...@@ -113,7 +113,7 @@ func NewUnionFs(fileSystems []pathfs.FileSystem, options UnionFsOptions) *UnionF ...@@ -113,7 +113,7 @@ func NewUnionFs(fileSystems []pathfs.FileSystem, options UnionFsOptions) *UnionF
return g return g
} }
func (fs *UnionFs) OnMount(nodeFs *pathfs.PathNodeFs) { func (fs *unionFS) OnMount(nodeFs *pathfs.PathNodeFs) {
fs.nodeFs = nodeFs fs.nodeFs = nodeFs
} }
...@@ -122,7 +122,7 @@ func (fs *UnionFs) OnMount(nodeFs *pathfs.PathNodeFs) { ...@@ -122,7 +122,7 @@ func (fs *UnionFs) OnMount(nodeFs *pathfs.PathNodeFs) {
// The isDeleted() method tells us if a path has a marker in the deletion store. // The isDeleted() method tells us if a path has a marker in the deletion store.
// It may return an error code if the store could not be accessed. // It may return an error code if the store could not be accessed.
func (fs *UnionFs) isDeleted(name string) (deleted bool, code fuse.Status) { func (fs *unionFS) isDeleted(name string) (deleted bool, code fuse.Status) {
marker := fs.deletionPath(name) marker := fs.deletionPath(name)
haveCache, found := fs.deletionCache.HasEntry(filepath.Base(marker)) haveCache, found := fs.deletionCache.HasEntry(filepath.Base(marker))
if haveCache { if haveCache {
...@@ -142,7 +142,7 @@ func (fs *UnionFs) isDeleted(name string) (deleted bool, code fuse.Status) { ...@@ -142,7 +142,7 @@ func (fs *UnionFs) isDeleted(name string) (deleted bool, code fuse.Status) {
return false, fuse.Status(syscall.EROFS) return false, fuse.Status(syscall.EROFS)
} }
func (fs *UnionFs) createDeletionStore() (code fuse.Status) { func (fs *unionFS) createDeletionStore() (code fuse.Status) {
writable := fs.fileSystems[0] writable := fs.fileSystems[0]
fi, code := writable.GetAttr(fs.options.DeletionDirName, nil) fi, code := writable.GetAttr(fs.options.DeletionDirName, nil)
if code == fuse.ENOENT { if code == fuse.ENOENT {
...@@ -159,7 +159,7 @@ func (fs *UnionFs) createDeletionStore() (code fuse.Status) { ...@@ -159,7 +159,7 @@ func (fs *UnionFs) createDeletionStore() (code fuse.Status) {
return code return code
} }
func (fs *UnionFs) getBranch(name string) branchResult { func (fs *unionFS) getBranch(name string) branchResult {
name = stripSlash(name) name = stripSlash(name)
r := fs.branchCache.Get(name) r := fs.branchCache.Get(name)
return r.(branchResult) return r.(branchResult)
...@@ -175,7 +175,7 @@ func (fs branchResult) String() string { ...@@ -175,7 +175,7 @@ func (fs branchResult) String() string {
return fmt.Sprintf("{%v %v branch %d}", fs.attr, fs.code, fs.branch) return fmt.Sprintf("{%v %v branch %d}", fs.attr, fs.code, fs.branch)
} }
func (fs *UnionFs) getBranchAttrNoCache(name string) branchResult { func (fs *unionFS) getBranchAttrNoCache(name string) branchResult {
name = stripSlash(name) name = stripSlash(name)
parent, base := path.Split(name) parent, base := path.Split(name)
...@@ -213,11 +213,11 @@ func (fs *UnionFs) getBranchAttrNoCache(name string) branchResult { ...@@ -213,11 +213,11 @@ func (fs *UnionFs) getBranchAttrNoCache(name string) branchResult {
//////////////// ////////////////
// Deletion. // Deletion.
func (fs *UnionFs) deletionPath(name string) string { func (fs *unionFS) deletionPath(name string) string {
return filepath.Join(fs.options.DeletionDirName, filePathHash(name)) return filepath.Join(fs.options.DeletionDirName, filePathHash(name))
} }
func (fs *UnionFs) removeDeletion(name string) { func (fs *unionFS) removeDeletion(name string) {
marker := fs.deletionPath(name) marker := fs.deletionPath(name)
fs.deletionCache.RemoveEntry(path.Base(marker)) fs.deletionCache.RemoveEntry(path.Base(marker))
...@@ -231,7 +231,7 @@ func (fs *UnionFs) removeDeletion(name string) { ...@@ -231,7 +231,7 @@ func (fs *UnionFs) removeDeletion(name string) {
} }
} }
func (fs *UnionFs) putDeletion(name string) (code fuse.Status) { func (fs *unionFS) putDeletion(name string) (code fuse.Status) {
code = fs.createDeletionStore() code = fs.createDeletionStore()
if !code.Ok() { if !code.Ok() {
return code return code
...@@ -271,7 +271,7 @@ func (fs *UnionFs) putDeletion(name string) (code fuse.Status) { ...@@ -271,7 +271,7 @@ func (fs *UnionFs) putDeletion(name string) (code fuse.Status) {
//////////////// ////////////////
// Promotion. // Promotion.
func (fs *UnionFs) Promote(name string, srcResult branchResult, context *fuse.Context) (code fuse.Status) { func (fs *unionFS) Promote(name string, srcResult branchResult, context *fuse.Context) (code fuse.Status) {
writable := fs.fileSystems[0] writable := fs.fileSystems[0]
sourceFs := fs.fileSystems[srcResult.branch] sourceFs := fs.fileSystems[srcResult.branch]
...@@ -347,7 +347,7 @@ func (fs *UnionFs) Promote(name string, srcResult branchResult, context *fuse.Co ...@@ -347,7 +347,7 @@ func (fs *UnionFs) Promote(name string, srcResult branchResult, context *fuse.Co
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
// Below: implement interface for a FileSystem. // Below: implement interface for a FileSystem.
func (fs *UnionFs) Link(orig string, newName string, context *fuse.Context) (code fuse.Status) { func (fs *unionFS) Link(orig string, newName string, context *fuse.Context) (code fuse.Status) {
origResult := fs.getBranch(orig) origResult := fs.getBranch(orig)
code = origResult.code code = origResult.code
if code.Ok() && origResult.branch > 0 { if code.Ok() && origResult.branch > 0 {
...@@ -377,7 +377,7 @@ func (fs *UnionFs) Link(orig string, newName string, context *fuse.Context) (cod ...@@ -377,7 +377,7 @@ func (fs *UnionFs) Link(orig string, newName string, context *fuse.Context) (cod
return code return code
} }
func (fs *UnionFs) Rmdir(path string, context *fuse.Context) (code fuse.Status) { func (fs *unionFS) Rmdir(path string, context *fuse.Context) (code fuse.Status) {
r := fs.getBranch(path) r := fs.getBranch(path)
if r.code != fuse.OK { if r.code != fuse.OK {
return r.code return r.code
...@@ -411,7 +411,7 @@ func (fs *UnionFs) Rmdir(path string, context *fuse.Context) (code fuse.Status) ...@@ -411,7 +411,7 @@ func (fs *UnionFs) Rmdir(path string, context *fuse.Context) (code fuse.Status)
return code return code
} }
func (fs *UnionFs) Mkdir(path string, mode uint32, context *fuse.Context) (code fuse.Status) { func (fs *unionFS) Mkdir(path string, mode uint32, context *fuse.Context) (code fuse.Status) {
deleted, code := fs.isDeleted(path) deleted, code := fs.isDeleted(path)
if !code.Ok() { if !code.Ok() {
return code return code
...@@ -448,7 +448,7 @@ func (fs *UnionFs) Mkdir(path string, mode uint32, context *fuse.Context) (code ...@@ -448,7 +448,7 @@ func (fs *UnionFs) Mkdir(path string, mode uint32, context *fuse.Context) (code
return code return code
} }
func (fs *UnionFs) Symlink(pointedTo string, linkName string, context *fuse.Context) (code fuse.Status) { func (fs *unionFS) Symlink(pointedTo string, linkName string, context *fuse.Context) (code fuse.Status) {
code = fs.promoteDirsTo(linkName) code = fs.promoteDirsTo(linkName)
if code.Ok() { if code.Ok() {
code = fs.fileSystems[0].Symlink(pointedTo, linkName, context) code = fs.fileSystems[0].Symlink(pointedTo, linkName, context)
...@@ -460,7 +460,7 @@ func (fs *UnionFs) Symlink(pointedTo string, linkName string, context *fuse.Cont ...@@ -460,7 +460,7 @@ func (fs *UnionFs) Symlink(pointedTo string, linkName string, context *fuse.Cont
return code return code
} }
func (fs *UnionFs) Truncate(path string, size uint64, context *fuse.Context) (code fuse.Status) { func (fs *unionFS) Truncate(path string, size uint64, context *fuse.Context) (code fuse.Status) {
if path == _DROP_CACHE { if path == _DROP_CACHE {
return fuse.OK return fuse.OK
} }
...@@ -483,7 +483,7 @@ func (fs *UnionFs) Truncate(path string, size uint64, context *fuse.Context) (co ...@@ -483,7 +483,7 @@ func (fs *UnionFs) Truncate(path string, size uint64, context *fuse.Context) (co
return code return code
} }
func (fs *UnionFs) Utimens(name string, atime *time.Time, mtime *time.Time, context *fuse.Context) (code fuse.Status) { func (fs *unionFS) Utimens(name string, atime *time.Time, mtime *time.Time, context *fuse.Context) (code fuse.Status) {
name = stripSlash(name) name = stripSlash(name)
r := fs.getBranch(name) r := fs.getBranch(name)
...@@ -503,7 +503,7 @@ func (fs *UnionFs) Utimens(name string, atime *time.Time, mtime *time.Time, cont ...@@ -503,7 +503,7 @@ func (fs *UnionFs) Utimens(name string, atime *time.Time, mtime *time.Time, cont
return code return code
} }
func (fs *UnionFs) Chown(name string, uid uint32, gid uint32, context *fuse.Context) (code fuse.Status) { func (fs *unionFS) Chown(name string, uid uint32, gid uint32, context *fuse.Context) (code fuse.Status) {
name = stripSlash(name) name = stripSlash(name)
r := fs.getBranch(name) r := fs.getBranch(name)
if r.attr == nil || r.code != fuse.OK { if r.attr == nil || r.code != fuse.OK {
...@@ -532,7 +532,7 @@ func (fs *UnionFs) Chown(name string, uid uint32, gid uint32, context *fuse.Cont ...@@ -532,7 +532,7 @@ func (fs *UnionFs) Chown(name string, uid uint32, gid uint32, context *fuse.Cont
return fuse.OK return fuse.OK
} }
func (fs *UnionFs) Chmod(name string, mode uint32, context *fuse.Context) (code fuse.Status) { func (fs *unionFS) Chmod(name string, mode uint32, context *fuse.Context) (code fuse.Status) {
name = stripSlash(name) name = stripSlash(name)
r := fs.getBranch(name) r := fs.getBranch(name)
if r.attr == nil { if r.attr == nil {
...@@ -564,7 +564,7 @@ func (fs *UnionFs) Chmod(name string, mode uint32, context *fuse.Context) (code ...@@ -564,7 +564,7 @@ func (fs *UnionFs) Chmod(name string, mode uint32, context *fuse.Context) (code
return fuse.OK return fuse.OK
} }
func (fs *UnionFs) Access(name string, mode uint32, context *fuse.Context) (code fuse.Status) { func (fs *unionFS) Access(name string, mode uint32, context *fuse.Context) (code fuse.Status) {
// We always allow writing. // We always allow writing.
mode = mode &^ raw.W_OK mode = mode &^ raw.W_OK
if name == "" { if name == "" {
...@@ -577,7 +577,7 @@ func (fs *UnionFs) Access(name string, mode uint32, context *fuse.Context) (code ...@@ -577,7 +577,7 @@ func (fs *UnionFs) Access(name string, mode uint32, context *fuse.Context) (code
return fuse.ENOENT return fuse.ENOENT
} }
func (fs *UnionFs) Unlink(name string, context *fuse.Context) (code fuse.Status) { func (fs *unionFS) Unlink(name string, context *fuse.Context) (code fuse.Status) {
r := fs.getBranch(name) r := fs.getBranch(name)
if r.branch == 0 { if r.branch == 0 {
code = fs.fileSystems[0].Unlink(name, context) code = fs.fileSystems[0].Unlink(name, context)
...@@ -594,7 +594,7 @@ func (fs *UnionFs) Unlink(name string, context *fuse.Context) (code fuse.Status) ...@@ -594,7 +594,7 @@ func (fs *UnionFs) Unlink(name string, context *fuse.Context) (code fuse.Status)
return code return code
} }
func (fs *UnionFs) Readlink(name string, context *fuse.Context) (out string, code fuse.Status) { func (fs *unionFS) Readlink(name string, context *fuse.Context) (out string, code fuse.Status) {
r := fs.getBranch(name) r := fs.getBranch(name)
if r.branch >= 0 { if r.branch >= 0 {
return fs.fileSystems[r.branch].Readlink(name, context) return fs.fileSystems[r.branch].Readlink(name, context)
...@@ -611,7 +611,7 @@ func stripSlash(fn string) string { ...@@ -611,7 +611,7 @@ func stripSlash(fn string) string {
return strings.TrimRight(fn, string(filepath.Separator)) return strings.TrimRight(fn, string(filepath.Separator))
} }
func (fs *UnionFs) promoteDirsTo(filename string) fuse.Status { func (fs *unionFS) promoteDirsTo(filename string) fuse.Status {
dirName, _ := filepath.Split(filename) dirName, _ := filepath.Split(filename)
dirName = stripSlash(dirName) dirName = stripSlash(dirName)
...@@ -655,7 +655,7 @@ func (fs *UnionFs) promoteDirsTo(filename string) fuse.Status { ...@@ -655,7 +655,7 @@ func (fs *UnionFs) promoteDirsTo(filename string) fuse.Status {
return fuse.OK return fuse.OK
} }
func (fs *UnionFs) Create(name string, flags uint32, mode uint32, context *fuse.Context) (fuseFile fuse.File, code fuse.Status) { func (fs *unionFS) Create(name string, flags uint32, mode uint32, context *fuse.Context) (fuseFile fuse.File, code fuse.Status) {
writable := fs.fileSystems[0] writable := fs.fileSystems[0]
code = fs.promoteDirsTo(name) code = fs.promoteDirsTo(name)
...@@ -677,7 +677,7 @@ func (fs *UnionFs) Create(name string, flags uint32, mode uint32, context *fuse. ...@@ -677,7 +677,7 @@ func (fs *UnionFs) Create(name string, flags uint32, mode uint32, context *fuse.
return fuseFile, code return fuseFile, code
} }
func (fs *UnionFs) GetAttr(name string, context *fuse.Context) (a *fuse.Attr, s fuse.Status) { func (fs *unionFS) GetAttr(name string, context *fuse.Context) (a *fuse.Attr, s fuse.Status) {
_, hidden := fs.hiddenFiles[name] _, hidden := fs.hiddenFiles[name]
if hidden { if hidden {
return nil, fuse.ENOENT return nil, fuse.ENOENT
...@@ -708,7 +708,7 @@ func (fs *UnionFs) GetAttr(name string, context *fuse.Context) (a *fuse.Attr, s ...@@ -708,7 +708,7 @@ func (fs *UnionFs) GetAttr(name string, context *fuse.Context) (a *fuse.Attr, s
return &fi, r.code return &fi, r.code
} }
func (fs *UnionFs) GetXAttr(name string, attr string, context *fuse.Context) ([]byte, fuse.Status) { func (fs *unionFS) GetXAttr(name string, attr string, context *fuse.Context) ([]byte, fuse.Status) {
if name == _DROP_CACHE { if name == _DROP_CACHE {
return nil, fuse.ENODATA return nil, fuse.ENODATA
} }
...@@ -720,7 +720,7 @@ func (fs *UnionFs) GetXAttr(name string, attr string, context *fuse.Context) ([] ...@@ -720,7 +720,7 @@ func (fs *UnionFs) GetXAttr(name string, attr string, context *fuse.Context) ([]
return nil, fuse.ENOENT return nil, fuse.ENOENT
} }
func (fs *UnionFs) OpenDir(directory string, context *fuse.Context) (stream []fuse.DirEntry, status fuse.Status) { func (fs *unionFS) OpenDir(directory string, context *fuse.Context) (stream []fuse.DirEntry, status fuse.Status) {
dirBranch := fs.getBranch(directory) dirBranch := fs.getBranch(directory)
if dirBranch.branch < 0 { if dirBranch.branch < 0 {
return nil, fuse.ENOENT return nil, fuse.ENOENT
...@@ -812,7 +812,7 @@ func (fs *UnionFs) OpenDir(directory string, context *fuse.Context) (stream []fu ...@@ -812,7 +812,7 @@ func (fs *UnionFs) OpenDir(directory string, context *fuse.Context) (stream []fu
// recursivePromote promotes path, and if a directory, everything // recursivePromote promotes path, and if a directory, everything
// below that directory. It returns a list of all promoted paths, in // below that directory. It returns a list of all promoted paths, in
// full, including the path itself. // full, including the path itself.
func (fs *UnionFs) recursivePromote(path string, pathResult branchResult, context *fuse.Context) (names []string, code fuse.Status) { func (fs *unionFS) recursivePromote(path string, pathResult branchResult, context *fuse.Context) (names []string, code fuse.Status) {
names = []string{} names = []string{}
if pathResult.branch > 0 { if pathResult.branch > 0 {
code = fs.Promote(path, pathResult, context) code = fs.Promote(path, pathResult, context)
...@@ -843,7 +843,7 @@ func (fs *UnionFs) recursivePromote(path string, pathResult branchResult, contex ...@@ -843,7 +843,7 @@ func (fs *UnionFs) recursivePromote(path string, pathResult branchResult, contex
return names, code return names, code
} }
func (fs *UnionFs) renameDirectory(srcResult branchResult, srcDir string, dstDir string, context *fuse.Context) (code fuse.Status) { func (fs *unionFS) renameDirectory(srcResult branchResult, srcDir string, dstDir string, context *fuse.Context) (code fuse.Status) {
names := []string{} names := []string{}
if code.Ok() { if code.Ok() {
names, code = fs.recursivePromote(srcDir, srcResult, context) names, code = fs.recursivePromote(srcDir, srcResult, context)
...@@ -876,7 +876,7 @@ func (fs *UnionFs) renameDirectory(srcResult branchResult, srcDir string, dstDir ...@@ -876,7 +876,7 @@ func (fs *UnionFs) renameDirectory(srcResult branchResult, srcDir string, dstDir
return code return code
} }
func (fs *UnionFs) Rename(src string, dst string, context *fuse.Context) (code fuse.Status) { func (fs *unionFS) Rename(src string, dst string, context *fuse.Context) (code fuse.Status) {
srcResult := fs.getBranch(src) srcResult := fs.getBranch(src)
code = srcResult.code code = srcResult.code
if code.Ok() { if code.Ok() {
...@@ -910,15 +910,15 @@ func (fs *UnionFs) Rename(src string, dst string, context *fuse.Context) (code f ...@@ -910,15 +910,15 @@ func (fs *UnionFs) Rename(src string, dst string, context *fuse.Context) (code f
return code return code
} }
func (fs *UnionFs) DropBranchCache(names []string) { func (fs *unionFS) DropBranchCache(names []string) {
fs.branchCache.DropAll(names) fs.branchCache.DropAll(names)
} }
func (fs *UnionFs) DropDeletionCache() { func (fs *unionFS) DropDeletionCache() {
fs.deletionCache.DropCache() fs.deletionCache.DropCache()
} }
func (fs *UnionFs) DropSubFsCaches() { func (fs *unionFS) DropSubFsCaches() {
for _, fs := range fs.fileSystems { for _, fs := range fs.fileSystems {
a, code := fs.GetAttr(_DROP_CACHE, nil) a, code := fs.GetAttr(_DROP_CACHE, nil)
if code.Ok() && a.IsRegular() { if code.Ok() && a.IsRegular() {
...@@ -931,7 +931,7 @@ func (fs *UnionFs) DropSubFsCaches() { ...@@ -931,7 +931,7 @@ func (fs *UnionFs) DropSubFsCaches() {
} }
} }
func (fs *UnionFs) Open(name string, flags uint32, context *fuse.Context) (fuseFile fuse.File, status fuse.Status) { func (fs *unionFS) Open(name string, flags uint32, context *fuse.Context) (fuseFile fuse.File, status fuse.Status) {
if name == _DROP_CACHE { if name == _DROP_CACHE {
if flags&fuse.O_ANYWRITE != 0 { if flags&fuse.O_ANYWRITE != 0 {
log.Println("Forced cache drop on", fs) log.Println("Forced cache drop on", fs)
...@@ -966,7 +966,7 @@ func (fs *UnionFs) Open(name string, flags uint32, context *fuse.Context) (fuseF ...@@ -966,7 +966,7 @@ func (fs *UnionFs) Open(name string, flags uint32, context *fuse.Context) (fuseF
return fuseFile, status return fuseFile, status
} }
func (fs *UnionFs) String() string { func (fs *unionFS) String() string {
names := []string{} names := []string{}
for _, fs := range fs.fileSystems { for _, fs := range fs.fileSystems {
names = append(names, fs.String()) names = append(names, fs.String())
...@@ -974,13 +974,13 @@ func (fs *UnionFs) String() string { ...@@ -974,13 +974,13 @@ func (fs *UnionFs) String() string {
return fmt.Sprintf("UnionFs(%v)", names) return fmt.Sprintf("UnionFs(%v)", names)
} }
func (fs *UnionFs) StatFs(name string) *fuse.StatfsOut { func (fs *unionFS) StatFs(name string) *fuse.StatfsOut {
return fs.fileSystems[0].StatFs("") return fs.fileSystems[0].StatFs("")
} }
type unionFsFile struct { type unionFsFile struct {
fuse.File fuse.File
ufs *UnionFs ufs *unionFS
node *fuse.Inode node *fuse.Inode
layer int layer int
} }
...@@ -989,7 +989,7 @@ func (fs *unionFsFile) String() string { ...@@ -989,7 +989,7 @@ func (fs *unionFsFile) String() string {
return fmt.Sprintf("unionFsFile(%s)", fs.File.String()) return fmt.Sprintf("unionFsFile(%s)", fs.File.String())
} }
func (fs *UnionFs) newUnionFsFile(f fuse.File, branch int) *unionFsFile { func (fs *unionFS) newUnionFsFile(f fuse.File, branch int) *unionFsFile {
return &unionFsFile{ return &unionFsFile{
File: f, File: f,
ufs: fs, ufs: fs,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment