Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
go-fuse
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
go-fuse
Commits
94429a4b
Commit
94429a4b
authored
Sep 05, 2011
by
Han-Wen Nienhuys
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Split up pathfilesystem.go and pathops.go
parent
bad4ee66
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
315 additions
and
345 deletions
+315
-345
fuse/Makefile
fuse/Makefile
+4
-2
fuse/fsconnector.go
fuse/fsconnector.go
+15
-297
fuse/fsinode.go
fuse/fsinode.go
+1
-0
fuse/fsmount.go
fuse/fsmount.go
+109
-0
fuse/fsops.go
fuse/fsops.go
+18
-41
fuse/inode.go
fuse/inode.go
+168
-0
fuse/pathdebug.go
fuse/pathdebug.go
+0
-5
No files found.
fuse/Makefile
View file @
94429a4b
...
@@ -11,9 +11,12 @@ MANUAL_GOFILES=api.go \
...
@@ -11,9 +11,12 @@ MANUAL_GOFILES=api.go \
defaultraw.go
\
defaultraw.go
\
direntry.go
\
direntry.go
\
files.go
\
files.go
\
fsmount.go
\
fsinode.go
\
fsinode.go
\
fsconnector.go
\
fuse.go
\
fuse.go
\
handle.go
\
handle.go
\
inode.go
\
latencymap.go
\
latencymap.go
\
lockingfs.go
\
lockingfs.go
\
loggingfs.go
\
loggingfs.go
\
...
@@ -23,8 +26,7 @@ MANUAL_GOFILES=api.go \
...
@@ -23,8 +26,7 @@ MANUAL_GOFILES=api.go \
mountstate.go
\
mountstate.go
\
opcode.go
\
opcode.go
\
pathdebug.go
\
pathdebug.go
\
pathfilesystem.go
\
fsops.go
\
pathops.go
\
readonlyfs.go
\
readonlyfs.go
\
request.go
\
request.go
\
switchfs.go
\
switchfs.go
\
...
...
fuse/
pathfilesystem
.go
→
fuse/
fsconnector
.go
View file @
94429a4b
package
fuse
package
fuse
/*
FilesystemConnector is a lowlevel FUSE filesystem that translates
// This file contains the internal logic of the
from inode numbers (as delivered by the kernel) to traditional path
// FileSystemConnector. The functions for satisfying the raw interface are in
names. The paths are then used as arguments for methods of
// fsops.go
FileSystem instances.
FileSystemConnector supports mounts of different FileSystems
on top of each other's directories.
General todos:
- We are doing lookups (incurring GetAttr() costs) for internal
lookups (eg. after doing a symlink). We could probably do without
the GetAttr calls.
*/
import
(
import
(
"fmt"
"fmt"
"log"
"log"
"os"
"path/filepath"
"path/filepath"
"strings"
"strings"
"sync"
"unsafe"
"unsafe"
)
)
// openedFile stores either an open dir or an open file.
type
openedFile
struct
{
Handled
*
fileSystemMount
*
inode
// O_CREAT, O_TRUNC, etc.
OpenFlags
uint32
// FOPEN_KEEP_CACHE and friends.
FuseFlags
uint32
dir
rawDir
file
File
}
type
fileSystemMount
struct
{
// If non-nil the file system mounted here.
fs
FileSystem
// Node that we were mounted on.
mountInode
*
inode
options
*
FileSystemOptions
// Protects parent/child relations within the mount.
// treeLock should be acquired before openFilesLock
treeLock
sync
.
RWMutex
// Manage filehandles of open files.
openFiles
HandleMap
}
func
(
me
*
fileSystemMount
)
fileInfoToEntry
(
fi
*
os
.
FileInfo
,
out
*
EntryOut
)
{
SplitNs
(
me
.
options
.
EntryTimeout
,
&
out
.
EntryValid
,
&
out
.
EntryValidNsec
)
SplitNs
(
me
.
options
.
AttrTimeout
,
&
out
.
AttrValid
,
&
out
.
AttrValidNsec
)
if
!
fi
.
IsDirectory
()
{
fi
.
Nlink
=
1
}
CopyFileInfo
(
fi
,
&
out
.
Attr
)
me
.
setOwner
(
&
out
.
Attr
)
}
func
(
me
*
fileSystemMount
)
fileInfoToAttr
(
fi
*
os
.
FileInfo
,
out
*
AttrOut
)
{
CopyFileInfo
(
fi
,
&
out
.
Attr
)
SplitNs
(
me
.
options
.
AttrTimeout
,
&
out
.
AttrValid
,
&
out
.
AttrValidNsec
)
me
.
setOwner
(
&
out
.
Attr
)
}
func
(
me
*
FileSystemConnector
)
getOpenedFile
(
h
uint64
)
*
openedFile
{
b
:=
(
*
openedFile
)(
unsafe
.
Pointer
(
DecodeHandle
(
h
)))
return
b
}
func
(
me
*
fileSystemMount
)
unregisterFileHandle
(
handle
uint64
)
*
openedFile
{
obj
:=
me
.
openFiles
.
Forget
(
handle
)
opened
:=
(
*
openedFile
)(
unsafe
.
Pointer
(
obj
))
node
:=
opened
.
inode
node
.
OpenFilesMutex
.
Lock
()
defer
node
.
OpenFilesMutex
.
Unlock
()
idx
:=
-
1
for
i
,
v
:=
range
node
.
OpenFiles
{
if
v
==
opened
{
idx
=
i
break
}
}
l
:=
len
(
node
.
OpenFiles
)
node
.
OpenFiles
[
idx
]
=
node
.
OpenFiles
[
l
-
1
]
node
.
OpenFiles
=
node
.
OpenFiles
[
:
l
-
1
]
return
opened
}
func
(
me
*
fileSystemMount
)
registerFileHandle
(
node
*
inode
,
dir
rawDir
,
f
File
,
flags
uint32
)
(
uint64
,
*
openedFile
)
{
node
.
OpenFilesMutex
.
Lock
()
defer
node
.
OpenFilesMutex
.
Unlock
()
b
:=
&
openedFile
{
dir
:
dir
,
file
:
f
,
inode
:
node
,
fileSystemMount
:
me
,
OpenFlags
:
flags
,
}
withFlags
,
ok
:=
f
.
(
*
WithFlags
)
if
ok
{
b
.
FuseFlags
=
withFlags
.
Flags
f
=
withFlags
.
File
}
node
.
OpenFiles
=
append
(
node
.
OpenFiles
,
b
)
handle
:=
me
.
openFiles
.
Register
(
&
b
.
Handled
)
return
handle
,
b
}
////////////////
// Tests should set to true.
// Tests should set to true.
var
paranoia
=
false
var
paranoia
=
false
// The inode reflects the kernel's idea of the inode.
type
inode
struct
{
Handled
// Constant during lifetime.
NodeId
uint64
// Number of open files and its protection.
OpenFilesMutex
sync
.
Mutex
OpenFiles
[]
*
openedFile
// treeLock is a pointer to me.mount.treeLock; we need store
// this mutex separately, since unmount may set me.mount = nil
// during Unmount(). Constant during lifetime.
//
// If multiple treeLocks must be acquired, the treeLocks
// closer to the root must be acquired first.
treeLock
*
sync
.
RWMutex
// All data below is protected by treeLock.
fsInode
*
fsInode
Children
map
[
string
]
*
inode
// Contains directories that function as mounts. The entries
// are duplicated in Children.
Mounts
map
[
string
]
*
fileSystemMount
LookupCount
int
// Non-nil if this is a mountpoint.
mountPoint
*
fileSystemMount
// The file system to which this node belongs. Is constant
// during the lifetime, except upon Unmount() when it is set
// to nil.
mount
*
fileSystemMount
}
// Must be called with treeLock for the mount held.
func
(
me
*
inode
)
addChild
(
name
string
,
child
*
inode
)
{
if
paranoia
{
ch
:=
me
.
Children
[
name
]
if
ch
!=
nil
{
panic
(
fmt
.
Sprintf
(
"Already have an inode with same name: %v: %v"
,
name
,
ch
))
}
}
me
.
Children
[
name
]
=
child
me
.
fsInode
.
addChild
(
name
,
child
.
fsInode
)
}
// Must be called with treeLock for the mount held.
func
(
me
*
inode
)
rmChild
(
name
string
)
(
ch
*
inode
)
{
ch
=
me
.
Children
[
name
]
if
ch
!=
nil
{
me
.
Children
[
name
]
=
nil
,
false
me
.
fsInode
.
rmChild
(
name
,
ch
.
fsInode
)
}
return
ch
}
// Can only be called on untouched inodes.
func
(
me
*
inode
)
mountFs
(
fs
FileSystem
,
opts
*
FileSystemOptions
)
{
me
.
mountPoint
=
&
fileSystemMount
{
fs
:
fs
,
openFiles
:
NewHandleMap
(
true
),
mountInode
:
me
,
options
:
opts
,
}
me
.
mount
=
me
.
mountPoint
me
.
treeLock
=
&
me
.
mountPoint
.
treeLock
}
// Must be called with treeLock held.
func
(
me
*
inode
)
canUnmount
()
bool
{
for
_
,
v
:=
range
me
.
Children
{
if
v
.
mountPoint
!=
nil
{
// This access may be out of date, but it is no
// problem to err on the safe side.
return
false
}
if
!
v
.
canUnmount
()
{
return
false
}
}
me
.
OpenFilesMutex
.
Lock
()
defer
me
.
OpenFilesMutex
.
Unlock
()
return
len
(
me
.
OpenFiles
)
==
0
}
// Must be called with treeLock held
func
(
me
*
inode
)
recursiveUnmount
()
{
for
_
,
v
:=
range
me
.
Children
{
v
.
recursiveUnmount
()
}
me
.
mount
=
nil
}
func
(
me
*
inode
)
IsDir
()
bool
{
return
me
.
Children
!=
nil
}
func
(
me
*
inode
)
getMountDirEntries
()
(
out
[]
DirEntry
)
{
me
.
treeLock
.
RLock
()
defer
me
.
treeLock
.
RUnlock
()
for
k
,
_
:=
range
me
.
Mounts
{
out
=
append
(
out
,
DirEntry
{
Name
:
k
,
Mode
:
S_IFDIR
,
})
}
return
out
}
// Returns any open file, preferably a r/w one.
func
(
me
*
inode
)
getAnyFile
()
(
file
File
)
{
me
.
OpenFilesMutex
.
Lock
()
defer
me
.
OpenFilesMutex
.
Unlock
()
for
_
,
f
:=
range
me
.
OpenFiles
{
if
file
==
nil
||
f
.
OpenFlags
&
O_ANYWRITE
!=
0
{
file
=
f
.
file
}
}
return
file
}
// Returns an open writable file for the given inode.
func
(
me
*
inode
)
getWritableFiles
()
(
files
[]
File
)
{
me
.
OpenFilesMutex
.
Lock
()
defer
me
.
OpenFilesMutex
.
Unlock
()
for
_
,
f
:=
range
me
.
OpenFiles
{
if
f
.
OpenFlags
&
O_ANYWRITE
!=
0
{
files
=
append
(
files
,
f
.
file
)
}
}
return
files
}
const
initDirSize
=
20
func
(
me
*
inode
)
verify
(
cur
*
fileSystemMount
)
{
if
me
.
mountPoint
!=
nil
{
if
me
!=
me
.
mountPoint
.
mountInode
{
panic
(
"mountpoint mismatch"
)
}
cur
=
me
.
mountPoint
}
if
me
.
mount
!=
cur
{
panic
(
fmt
.
Sprintf
(
"me.mount not set correctly %v %v"
,
me
.
mount
,
cur
))
}
for
name
,
m
:=
range
me
.
Mounts
{
if
m
.
mountInode
!=
me
.
Children
[
name
]
{
panic
(
fmt
.
Sprintf
(
"mountpoint parent mismatch: node:%v name:%v ch:%v"
,
me
.
mountPoint
,
name
,
me
.
Children
))
}
}
for
_
,
ch
:=
range
me
.
Children
{
if
ch
==
nil
{
panic
(
"Found nil child."
)
}
ch
.
verify
(
cur
)
}
}
func
NewFileSystemOptions
()
*
FileSystemOptions
{
func
NewFileSystemOptions
()
*
FileSystemOptions
{
return
&
FileSystemOptions
{
return
&
FileSystemOptions
{
NegativeTimeout
:
0.0
,
NegativeTimeout
:
0.0
,
...
@@ -312,6 +25,7 @@ func NewFileSystemOptions() *FileSystemOptions {
...
@@ -312,6 +25,7 @@ func NewFileSystemOptions() *FileSystemOptions {
}
}
}
}
// FilesystemConnector is a raw FUSE filesystem that manages in-process mounts and inodes.
type
FileSystemConnector
struct
{
type
FileSystemConnector
struct
{
DefaultRawFileSystem
DefaultRawFileSystem
...
@@ -322,12 +36,17 @@ type FileSystemConnector struct {
...
@@ -322,12 +36,17 @@ type FileSystemConnector struct {
rootNode
*
inode
rootNode
*
inode
}
}
func
(
me
*
FileSystemConnector
)
Init
(
fsInit
*
RawFsInit
)
{
func
NewFileSystemConnector
(
fs
FileSystem
,
opts
*
FileSystemOptions
)
(
me
*
FileSystemConnector
)
{
me
.
fsInit
=
*
fsInit
me
=
new
(
FileSystemConnector
)
}
if
opts
==
nil
{
opts
=
NewFileSystemOptions
()
func
(
me
*
FileSystemConnector
)
Statistics
()
string
{
}
return
fmt
.
Sprintf
(
"Inodes %20d
\n
"
,
me
.
inodeMap
.
Count
())
me
.
inodeMap
=
NewHandleMap
(
!
opts
.
SkipCheckHandles
)
me
.
rootNode
=
me
.
newInode
(
true
)
me
.
rootNode
.
NodeId
=
FUSE_ROOT_ID
me
.
verify
()
me
.
mountRoot
(
fs
,
opts
)
return
me
}
}
func
(
me
*
FileSystemConnector
)
verify
()
{
func
(
me
*
FileSystemConnector
)
verify
()
{
...
@@ -596,7 +315,6 @@ func (me *FileSystemConnector) Unmount(path string) Status {
...
@@ -596,7 +315,6 @@ func (me *FileSystemConnector) Unmount(path string) Status {
return
EBUSY
return
EBUSY
}
}
mountInode
.
recursiveUnmount
()
mount
.
mountInode
=
nil
mount
.
mountInode
=
nil
mountInode
.
mountPoint
=
nil
mountInode
.
mountPoint
=
nil
...
...
fuse/fsinode.go
View file @
94429a4b
package
fuse
package
fuse
import
(
import
(
"log"
"log"
"os"
"os"
...
...
fuse/fsmount.go
0 → 100644
View file @
94429a4b
package
fuse
import
(
"os"
"sync"
"unsafe"
)
// openedFile stores either an open dir or an open file.
type
openedFile
struct
{
Handled
// O_CREAT, O_TRUNC, etc.
OpenFlags
uint32
// FOPEN_KEEP_CACHE and friends.
FuseFlags
uint32
dir
rawDir
file
File
}
type
fileSystemMount
struct
{
// The file system we mounted here.
fs
FileSystem
// Node that we were mounted on.
mountInode
*
inode
// Options for the mount.
options
*
FileSystemOptions
// Protects Children hashmaps within the mount. treeLock
// should be acquired before openFilesLock
treeLock
sync
.
RWMutex
// Manage filehandles of open files.
openFiles
HandleMap
}
func
(
me
*
fileSystemMount
)
setOwner
(
attr
*
Attr
)
{
if
me
.
options
.
Owner
!=
nil
{
attr
.
Owner
=
*
me
.
options
.
Owner
}
}
func
(
me
*
fileSystemMount
)
fileInfoToEntry
(
fi
*
os
.
FileInfo
,
out
*
EntryOut
)
{
SplitNs
(
me
.
options
.
EntryTimeout
,
&
out
.
EntryValid
,
&
out
.
EntryValidNsec
)
SplitNs
(
me
.
options
.
AttrTimeout
,
&
out
.
AttrValid
,
&
out
.
AttrValidNsec
)
if
!
fi
.
IsDirectory
()
{
fi
.
Nlink
=
1
}
CopyFileInfo
(
fi
,
&
out
.
Attr
)
me
.
setOwner
(
&
out
.
Attr
)
}
func
(
me
*
fileSystemMount
)
fileInfoToAttr
(
fi
*
os
.
FileInfo
,
out
*
AttrOut
)
{
CopyFileInfo
(
fi
,
&
out
.
Attr
)
SplitNs
(
me
.
options
.
AttrTimeout
,
&
out
.
AttrValid
,
&
out
.
AttrValidNsec
)
me
.
setOwner
(
&
out
.
Attr
)
}
func
(
me
*
FileSystemConnector
)
getOpenedFile
(
h
uint64
)
*
openedFile
{
b
:=
(
*
openedFile
)(
unsafe
.
Pointer
(
DecodeHandle
(
h
)))
return
b
}
func
(
me
*
fileSystemMount
)
unregisterFileHandle
(
handle
uint64
,
node
*
inode
)
*
openedFile
{
obj
:=
me
.
openFiles
.
Forget
(
handle
)
opened
:=
(
*
openedFile
)(
unsafe
.
Pointer
(
obj
))
node
.
OpenFilesMutex
.
Lock
()
defer
node
.
OpenFilesMutex
.
Unlock
()
idx
:=
-
1
for
i
,
v
:=
range
node
.
OpenFiles
{
if
v
==
opened
{
idx
=
i
break
}
}
l
:=
len
(
node
.
OpenFiles
)
node
.
OpenFiles
[
idx
]
=
node
.
OpenFiles
[
l
-
1
]
node
.
OpenFiles
=
node
.
OpenFiles
[
:
l
-
1
]
return
opened
}
func
(
me
*
fileSystemMount
)
registerFileHandle
(
node
*
inode
,
dir
rawDir
,
f
File
,
flags
uint32
)
(
uint64
,
*
openedFile
)
{
node
.
OpenFilesMutex
.
Lock
()
defer
node
.
OpenFilesMutex
.
Unlock
()
b
:=
&
openedFile
{
dir
:
dir
,
file
:
f
,
OpenFlags
:
flags
,
}
withFlags
,
ok
:=
f
.
(
*
WithFlags
)
if
ok
{
b
.
FuseFlags
=
withFlags
.
Flags
f
=
withFlags
.
File
}
node
.
OpenFiles
=
append
(
node
.
OpenFiles
,
b
)
handle
:=
me
.
openFiles
.
Register
(
&
b
.
Handled
)
return
handle
,
b
}
fuse/
path
ops.go
→
fuse/
fs
ops.go
View file @
94429a4b
//
Translation of raw operation to path based operations.
//
FileSystemConnector's implementation of RawFileSystem
package
fuse
package
fuse
...
@@ -11,39 +11,14 @@ import (
...
@@ -11,39 +11,14 @@ import (
var
_
=
log
.
Println
var
_
=
log
.
Println
func
NewFileSystemConnector
(
fs
FileSystem
,
opts
*
FileSystemOptions
)
(
me
*
FileSystemConnector
)
{
me
=
new
(
FileSystemConnector
)
if
opts
==
nil
{
opts
=
NewFileSystemOptions
()
}
me
.
inodeMap
=
NewHandleMap
(
!
opts
.
SkipCheckHandles
)
me
.
rootNode
=
me
.
newInode
(
true
)
me
.
rootNode
.
NodeId
=
FUSE_ROOT_ID
me
.
verify
()
me
.
mountRoot
(
fs
,
opts
)
return
me
}
func
(
me
*
FileSystemConnector
)
GetPath
(
nodeid
uint64
)
(
path
string
,
mount
*
fileSystemMount
,
node
*
inode
)
{
n
:=
me
.
getInodeData
(
nodeid
)
p
:=
n
.
fsInode
.
GetPath
()
return
p
,
n
.
mount
,
n
}
func
(
me
*
fileSystemMount
)
setOwner
(
attr
*
Attr
)
{
func
(
me
*
FileSystemConnector
)
Init
(
fsInit
*
RawFsInit
)
{
if
me
.
options
.
Owner
!=
nil
{
me
.
fsInit
=
*
fsInit
attr
.
Owner
=
*
me
.
options
.
Owner
}
}
}
func
(
me
*
FileSystemConnector
)
Lookup
(
header
*
InHeader
,
name
string
)
(
out
*
EntryOut
,
status
Status
)
{
func
(
me
*
FileSystemConnector
)
Lookup
(
header
*
InHeader
,
name
string
)
(
out
*
EntryOut
,
status
Status
)
{
parent
:=
me
.
getInodeData
(
header
.
NodeId
)
parent
:=
me
.
getInodeData
(
header
.
NodeId
)
return
me
.
internalLookup
(
parent
,
name
,
1
,
&
header
.
Context
)
out
,
status
,
_
=
me
.
internalLookup
(
parent
,
name
,
1
,
&
header
.
Context
)
}
func
(
me
*
FileSystemConnector
)
internalLookup
(
parent
*
inode
,
name
string
,
lookupCount
int
,
context
*
Context
)
(
out
*
EntryOut
,
status
Status
)
{
out
,
status
,
_
=
me
.
internalLookupWithNode
(
parent
,
name
,
lookupCount
,
context
)
return
out
,
status
return
out
,
status
}
}
...
@@ -66,7 +41,7 @@ func (me *FileSystemConnector) internalMountLookup(mount *fileSystemMount, looku
...
@@ -66,7 +41,7 @@ func (me *FileSystemConnector) internalMountLookup(mount *fileSystemMount, looku
return
out
,
OK
,
mount
.
mountInode
return
out
,
OK
,
mount
.
mountInode
}
}
func
(
me
*
FileSystemConnector
)
internalLookup
WithNode
(
parent
*
inode
,
name
string
,
lookupCount
int
,
context
*
Context
)
(
out
*
EntryOut
,
status
Status
,
node
*
inode
)
{
func
(
me
*
FileSystemConnector
)
internalLookup
(
parent
*
inode
,
name
string
,
lookupCount
int
,
context
*
Context
)
(
out
*
EntryOut
,
status
Status
,
node
*
inode
)
{
if
mount
:=
me
.
lookupMount
(
parent
,
name
,
lookupCount
);
mount
!=
nil
{
if
mount
:=
me
.
lookupMount
(
parent
,
name
,
lookupCount
);
mount
!=
nil
{
return
me
.
internalMountLookup
(
mount
,
lookupCount
)
return
me
.
internalMountLookup
(
mount
,
lookupCount
)
}
}
...
@@ -206,9 +181,9 @@ func (me *FileSystemConnector) Mknod(header *InHeader, input *MknodIn, name stri
...
@@ -206,9 +181,9 @@ func (me *FileSystemConnector) Mknod(header *InHeader, input *MknodIn, name stri
n
:=
me
.
getInodeData
(
header
.
NodeId
)
n
:=
me
.
getInodeData
(
header
.
NodeId
)
code
=
n
.
fsInode
.
Mknod
(
name
,
input
.
Mode
,
uint32
(
input
.
Rdev
),
&
header
.
Context
)
code
=
n
.
fsInode
.
Mknod
(
name
,
input
.
Mode
,
uint32
(
input
.
Rdev
),
&
header
.
Context
)
if
code
.
Ok
()
{
if
code
.
Ok
()
{
return
me
.
internalLookup
(
n
,
name
,
1
,
&
header
.
Context
)
out
,
code
,
_
=
me
.
internalLookup
(
n
,
name
,
1
,
&
header
.
Context
)
}
}
return
nil
,
code
return
out
,
code
}
}
func
(
me
*
FileSystemConnector
)
Mkdir
(
header
*
InHeader
,
input
*
MkdirIn
,
name
string
)
(
out
*
EntryOut
,
code
Status
)
{
func
(
me
*
FileSystemConnector
)
Mkdir
(
header
*
InHeader
,
input
*
MkdirIn
,
name
string
)
(
out
*
EntryOut
,
code
Status
)
{
...
@@ -216,7 +191,7 @@ func (me *FileSystemConnector) Mkdir(header *InHeader, input *MkdirIn, name stri
...
@@ -216,7 +191,7 @@ func (me *FileSystemConnector) Mkdir(header *InHeader, input *MkdirIn, name stri
code
=
parent
.
fsInode
.
Mkdir
(
name
,
input
.
Mode
,
&
header
.
Context
)
code
=
parent
.
fsInode
.
Mkdir
(
name
,
input
.
Mode
,
&
header
.
Context
)
if
code
.
Ok
()
{
if
code
.
Ok
()
{
out
,
code
=
me
.
internalLookup
(
parent
,
name
,
1
,
&
header
.
Context
)
out
,
code
,
_
=
me
.
internalLookup
(
parent
,
name
,
1
,
&
header
.
Context
)
}
}
return
out
,
code
return
out
,
code
}
}
...
@@ -245,9 +220,9 @@ func (me *FileSystemConnector) Symlink(header *InHeader, pointedTo string, linkN
...
@@ -245,9 +220,9 @@ func (me *FileSystemConnector) Symlink(header *InHeader, pointedTo string, linkN
parent
:=
me
.
getInodeData
(
header
.
NodeId
)
parent
:=
me
.
getInodeData
(
header
.
NodeId
)
code
=
parent
.
fsInode
.
Symlink
(
linkName
,
pointedTo
,
&
header
.
Context
)
code
=
parent
.
fsInode
.
Symlink
(
linkName
,
pointedTo
,
&
header
.
Context
)
if
code
.
Ok
()
{
if
code
.
Ok
()
{
return
me
.
internalLookup
(
parent
,
linkName
,
1
,
&
header
.
Context
)
out
,
code
,
_
=
me
.
internalLookup
(
parent
,
linkName
,
1
,
&
header
.
Context
)
}
}
return
nil
,
code
return
out
,
code
}
}
...
@@ -283,7 +258,8 @@ func (me *FileSystemConnector) Link(header *InHeader, input *LinkIn, filename st
...
@@ -283,7 +258,8 @@ func (me *FileSystemConnector) Link(header *InHeader, input *LinkIn, filename st
return
nil
,
code
return
nil
,
code
}
}
// TODO - revise this for real hardlinks?
// TODO - revise this for real hardlinks?
return
me
.
internalLookup
(
parent
,
filename
,
1
,
&
header
.
Context
)
out
,
code
,
_
=
me
.
internalLookup
(
parent
,
filename
,
1
,
&
header
.
Context
)
return
out
,
code
}
}
func
(
me
*
FileSystemConnector
)
Access
(
header
*
InHeader
,
input
*
AccessIn
)
(
code
Status
)
{
func
(
me
*
FileSystemConnector
)
Access
(
header
*
InHeader
,
input
*
AccessIn
)
(
code
Status
)
{
...
@@ -298,7 +274,7 @@ func (me *FileSystemConnector) Create(header *InHeader, input *CreateIn, name st
...
@@ -298,7 +274,7 @@ func (me *FileSystemConnector) Create(header *InHeader, input *CreateIn, name st
return
0
,
0
,
nil
,
code
return
0
,
0
,
nil
,
code
}
}
out
,
code
,
inode
:=
me
.
internalLookup
WithNode
(
parent
,
name
,
1
,
&
header
.
Context
)
out
,
code
,
inode
:=
me
.
internalLookup
(
parent
,
name
,
1
,
&
header
.
Context
)
if
inode
==
nil
{
if
inode
==
nil
{
msg
:=
fmt
.
Sprintf
(
"Create succeded, but GetAttr returned no entry %v, %q. code %v"
,
header
.
NodeId
,
name
,
code
)
msg
:=
fmt
.
Sprintf
(
"Create succeded, but GetAttr returned no entry %v, %q. code %v"
,
header
.
NodeId
,
name
,
code
)
panic
(
msg
)
panic
(
msg
)
...
@@ -308,18 +284,19 @@ func (me *FileSystemConnector) Create(header *InHeader, input *CreateIn, name st
...
@@ -308,18 +284,19 @@ func (me *FileSystemConnector) Create(header *InHeader, input *CreateIn, name st
}
}
func
(
me
*
FileSystemConnector
)
Release
(
header
*
InHeader
,
input
*
ReleaseIn
)
{
func
(
me
*
FileSystemConnector
)
Release
(
header
*
InHeader
,
input
*
ReleaseIn
)
{
opened
:=
me
.
getOpenedFile
(
input
.
Fh
)
node
:=
me
.
getInodeData
(
header
.
NodeId
)
opened
.
inode
.
mount
.
unregisterFileHandle
(
input
.
Fh
)
node
.
mount
.
unregisterFileHandle
(
input
.
Fh
,
node
)
}
}
func
(
me
*
FileSystemConnector
)
Flush
(
header
*
InHeader
,
input
*
FlushIn
)
Status
{
func
(
me
*
FileSystemConnector
)
Flush
(
header
*
InHeader
,
input
*
FlushIn
)
Status
{
node
:=
me
.
getInodeData
(
header
.
NodeId
)
opened
:=
me
.
getOpenedFile
(
input
.
Fh
)
opened
:=
me
.
getOpenedFile
(
input
.
Fh
)
return
opened
.
i
node
.
fsInode
.
Flush
(
opened
.
file
,
opened
.
OpenFlags
,
&
header
.
Context
)
return
node
.
fsInode
.
Flush
(
opened
.
file
,
opened
.
OpenFlags
,
&
header
.
Context
)
}
}
func
(
me
*
FileSystemConnector
)
ReleaseDir
(
header
*
InHeader
,
input
*
ReleaseIn
)
{
func
(
me
*
FileSystemConnector
)
ReleaseDir
(
header
*
InHeader
,
input
*
ReleaseIn
)
{
node
:=
me
.
getInodeData
(
header
.
NodeId
)
node
:=
me
.
getInodeData
(
header
.
NodeId
)
opened
:=
node
.
mount
.
unregisterFileHandle
(
input
.
Fh
)
opened
:=
node
.
mount
.
unregisterFileHandle
(
input
.
Fh
,
node
)
opened
.
dir
.
Release
()
opened
.
dir
.
Release
()
me
.
considerDropInode
(
node
)
me
.
considerDropInode
(
node
)
}
}
...
...
fuse/inode.go
0 → 100644
View file @
94429a4b
package
fuse
import
(
"fmt"
"sync"
)
// The inode reflects the kernel's idea of the inode.
type
inode
struct
{
Handled
// Constant during lifetime.
NodeId
uint64
// Number of open files and its protection.
OpenFilesMutex
sync
.
Mutex
OpenFiles
[]
*
openedFile
// treeLock is a pointer to me.mount.treeLock; we need store
// this mutex separately, since unmount may set me.mount = nil
// during Unmount(). Constant during lifetime.
//
// If multiple treeLocks must be acquired, the treeLocks
// closer to the root must be acquired first.
treeLock
*
sync
.
RWMutex
// All data below is protected by treeLock.
fsInode
*
fsInode
Children
map
[
string
]
*
inode
// Contains directories that function as mounts. The entries
// are duplicated in Children.
Mounts
map
[
string
]
*
fileSystemMount
LookupCount
int
// Non-nil if this is a mountpoint.
mountPoint
*
fileSystemMount
// The file system to which this node belongs. Is constant
// during the lifetime, except upon Unmount() when it is set
// to nil.
mount
*
fileSystemMount
}
// Must be called with treeLock for the mount held.
func
(
me
*
inode
)
addChild
(
name
string
,
child
*
inode
)
{
if
paranoia
{
ch
:=
me
.
Children
[
name
]
if
ch
!=
nil
{
panic
(
fmt
.
Sprintf
(
"Already have an inode with same name: %v: %v"
,
name
,
ch
))
}
}
me
.
Children
[
name
]
=
child
me
.
fsInode
.
addChild
(
name
,
child
.
fsInode
)
}
// Must be called with treeLock for the mount held.
func
(
me
*
inode
)
rmChild
(
name
string
)
(
ch
*
inode
)
{
ch
=
me
.
Children
[
name
]
if
ch
!=
nil
{
me
.
Children
[
name
]
=
nil
,
false
me
.
fsInode
.
rmChild
(
name
,
ch
.
fsInode
)
}
return
ch
}
// Can only be called on untouched inodes.
func
(
me
*
inode
)
mountFs
(
fs
FileSystem
,
opts
*
FileSystemOptions
)
{
me
.
mountPoint
=
&
fileSystemMount
{
fs
:
fs
,
openFiles
:
NewHandleMap
(
true
),
mountInode
:
me
,
options
:
opts
,
}
me
.
mount
=
me
.
mountPoint
me
.
treeLock
=
&
me
.
mountPoint
.
treeLock
}
// Must be called with treeLock held.
func
(
me
*
inode
)
canUnmount
()
bool
{
for
_
,
v
:=
range
me
.
Children
{
if
v
.
mountPoint
!=
nil
{
// This access may be out of date, but it is no
// problem to err on the safe side.
return
false
}
if
!
v
.
canUnmount
()
{
return
false
}
}
me
.
OpenFilesMutex
.
Lock
()
defer
me
.
OpenFilesMutex
.
Unlock
()
return
len
(
me
.
OpenFiles
)
==
0
}
func
(
me
*
inode
)
IsDir
()
bool
{
return
me
.
Children
!=
nil
}
func
(
me
*
inode
)
getMountDirEntries
()
(
out
[]
DirEntry
)
{
me
.
treeLock
.
RLock
()
defer
me
.
treeLock
.
RUnlock
()
for
k
,
_
:=
range
me
.
Mounts
{
out
=
append
(
out
,
DirEntry
{
Name
:
k
,
Mode
:
S_IFDIR
,
})
}
return
out
}
// Returns any open file, preferably a r/w one.
func
(
me
*
inode
)
getAnyFile
()
(
file
File
)
{
me
.
OpenFilesMutex
.
Lock
()
defer
me
.
OpenFilesMutex
.
Unlock
()
for
_
,
f
:=
range
me
.
OpenFiles
{
if
file
==
nil
||
f
.
OpenFlags
&
O_ANYWRITE
!=
0
{
file
=
f
.
file
}
}
return
file
}
// Returns an open writable file for the given inode.
func
(
me
*
inode
)
getWritableFiles
()
(
files
[]
File
)
{
me
.
OpenFilesMutex
.
Lock
()
defer
me
.
OpenFilesMutex
.
Unlock
()
for
_
,
f
:=
range
me
.
OpenFiles
{
if
f
.
OpenFlags
&
O_ANYWRITE
!=
0
{
files
=
append
(
files
,
f
.
file
)
}
}
return
files
}
const
initDirSize
=
20
func
(
me
*
inode
)
verify
(
cur
*
fileSystemMount
)
{
if
me
.
mountPoint
!=
nil
{
if
me
!=
me
.
mountPoint
.
mountInode
{
panic
(
"mountpoint mismatch"
)
}
cur
=
me
.
mountPoint
}
if
me
.
mount
!=
cur
{
panic
(
fmt
.
Sprintf
(
"me.mount not set correctly %v %v"
,
me
.
mount
,
cur
))
}
for
name
,
m
:=
range
me
.
Mounts
{
if
m
.
mountInode
!=
me
.
Children
[
name
]
{
panic
(
fmt
.
Sprintf
(
"mountpoint parent mismatch: node:%v name:%v ch:%v"
,
me
.
mountPoint
,
name
,
me
.
Children
))
}
}
for
_
,
ch
:=
range
me
.
Children
{
if
ch
==
nil
{
panic
(
"Found nil child."
)
}
ch
.
verify
(
cur
)
}
}
fuse/pathdebug.go
View file @
94429a4b
...
@@ -149,11 +149,6 @@ func (me *FileSystemDebug) AddMountState(state *MountState) {
...
@@ -149,11 +149,6 @@ func (me *FileSystemDebug) AddMountState(state *MountState) {
func
()
[]
byte
{
return
[]
byte
(
state
.
BufferPoolStats
())
})
func
()
[]
byte
{
return
[]
byte
(
state
.
BufferPoolStats
())
})
}
}
func
(
me
*
FileSystemDebug
)
AddFileSystemConnector
(
conn
*
FileSystemConnector
)
{
me
.
Add
(
"filesystemconnector-stats"
,
func
()
[]
byte
{
return
[]
byte
(
conn
.
Statistics
())
})
}
func
hotPaths
(
timing
*
TimingFileSystem
)
[]
byte
{
func
hotPaths
(
timing
*
TimingFileSystem
)
[]
byte
{
hot
:=
timing
.
HotPaths
(
"GetAttr"
)
hot
:=
timing
.
HotPaths
(
"GetAttr"
)
unique
:=
len
(
hot
)
unique
:=
len
(
hot
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment