@@ -50,9 +50,6 @@ import (
5050// close-to-open.
5151
5252type Goofys struct {
53- fuseutil.NotImplementedFileSystem
54- connection * fuse.Connection
55-
5653 bucket string
5754
5855 flags * FlagStorage
@@ -114,6 +111,8 @@ type Goofys struct {
114111 diskFdCount int64
115112
116113 stats OpStats
114+
115+ NotifyCallback func (notifications []interface {})
117116}
118117
119118type OpStats struct {
@@ -127,6 +126,12 @@ type OpStats struct {
127126 ts time.Time
128127}
129128
129+ type GoofysFuse struct {
130+ fuseutil.NotImplementedFileSystem
131+ * Goofys
132+ connection * fuse.Connection
133+ }
134+
130135var s3Log = GetLogger ("s3" )
131136var log = GetLogger ("main" )
132137var fuseLog = GetLogger ("fuse" )
@@ -298,6 +303,23 @@ func newGoofys(ctx context.Context, bucket string, flags *FlagStorage,
298303 return fs
299304}
300305
306+ func NewGoofysFuse (fs * Goofys ) * GoofysFuse {
307+ fsint := & GoofysFuse {
308+ Goofys : fs ,
309+ }
310+ fs .NotifyCallback = func (notifications []interface {}) {
311+ if fsint .connection != nil {
312+ // Notify kernel in a separate thread/goroutine
313+ go func () {
314+ for _ , n := range notifications {
315+ fsint .connection .Notify (n )
316+ }
317+ }()
318+ }
319+ }
320+ return fsint
321+ }
322+
301323// from https://stackoverflow.com/questions/22892120/how-to-generate-a-random-string-of-a-fixed-length-in-golang
302324func RandStringBytesMaskImprSrc (n int ) string {
303325 const letterBytes = "abcdefghijklmnopqrstuvwxyz0123456789"
@@ -766,6 +788,7 @@ func (fs *Goofys) RefreshInodeCache(inode *Inode) error {
766788 inode .mu .Unlock ()
767789 inode .resetDirTimeRec ()
768790 var mappedErr error
791+ var notifications []interface {}
769792 if parent == nil {
770793 // For regular directories it's enough to send one invalidation
771794 // message, the kernel will send forgets for their children and
@@ -776,7 +799,6 @@ func (fs *Goofys) RefreshInodeCache(inode *Inode) error {
776799 // directory.
777800 dh := inode .OpenDir ()
778801 dh .mu .Lock ()
779- var notifications []interface {}
780802 for {
781803 en , err := dh .ReadDir (dh .lastInternalOffset , dh .lastExternalOffset )
782804 if err != nil {
@@ -798,43 +820,32 @@ func (fs *Goofys) RefreshInodeCache(inode *Inode) error {
798820 }
799821 dh .CloseDir ()
800822 dh .mu .Unlock ()
801- // Send notifications from another goroutine to prevent deadlocks
802- if fs .connection != nil {
803- go func () {
804- for _ , n := range notifications {
805- fs .connection .Notify (n )
806- }
807- }()
808- }
823+ fs .NotifyCallback (notifications )
809824 return mappedErr
810825 }
811826 inode , err := parent .recheckInode (inode , name )
812827 mappedErr = mapAwsError (err )
813- if fs .connection != nil {
814- // Send notifications from another goroutine to prevent deadlocks
815- go func () {
816- if mappedErr == syscall .ENOENT {
817- fs .connection .Notify (& fuseops.NotifyDelete {
818- Parent : parentId ,
819- Child : inodeId ,
820- Name : name ,
821- })
822- } else {
823- fs .connection .Notify (& fuseops.NotifyInvalEntry {
824- Parent : parentId ,
825- Name : name ,
826- })
827- }
828- }()
828+ if mappedErr == syscall .ENOENT {
829+ notifications = append (notifications , & fuseops.NotifyDelete {
830+ Parent : parentId ,
831+ Child : inodeId ,
832+ Name : name ,
833+ })
834+ } else {
835+ notifications = append (notifications , & fuseops.NotifyInvalEntry {
836+ Parent : parentId ,
837+ Name : name ,
838+ })
829839 }
840+ fs .NotifyCallback (notifications )
830841 if mappedErr == syscall .ENOENT {
831842 // We don't mind if the file disappeared
832843 return nil
833844 }
834845 return mappedErr
835846}
836847
837- func (fs * Goofys ) StatFS (
848+ func (fs * GoofysFuse ) StatFS (
838849 ctx context.Context ,
839850 op * fuseops.StatFSOp ) (err error ) {
840851
@@ -854,7 +865,7 @@ func (fs *Goofys) StatFS(
854865 return
855866}
856867
857- func (fs * Goofys ) GetInodeAttributes (
868+ func (fs * GoofysFuse ) GetInodeAttributes (
858869 ctx context.Context ,
859870 op * fuseops.GetInodeAttributesOp ) (err error ) {
860871
@@ -879,7 +890,7 @@ func (fs *Goofys) GetInodeAttributes(
879890 return
880891}
881892
882- func (fs * Goofys ) GetXattr (ctx context.Context ,
893+ func (fs * GoofysFuse ) GetXattr (ctx context.Context ,
883894 op * fuseops.GetXattrOp ) (err error ) {
884895 fs .mu .RLock ()
885896 inode := fs .getInodeOrDie (op .Inode )
@@ -910,7 +921,7 @@ func (fs *Goofys) GetXattr(ctx context.Context,
910921 return
911922}
912923
913- func (fs * Goofys ) ListXattr (ctx context.Context ,
924+ func (fs * GoofysFuse ) ListXattr (ctx context.Context ,
914925 op * fuseops.ListXattrOp ) (err error ) {
915926 fs .mu .RLock ()
916927 inode := fs .getInodeOrDie (op .Inode )
@@ -948,7 +959,7 @@ func (fs *Goofys) ListXattr(ctx context.Context,
948959 return
949960}
950961
951- func (fs * Goofys ) RemoveXattr (ctx context.Context ,
962+ func (fs * GoofysFuse ) RemoveXattr (ctx context.Context ,
952963 op * fuseops.RemoveXattrOp ) (err error ) {
953964 fs .mu .RLock ()
954965 inode := fs .getInodeOrDie (op .Inode )
@@ -971,7 +982,7 @@ func (fs *Goofys) RemoveXattr(ctx context.Context,
971982 return
972983}
973984
974- func (fs * Goofys ) SetXattr (ctx context.Context ,
985+ func (fs * GoofysFuse ) SetXattr (ctx context.Context ,
975986 op * fuseops.SetXattrOp ) (err error ) {
976987 fs .mu .RLock ()
977988 inode := fs .getInodeOrDie (op .Inode )
@@ -998,7 +1009,7 @@ func (fs *Goofys) SetXattr(ctx context.Context,
9981009 return
9991010}
10001011
1001- func (fs * Goofys ) CreateSymlink (ctx context.Context ,
1012+ func (fs * GoofysFuse ) CreateSymlink (ctx context.Context ,
10021013 op * fuseops.CreateSymlinkOp ) (err error ) {
10031014 fs .mu .RLock ()
10041015 parent := fs .getInodeOrDie (op .Parent )
@@ -1019,7 +1030,7 @@ func (fs *Goofys) CreateSymlink(ctx context.Context,
10191030 return
10201031}
10211032
1022- func (fs * Goofys ) ReadSymlink (ctx context.Context ,
1033+ func (fs * GoofysFuse ) ReadSymlink (ctx context.Context ,
10231034 op * fuseops.ReadSymlinkOp ) (err error ) {
10241035 fs .mu .RLock ()
10251036 inode := fs .getInodeOrDie (op .Inode )
@@ -1121,7 +1132,7 @@ func expired(cache time.Time, ttl time.Duration) bool {
11211132 return ! cache .Add (ttl ).After (now )
11221133}
11231134
1124- func (fs * Goofys ) LookUpInode (
1135+ func (fs * GoofysFuse ) LookUpInode (
11251136 ctx context.Context ,
11261137 op * fuseops.LookUpInodeOp ) (err error ) {
11271138
@@ -1192,7 +1203,7 @@ func (fs *Goofys) addDotAndDotDot(dir *Inode) {
11921203 fs .insertInode (dir , dot )
11931204}
11941205
1195- func (fs * Goofys ) ForgetInode (
1206+ func (fs * GoofysFuse ) ForgetInode (
11961207 ctx context.Context ,
11971208 op * fuseops.ForgetInodeOp ) (err error ) {
11981209
@@ -1209,7 +1220,7 @@ func (fs *Goofys) ForgetInode(
12091220 return
12101221}
12111222
1212- func (fs * Goofys ) OpenDir (
1223+ func (fs * GoofysFuse ) OpenDir (
12131224 ctx context.Context ,
12141225 op * fuseops.OpenDirOp ) (err error ) {
12151226
@@ -1255,7 +1266,7 @@ func makeDirEntry(en *DirHandleEntry) fuseutil.Dirent {
12551266 }
12561267}
12571268
1258- func (fs * Goofys ) ReadDir (
1269+ func (fs * GoofysFuse ) ReadDir (
12591270 ctx context.Context ,
12601271 op * fuseops.ReadDirOp ) (err error ) {
12611272
@@ -1358,7 +1369,7 @@ func (fs *Goofys) completeInflightListing(id int) map[string]bool {
13581369 return m
13591370}
13601371
1361- func (fs * Goofys ) ReleaseDirHandle (
1372+ func (fs * GoofysFuse ) ReleaseDirHandle (
13621373 ctx context.Context ,
13631374 op * fuseops.ReleaseDirHandleOp ) (err error ) {
13641375
@@ -1379,7 +1390,7 @@ func (fs *Goofys) ReleaseDirHandle(
13791390 return
13801391}
13811392
1382- func (fs * Goofys ) OpenFile (
1393+ func (fs * GoofysFuse ) OpenFile (
13831394 ctx context.Context ,
13841395 op * fuseops.OpenFileOp ) (err error ) {
13851396 fs .mu .RLock ()
@@ -1424,7 +1435,7 @@ func (fs *Goofys) OpenFile(
14241435 return
14251436}
14261437
1427- func (fs * Goofys ) ReadFile (
1438+ func (fs * GoofysFuse ) ReadFile (
14281439 ctx context.Context ,
14291440 op * fuseops.ReadFileOp ) (err error ) {
14301441
@@ -1440,7 +1451,7 @@ func (fs *Goofys) ReadFile(
14401451 return
14411452}
14421453
1443- func (fs * Goofys ) SyncFile (
1454+ func (fs * GoofysFuse ) SyncFile (
14441455 ctx context.Context ,
14451456 op * fuseops.SyncFileOp ) (err error ) {
14461457
@@ -1464,7 +1475,7 @@ func (fs *Goofys) SyncFile(
14641475 return
14651476}
14661477
1467- func (fs * Goofys ) FlushFile (
1478+ func (fs * GoofysFuse ) FlushFile (
14681479 ctx context.Context ,
14691480 op * fuseops.FlushFileOp ) (err error ) {
14701481
@@ -1476,7 +1487,7 @@ func (fs *Goofys) FlushFile(
14761487 return
14771488}
14781489
1479- func (fs * Goofys ) ReleaseFileHandle (
1490+ func (fs * GoofysFuse ) ReleaseFileHandle (
14801491 ctx context.Context ,
14811492 op * fuseops.ReleaseFileHandleOp ) (err error ) {
14821493 fs .mu .Lock ()
@@ -1495,7 +1506,7 @@ func (fs *Goofys) ReleaseFileHandle(
14951506 return
14961507}
14971508
1498- func (fs * Goofys ) CreateFile (
1509+ func (fs * GoofysFuse ) CreateFile (
14991510 ctx context.Context ,
15001511 op * fuseops.CreateFileOp ) (err error ) {
15011512
@@ -1539,7 +1550,7 @@ func (fs *Goofys) CreateFile(
15391550// MkNode is required for NFS even with regular files
15401551// because kernel nfsd uses vfs_create() -> fuse_create() -> fuse_mknod()
15411552// and then separate fuse_open() for file creation instead of fuse_create_open()
1542- func (fs * Goofys ) MkNode (
1553+ func (fs * GoofysFuse ) MkNode (
15431554 ctx context.Context ,
15441555 op * fuseops.MkNodeOp ) (err error ) {
15451556
@@ -1583,7 +1594,7 @@ func (fs *Goofys) MkNode(
15831594 return
15841595}
15851596
1586- func (fs * Goofys ) MkDir (
1597+ func (fs * GoofysFuse ) MkDir (
15871598 ctx context.Context ,
15881599 op * fuseops.MkDirOp ) (err error ) {
15891600
@@ -1618,7 +1629,7 @@ func (fs *Goofys) MkDir(
16181629 return
16191630}
16201631
1621- func (fs * Goofys ) RmDir (
1632+ func (fs * GoofysFuse ) RmDir (
16221633 ctx context.Context ,
16231634 op * fuseops.RmDirOp ) (err error ) {
16241635
@@ -1639,7 +1650,7 @@ func (fs *Goofys) RmDir(
16391650 return
16401651}
16411652
1642- func (fs * Goofys ) SetInodeAttributes (
1653+ func (fs * GoofysFuse ) SetInodeAttributes (
16431654 ctx context.Context ,
16441655 op * fuseops.SetInodeAttributesOp ) (err error ) {
16451656
@@ -1737,7 +1748,7 @@ func (fs *Goofys) SetInodeAttributes(
17371748 return
17381749}
17391750
1740- func (fs * Goofys ) WriteFile (
1751+ func (fs * GoofysFuse ) WriteFile (
17411752 ctx context.Context ,
17421753 op * fuseops.WriteFileOp ) (err error ) {
17431754
@@ -1761,7 +1772,7 @@ func (fs *Goofys) WriteFile(
17611772 return
17621773}
17631774
1764- func (fs * Goofys ) Unlink (
1775+ func (fs * GoofysFuse ) Unlink (
17651776 ctx context.Context ,
17661777 op * fuseops.UnlinkOp ) (err error ) {
17671778
@@ -1783,7 +1794,7 @@ func (fs *Goofys) Unlink(
17831794
17841795// rename("from", "to") causes the kernel to send lookup of "from" and
17851796// "to" prior to sending rename to us
1786- func (fs * Goofys ) Rename (
1797+ func (fs * GoofysFuse ) Rename (
17871798 ctx context.Context ,
17881799 op * fuseops.RenameOp ) (err error ) {
17891800
@@ -1856,7 +1867,7 @@ const (
18561867 FALLOC_FL_INSERT_RANGE = uint32 (0x20 )
18571868)
18581869
1859- func (fs * Goofys ) Fallocate (
1870+ func (fs * GoofysFuse ) Fallocate (
18601871 ctx context.Context ,
18611872 op * fuseops.FallocateOp ) (err error ) {
18621873
@@ -1930,7 +1941,7 @@ func (fs *Goofys) Fallocate(
19301941 return
19311942}
19321943
1933- func (fs * Goofys ) SetConnection (conn * fuse.Connection ) {
1944+ func (fs * GoofysFuse ) SetConnection (conn * fuse.Connection ) {
19341945 fs .connection = conn
19351946}
19361947
@@ -2039,7 +2050,8 @@ func MountFuse(
20392050 err = fmt .Errorf ("Mount: initialization failed" )
20402051 return
20412052 }
2042- server := fuseutil .NewFileSystemServer (fs )
2053+ fsint := NewGoofysFuse (fs )
2054+ server := fuseutil .NewFileSystemServer (fsint )
20432055
20442056 mfs , err = fuse .Mount (flags .MountPoint , server , mountCfg )
20452057 if err != nil {
0 commit comments