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
Levin Zimmermann
go-fuse
Commits
c254e3ec
Commit
c254e3ec
authored
Apr 22, 2011
by
Han-Wen Nienhuys
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Use arrays for opcode dispatches.
parent
88b3aa85
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
404 additions
and
400 deletions
+404
-400
fuse/fuse.go
fuse/fuse.go
+39
-238
fuse/lockingfs.go
fuse/lockingfs.go
+0
-18
fuse/loopback_test.go
fuse/loopback_test.go
+10
-10
fuse/opcode.go
fuse/opcode.go
+332
-90
fuse/pathdebug.go
fuse/pathdebug.go
+3
-3
fuse/pathfilesystem.go
fuse/pathfilesystem.go
+8
-8
fuse/timingrawfs.go
fuse/timingrawfs.go
+0
-15
fuse/types.go
fuse/types.go
+12
-6
fuse/wrappedfs.go
fuse/wrappedfs.go
+0
-12
No files found.
fuse/fuse.go
View file @
c254e3ec
// Code that handles the control loop, and en/decoding messages
// to/from the kernel. Dispatches calls into RawFileSystem.
package
fuse
package
fuse
import
(
import
(
"bytes"
"fmt"
"fmt"
"log"
"log"
"os"
"os"
...
@@ -28,8 +30,9 @@ type request struct {
...
@@ -28,8 +30,9 @@ type request struct {
inputBuf
[]
byte
inputBuf
[]
byte
// These split up inputBuf.
// These split up inputBuf.
inHeader
*
InHeader
inHeader
*
InHeader
// generic header
arg
[]
byte
inData
unsafe
.
Pointer
// per op data
arg
[]
byte
// flat data.
// Unstructured data, a pointer to the relevant XxxxOut struct.
// Unstructured data, a pointer to the relevant XxxxOut struct.
data
unsafe
.
Pointer
data
unsafe
.
Pointer
...
@@ -46,6 +49,14 @@ type request struct {
...
@@ -46,6 +49,14 @@ type request struct {
preWriteNs
int64
preWriteNs
int64
}
}
func
(
me
*
request
)
filename
()
string
{
return
strings
.
TrimRight
(
string
(
me
.
arg
),
"
\x00
"
)
}
func
(
me
*
request
)
filenames
(
count
int
)
[]
string
{
return
strings
.
Split
(
string
(
me
.
arg
),
"
\x00
"
,
count
)
}
type
MountState
struct
{
type
MountState
struct
{
// Empty if unmounted.
// Empty if unmounted.
mountPoint
string
mountPoint
string
...
@@ -252,6 +263,10 @@ func (me *MountState) handle(req *request) {
...
@@ -252,6 +263,10 @@ func (me *MountState) handle(req *request) {
req
.
inHeader
=
(
*
InHeader
)(
unsafe
.
Pointer
(
&
req
.
inputBuf
[
0
]))
req
.
inHeader
=
(
*
InHeader
)(
unsafe
.
Pointer
(
&
req
.
inputBuf
[
0
]))
req
.
arg
=
req
.
inputBuf
[
inHSize
:
]
req
.
arg
=
req
.
inputBuf
[
inHSize
:
]
me
.
dispatch
(
req
)
me
.
dispatch
(
req
)
// If we try to write OK, nil, we will get
// error: writer: Writev [[16 0 0 0 0 0 0 0 17 0 0 0 0 0 0 0]]
// failed, err: writev: no such file or directory
if
req
.
inHeader
.
Opcode
!=
FUSE_FORGET
{
if
req
.
inHeader
.
Opcode
!=
FUSE_FORGET
{
serialize
(
req
,
me
.
Debug
)
serialize
(
req
,
me
.
Debug
)
req
.
preWriteNs
=
time
.
Nanoseconds
()
req
.
preWriteNs
=
time
.
Nanoseconds
()
...
@@ -260,165 +275,40 @@ func (me *MountState) handle(req *request) {
...
@@ -260,165 +275,40 @@ func (me *MountState) handle(req *request) {
}
}
func
(
me
*
MountState
)
dispatch
(
req
*
request
)
{
func
(
me
*
MountState
)
dispatch
(
req
*
request
)
{
h
:=
req
.
inHeader
argSize
,
ok
:=
inputSize
(
req
.
inHeader
.
Opcode
)
argumentSize
,
ok
:=
inputSizeMap
[
int
(
h
.
Opcode
)]
if
!
ok
{
if
!
ok
{
log
.
Println
(
"Unknown opcode %d (input)"
,
h
.
Opcode
)
log
.
Println
(
"Unknown opcode %d (input)"
,
req
.
inHeader
.
Opcode
)
req
.
status
=
ENOSYS
req
.
status
=
ENOSYS
return
return
}
}
if
len
(
req
.
arg
)
<
argumentSize
{
log
.
Println
(
"Short read for %v: %v"
,
h
.
Opcode
,
req
.
arg
)
if
len
(
req
.
arg
)
<
argSize
{
log
.
Println
(
"Short read for %v: %v"
,
req
.
inHeader
.
Opcode
,
req
.
arg
)
req
.
status
=
EIO
req
.
status
=
EIO
return
return
}
}
var
inData
unsafe
.
Pointer
if
argSize
>
0
{
if
argumentSize
>
0
{
req
.
inData
=
unsafe
.
Pointer
(
&
req
.
arg
[
0
])
inData
=
unsafe
.
Pointer
(
&
req
.
arg
[
0
])
req
.
arg
=
req
.
arg
[
argSize
:
]
}
data
:=
req
.
arg
[
argumentSize
:
]
var
status
Status
=
OK
fs
:=
me
.
fileSystem
filename
:=
""
// Perhaps a map is faster?
if
h
.
Opcode
==
FUSE_UNLINK
||
h
.
Opcode
==
FUSE_RMDIR
||
h
.
Opcode
==
FUSE_LOOKUP
||
h
.
Opcode
==
FUSE_MKDIR
||
h
.
Opcode
==
FUSE_MKNOD
||
h
.
Opcode
==
FUSE_CREATE
||
h
.
Opcode
==
FUSE_LINK
||
h
.
Opcode
==
FUSE_GETXATTR
||
h
.
Opcode
==
FUSE_REMOVEXATTR
{
filename
=
strings
.
TrimRight
(
string
(
data
),
"
\x00
"
)
}
if
me
.
Debug
{
nm
:=
""
if
filename
!=
""
{
nm
=
"n: '"
+
filename
+
"'"
}
if
h
.
Opcode
==
FUSE_RENAME
{
nm
=
"n: '"
+
string
(
data
)
+
"'"
}
log
.
Printf
(
"Dispatch: %v, NodeId: %v %s
\n
"
,
operationName
(
h
.
Opcode
),
h
.
NodeId
,
nm
)
}
}
// Follow ordering of fuse_lowlevel.h.
f
:=
lookupOperation
(
req
.
inHeader
.
Opcode
)
switch
h
.
Opcode
{
if
f
==
nil
{
case
FUSE_INIT
:
msg
:=
fmt
.
Sprintf
(
"Unsupported OpCode: %d=%v"
,
req
.
data
,
status
=
me
.
init
(
h
,
(
*
InitIn
)(
inData
))
req
.
inHeader
.
Opcode
,
operationName
(
req
.
inHeader
.
Opcode
))
case
FUSE_DESTROY
:
me
.
Error
(
os
.
NewError
(
msg
))
fs
.
Destroy
(
h
,
(
*
InitIn
)(
inData
))
case
FUSE_LOOKUP
:
lookupOut
,
s
:=
fs
.
Lookup
(
h
,
filename
)
status
=
s
req
.
data
=
unsafe
.
Pointer
(
lookupOut
)
case
FUSE_FORGET
:
fs
.
Forget
(
h
,
(
*
ForgetIn
)(
inData
))
// If we try to write OK, nil, we will get
// error: writer: Writev [[16 0 0 0 0 0 0 0 17 0 0 0 0 0 0 0]]
// failed, err: writev: no such file or directory
return
case
FUSE_GETATTR
:
// TODO - if inData.Fh is set, do file.GetAttr
attrOut
,
s
:=
fs
.
GetAttr
(
h
,
(
*
GetAttrIn
)(
inData
))
status
=
s
req
.
data
=
unsafe
.
Pointer
(
attrOut
)
case
FUSE_SETATTR
:
req
.
data
,
status
=
doSetattr
(
me
,
h
,
(
*
SetAttrIn
)(
inData
))
case
FUSE_READLINK
:
req
.
flatData
,
status
=
fs
.
Readlink
(
h
)
case
FUSE_MKNOD
:
entryOut
,
s
:=
fs
.
Mknod
(
h
,
(
*
MknodIn
)(
inData
),
filename
)
status
=
s
req
.
data
=
unsafe
.
Pointer
(
entryOut
)
case
FUSE_MKDIR
:
entryOut
,
s
:=
fs
.
Mkdir
(
h
,
(
*
MkdirIn
)(
inData
),
filename
)
status
=
s
req
.
data
=
unsafe
.
Pointer
(
entryOut
)
case
FUSE_UNLINK
:
status
=
fs
.
Unlink
(
h
,
filename
)
case
FUSE_RMDIR
:
status
=
fs
.
Rmdir
(
h
,
filename
)
case
FUSE_SYMLINK
:
filenames
:=
strings
.
Split
(
string
(
data
),
"
\x00
"
,
3
)
if
len
(
filenames
)
>=
2
{
entryOut
,
s
:=
fs
.
Symlink
(
h
,
filenames
[
1
],
filenames
[
0
])
status
=
s
req
.
data
=
unsafe
.
Pointer
(
entryOut
)
}
else
{
status
=
EIO
}
case
FUSE_RENAME
:
filenames
:=
strings
.
Split
(
string
(
data
),
"
\x00
"
,
3
)
if
len
(
filenames
)
>=
2
{
status
=
fs
.
Rename
(
h
,
(
*
RenameIn
)(
inData
),
filenames
[
0
],
filenames
[
1
])
}
else
{
status
=
EIO
}
case
FUSE_LINK
:
entryOut
,
s
:=
fs
.
Link
(
h
,
(
*
LinkIn
)(
inData
),
filename
)
status
=
s
req
.
data
=
unsafe
.
Pointer
(
entryOut
)
case
FUSE_OPEN
:
req
.
data
,
status
=
doOpen
(
me
,
h
,
(
*
OpenIn
)(
inData
))
case
FUSE_READ
:
req
.
flatData
,
status
=
me
.
fileSystem
.
Read
((
*
ReadIn
)(
inData
),
me
.
buffers
)
case
FUSE_WRITE
:
req
.
data
,
status
=
doWrite
(
me
,
h
,
(
*
WriteIn
)(
inData
),
data
)
case
FUSE_FLUSH
:
status
=
me
.
fileSystem
.
Flush
((
*
FlushIn
)(
inData
))
case
FUSE_RELEASE
:
me
.
fileSystem
.
Release
(
h
,
(
*
ReleaseIn
)(
inData
))
case
FUSE_FSYNC
:
status
=
me
.
fileSystem
.
Fsync
((
*
FsyncIn
)(
inData
))
case
FUSE_OPENDIR
:
req
.
data
,
status
=
doOpenDir
(
me
,
h
,
(
*
OpenIn
)(
inData
))
case
FUSE_READDIR
:
req
.
flatData
,
status
=
doReadDir
(
me
,
h
,
(
*
ReadIn
)(
inData
))
case
FUSE_RELEASEDIR
:
me
.
fileSystem
.
ReleaseDir
(
h
,
(
*
ReleaseIn
)(
inData
))
case
FUSE_FSYNCDIR
:
status
=
me
.
fileSystem
.
FsyncDir
(
h
,
(
*
FsyncIn
)(
inData
))
case
FUSE_SETXATTR
:
splits
:=
bytes
.
Split
(
data
,
[]
byte
{
0
},
2
)
status
=
fs
.
SetXAttr
(
h
,
(
*
SetXAttrIn
)(
inData
),
string
(
splits
[
0
]),
splits
[
1
])
case
FUSE_GETXATTR
:
req
.
data
,
req
.
flatData
,
status
=
doGetXAttr
(
me
,
h
,
(
*
GetXAttrIn
)(
inData
),
filename
,
h
.
Opcode
)
case
FUSE_LISTXATTR
:
req
.
data
,
req
.
flatData
,
status
=
doGetXAttr
(
me
,
h
,
(
*
GetXAttrIn
)(
inData
),
filename
,
h
.
Opcode
)
case
FUSE_REMOVEXATTR
:
status
=
fs
.
RemoveXAttr
(
h
,
filename
)
case
FUSE_ACCESS
:
status
=
fs
.
Access
(
h
,
(
*
AccessIn
)(
inData
))
case
FUSE_CREATE
:
req
.
data
,
status
=
doCreate
(
me
,
h
,
(
*
CreateIn
)(
inData
),
filename
)
// TODO - implement file locking.
// case FUSE_SETLK
// case FUSE_SETLKW
case
FUSE_BMAP
:
bmapOut
,
s
:=
fs
.
Bmap
(
h
,
(
*
BmapIn
)(
inData
))
status
=
s
req
.
data
=
unsafe
.
Pointer
(
bmapOut
)
case
FUSE_IOCTL
:
ioctlOut
,
s
:=
fs
.
Ioctl
(
h
,
(
*
IoctlIn
)(
inData
))
status
=
s
req
.
data
=
unsafe
.
Pointer
(
ioctlOut
)
case
FUSE_POLL
:
pollOut
,
s
:=
fs
.
Poll
(
h
,
(
*
PollIn
)(
inData
))
status
=
s
req
.
data
=
unsafe
.
Pointer
(
pollOut
)
// TODO - figure out how to support this
// case FUSE_INTERRUPT
default
:
me
.
Error
(
os
.
NewError
(
fmt
.
Sprintf
(
"Unsupported OpCode: %d=%v"
,
h
.
Opcode
,
operationName
(
h
.
Opcode
))))
req
.
status
=
ENOSYS
req
.
status
=
ENOSYS
return
return
}
}
req
.
status
=
status
if
me
.
Debug
{
nm
:=
""
// TODO - reinstate filename printing.
log
.
Printf
(
"Dispatch: %v, NodeId: %v %s
\n
"
,
operationName
(
req
.
inHeader
.
Opcode
),
req
.
inHeader
.
NodeId
,
nm
)
}
f
(
me
,
req
)
}
}
// Thanks to Andrew Gerrand for this hack.
// Thanks to Andrew Gerrand for this hack.
...
@@ -428,7 +318,7 @@ func asSlice(ptr unsafe.Pointer, byteCount int) []byte {
...
@@ -428,7 +318,7 @@ func asSlice(ptr unsafe.Pointer, byteCount int) []byte {
}
}
func
serialize
(
req
*
request
,
debug
bool
)
{
func
serialize
(
req
*
request
,
debug
bool
)
{
dataLength
,
ok
:=
outputSize
Map
[
int
(
req
.
inHeader
.
Opcode
)]
dataLength
,
ok
:=
outputSize
(
req
.
inHeader
.
Opcode
)
if
!
ok
{
if
!
ok
{
log
.
Println
(
"Unknown opcode %d (output)"
,
req
.
inHeader
.
Opcode
)
log
.
Println
(
"Unknown opcode %d (output)"
,
req
.
inHeader
.
Opcode
)
req
.
status
=
ENOSYS
req
.
status
=
ENOSYS
...
@@ -487,92 +377,3 @@ func (me *MountState) init(h *InHeader, input *InitIn) (unsafe.Pointer, Status)
...
@@ -487,92 +377,3 @@ func (me *MountState) init(h *InHeader, input *InitIn) (unsafe.Pointer, Status)
return
unsafe
.
Pointer
(
out
),
OK
return
unsafe
.
Pointer
(
out
),
OK
}
}
////////////////////////////////////////////////////////////////
// Handling files.
func
doOpen
(
state
*
MountState
,
header
*
InHeader
,
input
*
OpenIn
)
(
unsafe
.
Pointer
,
Status
)
{
flags
,
handle
,
status
:=
state
.
fileSystem
.
Open
(
header
,
input
)
if
status
!=
OK
{
return
nil
,
status
}
out
:=
new
(
OpenOut
)
out
.
Fh
=
handle
out
.
OpenFlags
=
flags
return
unsafe
.
Pointer
(
out
),
status
}
func
doCreate
(
state
*
MountState
,
header
*
InHeader
,
input
*
CreateIn
,
name
string
)
(
unsafe
.
Pointer
,
Status
)
{
flags
,
handle
,
entry
,
status
:=
state
.
fileSystem
.
Create
(
header
,
input
,
name
)
if
status
!=
OK
{
return
nil
,
status
}
out
:=
new
(
CreateOut
)
out
.
Entry
=
*
entry
out
.
Open
.
Fh
=
handle
out
.
Open
.
OpenFlags
=
flags
return
unsafe
.
Pointer
(
out
),
status
}
func
doWrite
(
state
*
MountState
,
header
*
InHeader
,
input
*
WriteIn
,
data
[]
byte
)
(
out
unsafe
.
Pointer
,
code
Status
)
{
n
,
status
:=
state
.
fileSystem
.
Write
(
input
,
data
)
o
:=
&
WriteOut
{
Size
:
n
,
}
return
unsafe
.
Pointer
(
o
),
status
}
func
doSetattr
(
state
*
MountState
,
header
*
InHeader
,
input
*
SetAttrIn
)
(
out
unsafe
.
Pointer
,
code
Status
)
{
// TODO - if Fh != 0, we should do a FSetAttr instead.
o
,
s
:=
state
.
fileSystem
.
SetAttr
(
header
,
input
)
return
unsafe
.
Pointer
(
o
),
s
}
func
doGetXAttr
(
state
*
MountState
,
header
*
InHeader
,
input
*
GetXAttrIn
,
attr
string
,
opcode
uint32
)
(
out
unsafe
.
Pointer
,
data
[]
byte
,
code
Status
)
{
if
opcode
==
FUSE_GETXATTR
{
data
,
code
=
state
.
fileSystem
.
GetXAttr
(
header
,
attr
)
}
else
{
data
,
code
=
state
.
fileSystem
.
ListXAttr
(
header
)
}
if
code
!=
OK
{
return
nil
,
nil
,
code
}
size
:=
uint32
(
len
(
data
))
if
input
.
Size
==
0
{
out
:=
new
(
GetXAttrOut
)
out
.
Size
=
size
return
unsafe
.
Pointer
(
out
),
nil
,
OK
}
if
size
>
input
.
Size
{
return
nil
,
nil
,
ERANGE
}
return
nil
,
data
,
OK
}
////////////////////////////////////////////////////////////////
// Handling directories
func
doOpenDir
(
state
*
MountState
,
header
*
InHeader
,
input
*
OpenIn
)
(
unsafe
.
Pointer
,
Status
)
{
flags
,
handle
,
status
:=
state
.
fileSystem
.
OpenDir
(
header
,
input
)
if
status
!=
OK
{
return
nil
,
status
}
out
:=
new
(
OpenOut
)
out
.
Fh
=
handle
out
.
OpenFlags
=
flags
return
unsafe
.
Pointer
(
out
),
status
}
func
doReadDir
(
state
*
MountState
,
header
*
InHeader
,
input
*
ReadIn
)
(
out
[]
byte
,
code
Status
)
{
entries
,
code
:=
state
.
fileSystem
.
ReadDir
(
header
,
input
)
if
entries
==
nil
{
return
nil
,
code
}
return
entries
.
Bytes
(),
code
}
fuse/lockingfs.go
View file @
c254e3ec
...
@@ -296,24 +296,6 @@ func (me *LockingRawFileSystem) Create(header *InHeader, input *CreateIn, name s
...
@@ -296,24 +296,6 @@ func (me *LockingRawFileSystem) Create(header *InHeader, input *CreateIn, name s
return
me
.
Original
.
Create
(
header
,
input
,
name
)
return
me
.
Original
.
Create
(
header
,
input
,
name
)
}
}
func
(
me
*
LockingRawFileSystem
)
Bmap
(
header
*
InHeader
,
input
*
BmapIn
)
(
out
*
BmapOut
,
code
Status
)
{
me
.
lock
.
Lock
()
defer
me
.
lock
.
Unlock
()
return
me
.
Original
.
Bmap
(
header
,
input
)
}
func
(
me
*
LockingRawFileSystem
)
Ioctl
(
header
*
InHeader
,
input
*
IoctlIn
)
(
out
*
IoctlOut
,
code
Status
)
{
me
.
lock
.
Lock
()
defer
me
.
lock
.
Unlock
()
return
me
.
Original
.
Ioctl
(
header
,
input
)
}
func
(
me
*
LockingRawFileSystem
)
Poll
(
header
*
InHeader
,
input
*
PollIn
)
(
out
*
PollOut
,
code
Status
)
{
me
.
lock
.
Lock
()
defer
me
.
lock
.
Unlock
()
return
me
.
Original
.
Poll
(
header
,
input
)
}
func
(
me
*
LockingRawFileSystem
)
OpenDir
(
header
*
InHeader
,
input
*
OpenIn
)
(
flags
uint32
,
h
uint64
,
status
Status
)
{
func
(
me
*
LockingRawFileSystem
)
OpenDir
(
header
*
InHeader
,
input
*
OpenIn
)
(
flags
uint32
,
h
uint64
,
status
Status
)
{
me
.
lock
.
Lock
()
me
.
lock
.
Lock
()
defer
me
.
lock
.
Unlock
()
defer
me
.
lock
.
Unlock
()
...
...
fuse/loopback_test.go
View file @
c254e3ec
...
@@ -275,11 +275,11 @@ func (me *testCase) testSymlink() {
...
@@ -275,11 +275,11 @@ func (me *testCase) testSymlink() {
func
(
me
*
testCase
)
testRename
()
{
func
(
me
*
testCase
)
testRename
()
{
me
.
tester
.
Log
(
"Testing rename."
)
me
.
tester
.
Log
(
"Testing rename."
)
me
.
writeOrigFile
()
me
.
writeOrigFile
()
sd
:=
me
.
mountPoint
+
"/testRename"
sd
:=
me
.
mountPoint
+
"/testRename"
err
:=
os
.
MkdirAll
(
sd
,
0777
)
err
:=
os
.
MkdirAll
(
sd
,
0777
)
defer
os
.
RemoveAll
(
sd
)
defer
os
.
RemoveAll
(
sd
)
subFile
:=
sd
+
"/subfile"
subFile
:=
sd
+
"/subfile"
err
=
os
.
Rename
(
me
.
mountFile
,
subFile
)
err
=
os
.
Rename
(
me
.
mountFile
,
subFile
)
CheckSuccess
(
err
)
CheckSuccess
(
err
)
f
,
_
:=
os
.
Lstat
(
me
.
origFile
)
f
,
_
:=
os
.
Lstat
(
me
.
origFile
)
...
@@ -295,21 +295,21 @@ func (me *testCase) testRename() {
...
@@ -295,21 +295,21 @@ func (me *testCase) testRename() {
func
(
me
*
testCase
)
testDelRename
()
{
func
(
me
*
testCase
)
testDelRename
()
{
me
.
tester
.
Log
(
"Testing del+rename."
)
me
.
tester
.
Log
(
"Testing del+rename."
)
sd
:=
me
.
mountPoint
+
"/testDelRename"
sd
:=
me
.
mountPoint
+
"/testDelRename"
err
:=
os
.
MkdirAll
(
sd
,
0755
)
err
:=
os
.
MkdirAll
(
sd
,
0755
)
CheckSuccess
(
err
)
CheckSuccess
(
err
)
d
:=
sd
+
"/dest"
d
:=
sd
+
"/dest"
err
=
ioutil
.
WriteFile
(
d
,
[]
byte
(
"blabla"
),
0644
)
err
=
ioutil
.
WriteFile
(
d
,
[]
byte
(
"blabla"
),
0644
)
CheckSuccess
(
err
)
CheckSuccess
(
err
)
f
,
err
:=
os
.
Open
(
d
)
f
,
err
:=
os
.
Open
(
d
)
CheckSuccess
(
err
)
CheckSuccess
(
err
)
err
=
os
.
Remove
(
d
)
err
=
os
.
Remove
(
d
)
CheckSuccess
(
err
)
CheckSuccess
(
err
)
s
:=
sd
+
"/src"
s
:=
sd
+
"/src"
err
=
ioutil
.
WriteFile
(
s
,
[]
byte
(
"blabla"
),
0644
)
err
=
ioutil
.
WriteFile
(
s
,
[]
byte
(
"blabla"
),
0644
)
CheckSuccess
(
err
)
CheckSuccess
(
err
)
...
@@ -322,15 +322,15 @@ func (me *testCase) testDelRename() {
...
@@ -322,15 +322,15 @@ func (me *testCase) testDelRename() {
func
(
me
*
testCase
)
testOverwriteRename
()
{
func
(
me
*
testCase
)
testOverwriteRename
()
{
me
.
tester
.
Log
(
"Testing rename overwrite."
)
me
.
tester
.
Log
(
"Testing rename overwrite."
)
sd
:=
me
.
mountPoint
+
"/testOverwriteRename"
sd
:=
me
.
mountPoint
+
"/testOverwriteRename"
err
:=
os
.
MkdirAll
(
sd
,
0755
)
err
:=
os
.
MkdirAll
(
sd
,
0755
)
CheckSuccess
(
err
)
CheckSuccess
(
err
)
d
:=
sd
+
"/dest"
d
:=
sd
+
"/dest"
err
=
ioutil
.
WriteFile
(
d
,
[]
byte
(
"blabla"
),
0644
)
err
=
ioutil
.
WriteFile
(
d
,
[]
byte
(
"blabla"
),
0644
)
CheckSuccess
(
err
)
CheckSuccess
(
err
)
s
:=
sd
+
"/src"
s
:=
sd
+
"/src"
err
=
ioutil
.
WriteFile
(
s
,
[]
byte
(
"blabla"
),
0644
)
err
=
ioutil
.
WriteFile
(
s
,
[]
byte
(
"blabla"
),
0644
)
CheckSuccess
(
err
)
CheckSuccess
(
err
)
...
...
fuse/opcode.go
View file @
c254e3ec
package
fuse
package
fuse
import
(
import
(
"bytes"
"fmt"
"fmt"
"os"
"os"
"unsafe"
"unsafe"
...
@@ -13,7 +14,7 @@ func (code Status) String() string {
...
@@ -13,7 +14,7 @@ func (code Status) String() string {
return
fmt
.
Sprintf
(
"%d=%v"
,
int
(
code
),
os
.
Errno
(
code
))
return
fmt
.
Sprintf
(
"%d=%v"
,
int
(
code
),
os
.
Errno
(
code
))
}
}
func
replyString
(
opcode
uint32
,
ptr
unsafe
.
Pointer
)
string
{
func
replyString
(
opcode
Opcode
,
ptr
unsafe
.
Pointer
)
string
{
var
val
interface
{}
var
val
interface
{}
switch
opcode
{
switch
opcode
{
case
FUSE_LOOKUP
:
case
FUSE_LOOKUP
:
...
@@ -27,95 +28,257 @@ func replyString(opcode uint32, ptr unsafe.Pointer) string {
...
@@ -27,95 +28,257 @@ func replyString(opcode uint32, ptr unsafe.Pointer) string {
return
""
return
""
}
}
func
operationName
(
opcode
uint32
)
string
{
////////////////////////////////////////////////////////////////
switch
opcode
{
case
FUSE_LOOKUP
:
func
doOpen
(
state
*
MountState
,
req
*
request
)
{
return
"FUSE_LOOKUP"
flags
,
handle
,
status
:=
state
.
fileSystem
.
Open
(
req
.
inHeader
,
(
*
OpenIn
)(
req
.
inData
))
case
FUSE_FORGET
:
req
.
status
=
status
return
"FUSE_FORGET"
if
status
!=
OK
{
case
FUSE_GETATTR
:
return
return
"FUSE_GETATTR"
}
case
FUSE_SETATTR
:
return
"FUSE_SETATTR"
out
:=
&
OpenOut
{
case
FUSE_READLINK
:
Fh
:
handle
,
return
"FUSE_READLINK"
OpenFlags
:
flags
,
case
FUSE_SYMLINK
:
}
return
"FUSE_SYMLINK"
case
FUSE_MKNOD
:
req
.
data
=
unsafe
.
Pointer
(
out
)
return
"FUSE_MKNOD"
}
case
FUSE_MKDIR
:
return
"FUSE_MKDIR"
case
FUSE_UNLINK
:
func
doCreate
(
state
*
MountState
,
req
*
request
)
{
return
"FUSE_UNLINK"
flags
,
handle
,
entry
,
status
:=
state
.
fileSystem
.
Create
(
req
.
inHeader
,
(
*
CreateIn
)(
req
.
inData
),
req
.
filename
())
case
FUSE_RMDIR
:
req
.
status
=
status
return
"FUSE_RMDIR"
if
status
==
OK
{
case
FUSE_RENAME
:
req
.
data
=
unsafe
.
Pointer
(
&
CreateOut
{
return
"FUSE_RENAME"
EntryOut
:
*
entry
,
case
FUSE_LINK
:
OpenOut
:
OpenOut
{
return
"FUSE_LINK"
Fh
:
handle
,
case
FUSE_OPEN
:
OpenFlags
:
flags
,
return
"FUSE_OPEN"
},
case
FUSE_READ
:
})
return
"FUSE_READ"
}
case
FUSE_WRITE
:
}
return
"FUSE_WRITE"
case
FUSE_STATFS
:
return
"FUSE_STATFS"
func
doReadDir
(
state
*
MountState
,
req
*
request
)
{
case
FUSE_RELEASE
:
entries
,
code
:=
state
.
fileSystem
.
ReadDir
(
req
.
inHeader
,
(
*
ReadIn
)(
req
.
inData
))
return
"FUSE_RELEASE"
if
entries
!=
nil
{
case
FUSE_FSYNC
:
req
.
flatData
=
entries
.
Bytes
()
return
"FUSE_FSYNC"
}
case
FUSE_SETXATTR
:
req
.
status
=
code
return
"FUSE_SETXATTR"
}
case
FUSE_GETXATTR
:
return
"FUSE_GETXATTR"
case
FUSE_LISTXATTR
:
func
doOpenDir
(
state
*
MountState
,
req
*
request
)
{
return
"FUSE_LISTXATTR"
flags
,
handle
,
status
:=
state
.
fileSystem
.
OpenDir
(
req
.
inHeader
,
(
*
OpenIn
)(
req
.
inData
))
case
FUSE_REMOVEXATTR
:
req
.
status
=
status
return
"FUSE_REMOVEXATTR"
if
status
==
OK
{
case
FUSE_FLUSH
:
req
.
data
=
unsafe
.
Pointer
(
&
OpenOut
{
return
"FUSE_FLUSH"
Fh
:
handle
,
case
FUSE_INIT
:
OpenFlags
:
flags
,
return
"FUSE_INIT"
})
case
FUSE_OPENDIR
:
}
return
"FUSE_OPENDIR"
}
case
FUSE_READDIR
:
return
"FUSE_READDIR"
func
doSetattr
(
state
*
MountState
,
req
*
request
)
{
case
FUSE_RELEASEDIR
:
// TODO - if Fh != 0, we should do a FSetAttr instead.
return
"FUSE_RELEASEDIR"
o
,
s
:=
state
.
fileSystem
.
SetAttr
(
req
.
inHeader
,
(
*
SetAttrIn
)(
req
.
inData
))
case
FUSE_FSYNCDIR
:
req
.
data
=
unsafe
.
Pointer
(
o
)
return
"FUSE_FSYNCDIR"
req
.
status
=
s
case
FUSE_GETLK
:
}
return
"FUSE_GETLK"
case
FUSE_SETLK
:
func
doWrite
(
state
*
MountState
,
req
*
request
)
{
return
"FUSE_SETLK"
n
,
status
:=
state
.
fileSystem
.
Write
((
*
WriteIn
)(
req
.
inData
),
req
.
arg
)
case
FUSE_SETLKW
:
o
:=
&
WriteOut
{
return
"FUSE_SETLKW"
Size
:
n
,
case
FUSE_ACCESS
:
}
return
"FUSE_ACCESS"
req
.
data
=
unsafe
.
Pointer
(
o
)
case
FUSE_CREATE
:
req
.
status
=
status
return
"FUSE_CREATE"
}
case
FUSE_INTERRUPT
:
return
"FUSE_INTERRUPT"
case
FUSE_BMAP
:
func
doGetXAttr
(
state
*
MountState
,
req
*
request
)
{
return
"FUSE_BMAP"
input
:=
(
*
GetXAttrIn
)(
req
.
inData
)
case
FUSE_DESTROY
:
var
data
[]
byte
return
"FUSE_DESTROY"
if
req
.
inHeader
.
Opcode
==
FUSE_GETXATTR
{
case
FUSE_IOCTL
:
data
,
req
.
status
=
state
.
fileSystem
.
GetXAttr
(
req
.
inHeader
,
req
.
filename
())
return
"FUSE_IOCTL"
}
else
{
case
FUSE_POLL
:
data
,
req
.
status
=
state
.
fileSystem
.
ListXAttr
(
req
.
inHeader
)
return
"FUSE_POLL"
}
}
return
"UNKNOWN"
if
req
.
status
!=
OK
{
}
return
}
size
:=
uint32
(
len
(
data
))
var
inputSizeMap
map
[
int
]
int
if
input
.
Size
==
0
{
var
outputSizeMap
map
[
int
]
int
out
:=
&
GetXAttrOut
{
Size
:
size
,
}
req
.
data
=
unsafe
.
Pointer
(
out
)
}
if
size
>
input
.
Size
{
req
.
status
=
ERANGE
}
req
.
flatData
=
data
}
func
doGetAttr
(
state
*
MountState
,
req
*
request
)
{
// TODO - if req.inData.Fh is set, do file.GetAttr
attrOut
,
s
:=
state
.
fileSystem
.
GetAttr
(
req
.
inHeader
,
(
*
GetAttrIn
)(
req
.
inData
))
req
.
status
=
s
req
.
data
=
unsafe
.
Pointer
(
attrOut
)
}
func
doForget
(
state
*
MountState
,
req
*
request
)
{
state
.
fileSystem
.
Forget
(
req
.
inHeader
,
(
*
ForgetIn
)(
req
.
inData
))
}
func
doReadlink
(
state
*
MountState
,
req
*
request
)
{
req
.
flatData
,
req
.
status
=
state
.
fileSystem
.
Readlink
(
req
.
inHeader
)
}
func
doInit
(
state
*
MountState
,
req
*
request
)
{
req
.
data
,
req
.
status
=
state
.
init
(
req
.
inHeader
,
(
*
InitIn
)(
req
.
inData
))
}
func
doDestroy
(
state
*
MountState
,
req
*
request
)
{
state
.
fileSystem
.
Destroy
(
req
.
inHeader
,
(
*
InitIn
)(
req
.
inData
))
}
func
doLookup
(
state
*
MountState
,
req
*
request
)
{
lookupOut
,
s
:=
state
.
fileSystem
.
Lookup
(
req
.
inHeader
,
req
.
filename
())
req
.
status
=
s
req
.
data
=
unsafe
.
Pointer
(
lookupOut
)
}
func
doMknod
(
state
*
MountState
,
req
*
request
)
{
entryOut
,
s
:=
state
.
fileSystem
.
Mknod
(
req
.
inHeader
,
(
*
MknodIn
)(
req
.
inData
),
req
.
filename
())
req
.
status
=
s
req
.
data
=
unsafe
.
Pointer
(
entryOut
)
}
func
doMkdir
(
state
*
MountState
,
req
*
request
)
{
entryOut
,
s
:=
state
.
fileSystem
.
Mkdir
(
req
.
inHeader
,
(
*
MkdirIn
)(
req
.
inData
),
req
.
filename
())
req
.
status
=
s
req
.
data
=
unsafe
.
Pointer
(
entryOut
)
}
func
doUnlink
(
state
*
MountState
,
req
*
request
)
{
req
.
status
=
state
.
fileSystem
.
Unlink
(
req
.
inHeader
,
req
.
filename
())
}
func
doRmdir
(
state
*
MountState
,
req
*
request
)
{
req
.
status
=
state
.
fileSystem
.
Rmdir
(
req
.
inHeader
,
req
.
filename
())
}
func
doLink
(
state
*
MountState
,
req
*
request
)
{
entryOut
,
s
:=
state
.
fileSystem
.
Link
(
req
.
inHeader
,
(
*
LinkIn
)(
req
.
inData
),
req
.
filename
())
req
.
status
=
s
req
.
data
=
unsafe
.
Pointer
(
entryOut
)
}
func
doRead
(
state
*
MountState
,
req
*
request
)
{
req
.
flatData
,
req
.
status
=
state
.
fileSystem
.
Read
((
*
ReadIn
)(
req
.
inData
),
state
.
buffers
)
}
func
doFlush
(
state
*
MountState
,
req
*
request
)
{
req
.
status
=
state
.
fileSystem
.
Flush
((
*
FlushIn
)(
req
.
inData
))
}
func
doRelease
(
state
*
MountState
,
req
*
request
)
{
state
.
fileSystem
.
Release
(
req
.
inHeader
,
(
*
ReleaseIn
)(
req
.
inData
))
}
func
doFsync
(
state
*
MountState
,
req
*
request
)
{
req
.
status
=
state
.
fileSystem
.
Fsync
((
*
FsyncIn
)(
req
.
inData
))
}
func
doReleaseDir
(
state
*
MountState
,
req
*
request
)
{
state
.
fileSystem
.
ReleaseDir
(
req
.
inHeader
,
(
*
ReleaseIn
)(
req
.
inData
))
}
func
doFsyncDir
(
state
*
MountState
,
req
*
request
)
{
req
.
status
=
state
.
fileSystem
.
FsyncDir
(
req
.
inHeader
,
(
*
FsyncIn
)(
req
.
inData
))
}
func
doSetXAttr
(
state
*
MountState
,
req
*
request
)
{
splits
:=
bytes
.
Split
(
req
.
arg
,
[]
byte
{
0
},
2
)
req
.
status
=
state
.
fileSystem
.
SetXAttr
(
req
.
inHeader
,
(
*
SetXAttrIn
)(
req
.
inData
),
string
(
splits
[
0
]),
splits
[
1
])
}
func
doRemoveXAttr
(
state
*
MountState
,
req
*
request
)
{
req
.
status
=
state
.
fileSystem
.
RemoveXAttr
(
req
.
inHeader
,
req
.
filename
())
}
func
doAccess
(
state
*
MountState
,
req
*
request
)
{
req
.
status
=
state
.
fileSystem
.
Access
(
req
.
inHeader
,
(
*
AccessIn
)(
req
.
inData
))
}
func
doSymlink
(
state
*
MountState
,
req
*
request
)
{
filenames
:=
req
.
filenames
(
3
)
if
len
(
filenames
)
>=
2
{
entryOut
,
s
:=
state
.
fileSystem
.
Symlink
(
req
.
inHeader
,
filenames
[
1
],
filenames
[
0
])
req
.
status
=
s
req
.
data
=
unsafe
.
Pointer
(
entryOut
)
}
else
{
req
.
status
=
EIO
}
}
func
doRename
(
state
*
MountState
,
req
*
request
)
{
filenames
:=
req
.
filenames
(
3
)
if
len
(
filenames
)
>=
2
{
req
.
status
=
state
.
fileSystem
.
Rename
(
req
.
inHeader
,
(
*
RenameIn
)(
req
.
inData
),
filenames
[
0
],
filenames
[
1
])
}
else
{
req
.
status
=
EIO
}
}
////////////////////////////////////////////////////////////////
var
operationNames
[]
string
var
inputSizes
[]
int
var
outputSizes
[]
int
type
operation
func
(
*
MountState
,
*
request
)
var
operationFuncs
[]
operation
func
operationName
(
opcode
Opcode
)
string
{
if
opcode
>
OPCODE_COUNT
{
return
"unknown"
}
return
operationNames
[
opcode
]
}
func
inputSize
(
o
Opcode
)
(
int
,
bool
)
{
return
lookupSize
(
o
,
inputSizes
)
}
func
outputSize
(
o
Opcode
)
(
int
,
bool
)
{
return
lookupSize
(
o
,
outputSizes
)
}
func
lookupSize
(
o
Opcode
,
sMap
[]
int
)
(
int
,
bool
)
{
if
o
>=
OPCODE_COUNT
{
return
-
1
,
false
}
return
sMap
[
int
(
o
)],
true
}
func
lookupOperation
(
o
Opcode
)
operation
{
return
operationFuncs
[
o
]
}
func
makeSizes
(
dict
map
[
int
]
int
)
[]
int
{
out
:=
make
([]
int
,
OPCODE_COUNT
)
for
i
,
_
:=
range
out
{
out
[
i
]
=
-
1
}
for
code
,
val
:=
range
dict
{
out
[
code
]
=
val
}
return
out
}
func
init
()
{
func
init
()
{
inputSize
Map
=
map
[
int
]
int
{
inputSize
s
=
makeSizes
(
map
[
int
]
int
{
FUSE_LOOKUP
:
0
,
FUSE_LOOKUP
:
0
,
FUSE_FORGET
:
unsafe
.
Sizeof
(
ForgetIn
{}),
FUSE_FORGET
:
unsafe
.
Sizeof
(
ForgetIn
{}),
FUSE_GETATTR
:
unsafe
.
Sizeof
(
GetAttrIn
{}),
FUSE_GETATTR
:
unsafe
.
Sizeof
(
GetAttrIn
{}),
...
@@ -154,9 +317,9 @@ func init() {
...
@@ -154,9 +317,9 @@ func init() {
FUSE_DESTROY
:
0
,
FUSE_DESTROY
:
0
,
FUSE_IOCTL
:
unsafe
.
Sizeof
(
IoctlIn
{}),
FUSE_IOCTL
:
unsafe
.
Sizeof
(
IoctlIn
{}),
FUSE_POLL
:
unsafe
.
Sizeof
(
PollIn
{}),
FUSE_POLL
:
unsafe
.
Sizeof
(
PollIn
{}),
}
}
)
outputSize
Map
=
map
[
int
]
int
{
outputSize
s
=
makeSizes
(
map
[
int
]
int
{
FUSE_LOOKUP
:
unsafe
.
Sizeof
(
EntryOut
{}),
FUSE_LOOKUP
:
unsafe
.
Sizeof
(
EntryOut
{}),
FUSE_FORGET
:
0
,
FUSE_FORGET
:
0
,
FUSE_GETATTR
:
unsafe
.
Sizeof
(
AttrOut
{}),
FUSE_GETATTR
:
unsafe
.
Sizeof
(
AttrOut
{}),
...
@@ -196,5 +359,84 @@ func init() {
...
@@ -196,5 +359,84 @@ func init() {
FUSE_DESTROY
:
0
,
FUSE_DESTROY
:
0
,
FUSE_IOCTL
:
unsafe
.
Sizeof
(
IoctlOut
{}),
FUSE_IOCTL
:
unsafe
.
Sizeof
(
IoctlOut
{}),
FUSE_POLL
:
unsafe
.
Sizeof
(
PollOut
{}),
FUSE_POLL
:
unsafe
.
Sizeof
(
PollOut
{}),
})
operationNames
=
make
([]
string
,
OPCODE_COUNT
)
for
k
,
v
:=
range
map
[
int
]
string
{
FUSE_LOOKUP
:
"FUSE_LOOKUP"
,
FUSE_FORGET
:
"FUSE_FORGET"
,
FUSE_GETATTR
:
"FUSE_GETATTR"
,
FUSE_SETATTR
:
"FUSE_SETATTR"
,
FUSE_READLINK
:
"FUSE_READLINK"
,
FUSE_SYMLINK
:
"FUSE_SYMLINK"
,
FUSE_MKNOD
:
"FUSE_MKNOD"
,
FUSE_MKDIR
:
"FUSE_MKDIR"
,
FUSE_UNLINK
:
"FUSE_UNLINK"
,
FUSE_RMDIR
:
"FUSE_RMDIR"
,
FUSE_RENAME
:
"FUSE_RENAME"
,
FUSE_LINK
:
"FUSE_LINK"
,
FUSE_OPEN
:
"FUSE_OPEN"
,
FUSE_READ
:
"FUSE_READ"
,
FUSE_WRITE
:
"FUSE_WRITE"
,
FUSE_STATFS
:
"FUSE_STATFS"
,
FUSE_RELEASE
:
"FUSE_RELEASE"
,
FUSE_FSYNC
:
"FUSE_FSYNC"
,
FUSE_SETXATTR
:
"FUSE_SETXATTR"
,
FUSE_GETXATTR
:
"FUSE_GETXATTR"
,
FUSE_LISTXATTR
:
"FUSE_LISTXATTR"
,
FUSE_REMOVEXATTR
:
"FUSE_REMOVEXATTR"
,
FUSE_FLUSH
:
"FUSE_FLUSH"
,
FUSE_INIT
:
"FUSE_INIT"
,
FUSE_OPENDIR
:
"FUSE_OPENDIR"
,
FUSE_READDIR
:
"FUSE_READDIR"
,
FUSE_RELEASEDIR
:
"FUSE_RELEASEDIR"
,
FUSE_FSYNCDIR
:
"FUSE_FSYNCDIR"
,
FUSE_GETLK
:
"FUSE_GETLK"
,
FUSE_SETLK
:
"FUSE_SETLK"
,
FUSE_SETLKW
:
"FUSE_SETLKW"
,
FUSE_ACCESS
:
"FUSE_ACCESS"
,
FUSE_CREATE
:
"FUSE_CREATE"
,
FUSE_INTERRUPT
:
"FUSE_INTERRUPT"
,
FUSE_BMAP
:
"FUSE_BMAP"
,
FUSE_DESTROY
:
"FUSE_DESTROY"
,
FUSE_IOCTL
:
"FUSE_IOCTL"
,
FUSE_POLL
:
"FUSE_POLL"
}
{
operationNames
[
k
]
=
v
}
operationFuncs
=
make
([]
operation
,
OPCODE_COUNT
)
for
k
,
v
:=
range
map
[
Opcode
]
operation
{
FUSE_OPEN
:
doOpen
,
FUSE_READDIR
:
doReadDir
,
FUSE_WRITE
:
doWrite
,
FUSE_OPENDIR
:
doOpenDir
,
FUSE_CREATE
:
doCreate
,
FUSE_SETATTR
:
doSetattr
,
FUSE_GETXATTR
:
doGetXAttr
,
FUSE_LISTXATTR
:
doGetXAttr
,
FUSE_GETATTR
:
doGetAttr
,
FUSE_FORGET
:
doForget
,
FUSE_READLINK
:
doReadlink
,
FUSE_INIT
:
doInit
,
FUSE_DESTROY
:
doDestroy
,
FUSE_LOOKUP
:
doLookup
,
FUSE_MKNOD
:
doMknod
,
FUSE_MKDIR
:
doMkdir
,
FUSE_UNLINK
:
doUnlink
,
FUSE_RMDIR
:
doRmdir
,
FUSE_LINK
:
doLink
,
FUSE_READ
:
doRead
,
FUSE_FLUSH
:
doFlush
,
FUSE_RELEASE
:
doRelease
,
FUSE_FSYNC
:
doFsync
,
FUSE_RELEASEDIR
:
doReleaseDir
,
FUSE_FSYNCDIR
:
doFsyncDir
,
FUSE_SETXATTR
:
doSetXAttr
,
FUSE_REMOVEXATTR
:
doRemoveXAttr
,
FUSE_ACCESS
:
doAccess
,
FUSE_SYMLINK
:
doSymlink
,
FUSE_RENAME
:
doRename
,
}
{
operationFuncs
[
k
]
=
v
}
}
}
}
fuse/pathdebug.go
View file @
c254e3ec
package
fuse
package
fuse
import
(
import
(
"fmt"
"fmt"
)
)
...
@@ -12,7 +13,7 @@ type FileSystemDebug struct {
...
@@ -12,7 +13,7 @@ type FileSystemDebug struct {
WrappingFileSystem
WrappingFileSystem
}
}
func
(
me
*
FileSystemDebug
)
Open
(
path
string
,
flags
uint32
)
(
fuseFile
File
,
status
Status
)
{
func
(
me
*
FileSystemDebug
)
Open
(
path
string
,
flags
uint32
)
(
fuseFile
File
,
status
Status
)
{
if
path
==
".debug"
&&
me
.
Connector
!=
nil
{
if
path
==
".debug"
&&
me
.
Connector
!=
nil
{
return
NewReadOnlyFile
([]
byte
(
me
.
Connector
.
DebugString
())),
OK
return
NewReadOnlyFile
([]
byte
(
me
.
Connector
.
DebugString
())),
OK
}
}
...
@@ -24,8 +25,7 @@ func (me *FileSystemDebug) GetAttr(path string) (*Attr, Status) {
...
@@ -24,8 +25,7 @@ func (me *FileSystemDebug) GetAttr(path string) (*Attr, Status) {
return
&
Attr
{
return
&
Attr
{
Mode
:
S_IFREG
,
Mode
:
S_IFREG
,
Size
:
uint64
(
len
(
me
.
Connector
.
DebugString
())),
Size
:
uint64
(
len
(
me
.
Connector
.
DebugString
())),
},
OK
},
OK
}
}
return
me
.
Original
.
GetAttr
(
path
)
return
me
.
Original
.
GetAttr
(
path
)
}
}
fuse/pathfilesystem.go
View file @
c254e3ec
...
@@ -169,7 +169,7 @@ type FileSystemConnector struct {
...
@@ -169,7 +169,7 @@ type FileSystemConnector struct {
func
(
me
*
FileSystemConnector
)
DebugString
()
string
{
func
(
me
*
FileSystemConnector
)
DebugString
()
string
{
me
.
lock
.
RLock
()
me
.
lock
.
RLock
()
defer
me
.
lock
.
RUnlock
()
defer
me
.
lock
.
RUnlock
()
me
.
fileLock
.
RLock
()
me
.
fileLock
.
RLock
()
defer
me
.
fileLock
.
RUnlock
()
defer
me
.
fileLock
.
RUnlock
()
...
@@ -237,14 +237,14 @@ func (me *FileSystemConnector) verify() {
...
@@ -237,14 +237,14 @@ func (me *FileSystemConnector) verify() {
hiddenOpen
+=
v
.
OpenCount
hiddenOpen
+=
v
.
OpenCount
}
}
}
}
root
:=
me
.
inodeMap
[
FUSE_ROOT_ID
]
root
:=
me
.
inodeMap
[
FUSE_ROOT_ID
]
root
.
verify
()
root
.
verify
()
open
:=
root
.
totalOpenCount
()
open
:=
root
.
totalOpenCount
()
openFiles
:=
len
(
me
.
openFiles
)
openFiles
:=
len
(
me
.
openFiles
)
mounted
:=
root
.
totalMountCount
()
mounted
:=
root
.
totalMountCount
()
if
open
+
hiddenOpen
!=
openFiles
+
mounted
{
if
open
+
hiddenOpen
!=
openFiles
+
mounted
{
panic
(
fmt
.
Sprintf
(
"opencount mismatch totalOpen=%v openFiles=%v mounted=%v hidden=%v"
,
open
,
openFiles
,
mounted
,
hiddenOpen
))
panic
(
fmt
.
Sprintf
(
"opencount mismatch totalOpen=%v openFiles=%v mounted=%v hidden=%v"
,
open
,
openFiles
,
mounted
,
hiddenOpen
))
}
}
}
}
...
@@ -306,10 +306,10 @@ func (me *FileSystemConnector) considerDropInode(n *inode) {
...
@@ -306,10 +306,10 @@ func (me *FileSystemConnector) considerDropInode(n *inode) {
n
.
mount
.
mutex
.
RLock
()
n
.
mount
.
mutex
.
RLock
()
defer
n
.
mount
.
mutex
.
RUnlock
()
defer
n
.
mount
.
mutex
.
RUnlock
()
}
}
// TODO - this should probably not happen at all.
// TODO - this should probably not happen at all.
if
(
n
.
LookupCount
<=
0
&&
len
(
n
.
Children
)
==
0
&&
(
n
.
mount
==
nil
||
n
.
mount
.
unmountPending
)
&&
if
n
.
LookupCount
<=
0
&&
len
(
n
.
Children
)
==
0
&&
(
n
.
mount
==
nil
||
n
.
mount
.
unmountPending
)
&&
n
.
OpenCount
<=
0
)
{
n
.
OpenCount
<=
0
{
n
.
setParent
(
nil
)
n
.
setParent
(
nil
)
me
.
inodeMap
[
n
.
NodeId
]
=
nil
,
false
me
.
inodeMap
[
n
.
NodeId
]
=
nil
,
false
}
}
...
@@ -328,7 +328,7 @@ func (me *FileSystemConnector) renameUpdate(oldParent *inode, oldName string, ne
...
@@ -328,7 +328,7 @@ func (me *FileSystemConnector) renameUpdate(oldParent *inode, oldName string, ne
dest
:=
newParent
.
Children
[
newName
]
dest
:=
newParent
.
Children
[
newName
]
if
dest
!=
nil
{
if
dest
!=
nil
{
dest
.
setParent
(
nil
)
dest
.
setParent
(
nil
)
}
}
node
.
setParent
(
nil
)
node
.
setParent
(
nil
)
node
.
Name
=
newName
node
.
Name
=
newName
node
.
setParent
(
newParent
)
node
.
setParent
(
newParent
)
...
@@ -384,7 +384,7 @@ func EmptyFileSystemConnector() (out *FileSystemConnector) {
...
@@ -384,7 +384,7 @@ func EmptyFileSystemConnector() (out *FileSystemConnector) {
out
.
options
.
AttrTimeout
=
1.0
out
.
options
.
AttrTimeout
=
1.0
out
.
options
.
EntryTimeout
=
1.0
out
.
options
.
EntryTimeout
=
1.0
out
.
verify
()
out
.
verify
()
return
out
;
return
out
}
}
func
NewFileSystemConnector
(
fs
FileSystem
)
(
out
*
FileSystemConnector
)
{
func
NewFileSystemConnector
(
fs
FileSystem
)
(
out
*
FileSystemConnector
)
{
...
...
fuse/timingrawfs.go
View file @
c254e3ec
...
@@ -151,21 +151,6 @@ func (me *TimingRawFileSystem) Create(header *InHeader, input *CreateIn, name st
...
@@ -151,21 +151,6 @@ func (me *TimingRawFileSystem) Create(header *InHeader, input *CreateIn, name st
return
me
.
Original
.
Create
(
header
,
input
,
name
)
return
me
.
Original
.
Create
(
header
,
input
,
name
)
}
}
func
(
me
*
TimingRawFileSystem
)
Bmap
(
header
*
InHeader
,
input
*
BmapIn
)
(
out
*
BmapOut
,
code
Status
)
{
defer
me
.
startTimer
(
"Bmap"
)()
return
me
.
Original
.
Bmap
(
header
,
input
)
}
func
(
me
*
TimingRawFileSystem
)
Ioctl
(
header
*
InHeader
,
input
*
IoctlIn
)
(
out
*
IoctlOut
,
code
Status
)
{
defer
me
.
startTimer
(
"Ioctl"
)()
return
me
.
Original
.
Ioctl
(
header
,
input
)
}
func
(
me
*
TimingRawFileSystem
)
Poll
(
header
*
InHeader
,
input
*
PollIn
)
(
out
*
PollOut
,
code
Status
)
{
defer
me
.
startTimer
(
"Poll"
)()
return
me
.
Original
.
Poll
(
header
,
input
)
}
func
(
me
*
TimingRawFileSystem
)
OpenDir
(
header
*
InHeader
,
input
*
OpenIn
)
(
flags
uint32
,
handle
uint64
,
status
Status
)
{
func
(
me
*
TimingRawFileSystem
)
OpenDir
(
header
*
InHeader
,
input
*
OpenIn
)
(
flags
uint32
,
handle
uint64
,
status
Status
)
{
defer
me
.
startTimer
(
"OpenDir"
)()
defer
me
.
startTimer
(
"OpenDir"
)()
return
me
.
Original
.
OpenDir
(
header
,
input
)
return
me
.
Original
.
OpenDir
(
header
,
input
)
...
...
fuse/types.go
View file @
c254e3ec
...
@@ -143,6 +143,8 @@ const (
...
@@ -143,6 +143,8 @@ const (
FUSE_IOCTL
=
39
FUSE_IOCTL
=
39
FUSE_POLL
=
40
FUSE_POLL
=
40
OPCODE_COUNT
=
41
CUSE_INIT
=
4096
CUSE_INIT
=
4096
)
)
...
@@ -287,8 +289,8 @@ type OpenOut struct {
...
@@ -287,8 +289,8 @@ type OpenOut struct {
}
}
type
CreateOut
struct
{
type
CreateOut
struct
{
Entry
Entry
Out
EntryOut
Open
Open
Out
OpenOut
}
}
type
ReleaseIn
struct
{
type
ReleaseIn
struct
{
...
@@ -456,7 +458,7 @@ type NotifyPollWakeupOut struct {
...
@@ -456,7 +458,7 @@ type NotifyPollWakeupOut struct {
type
InHeader
struct
{
type
InHeader
struct
{
Length
uint32
Length
uint32
Opcode
uint32
Opcode
Unique
uint64
Unique
uint64
NodeId
uint64
NodeId
uint64
Identity
Identity
...
@@ -528,9 +530,13 @@ type RawFileSystem interface {
...
@@ -528,9 +530,13 @@ type RawFileSystem interface {
RemoveXAttr
(
header
*
InHeader
,
attr
string
)
(
code
Status
)
RemoveXAttr
(
header
*
InHeader
,
attr
string
)
(
code
Status
)
Access
(
header
*
InHeader
,
input
*
AccessIn
)
(
code
Status
)
Access
(
header
*
InHeader
,
input
*
AccessIn
)
(
code
Status
)
Create
(
header
*
InHeader
,
input
*
CreateIn
,
name
string
)
(
flags
uint32
,
handle
uint64
,
out
*
EntryOut
,
code
Status
)
Create
(
header
*
InHeader
,
input
*
CreateIn
,
name
string
)
(
flags
uint32
,
handle
uint64
,
out
*
EntryOut
,
code
Status
)
Bmap
(
header
*
InHeader
,
input
*
BmapIn
)
(
out
*
BmapOut
,
code
Status
)
Ioctl
(
header
*
InHeader
,
input
*
IoctlIn
)
(
out
*
IoctlOut
,
code
Status
)
/*
Poll
(
header
*
InHeader
,
input
*
PollIn
)
(
out
*
PollOut
,
code
Status
)
// unimplemented.
Bmap(header *InHeader, input *BmapIn) (out *BmapOut, code Status)
Ioctl(header *InHeader, input *IoctlIn) (out *IoctlOut, code Status)
Poll(header *InHeader, input *PollIn) (out *PollOut, code Status)
*/
// File handling.
// File handling.
Open
(
header
*
InHeader
,
input
*
OpenIn
)
(
flags
uint32
,
handle
uint64
,
status
Status
)
Open
(
header
*
InHeader
,
input
*
OpenIn
)
(
flags
uint32
,
handle
uint64
,
status
Status
)
...
...
fuse/wrappedfs.go
View file @
c254e3ec
...
@@ -189,18 +189,6 @@ func (me *WrappingRawFileSystem) Create(header *InHeader, input *CreateIn, name
...
@@ -189,18 +189,6 @@ func (me *WrappingRawFileSystem) Create(header *InHeader, input *CreateIn, name
return
me
.
Original
.
Create
(
header
,
input
,
name
)
return
me
.
Original
.
Create
(
header
,
input
,
name
)
}
}
func
(
me
*
WrappingRawFileSystem
)
Bmap
(
header
*
InHeader
,
input
*
BmapIn
)
(
out
*
BmapOut
,
code
Status
)
{
return
me
.
Original
.
Bmap
(
header
,
input
)
}
func
(
me
*
WrappingRawFileSystem
)
Ioctl
(
header
*
InHeader
,
input
*
IoctlIn
)
(
out
*
IoctlOut
,
code
Status
)
{
return
me
.
Original
.
Ioctl
(
header
,
input
)
}
func
(
me
*
WrappingRawFileSystem
)
Poll
(
header
*
InHeader
,
input
*
PollIn
)
(
out
*
PollOut
,
code
Status
)
{
return
me
.
Original
.
Poll
(
header
,
input
)
}
func
(
me
*
WrappingRawFileSystem
)
OpenDir
(
header
*
InHeader
,
input
*
OpenIn
)
(
flags
uint32
,
handle
uint64
,
status
Status
)
{
func
(
me
*
WrappingRawFileSystem
)
OpenDir
(
header
*
InHeader
,
input
*
OpenIn
)
(
flags
uint32
,
handle
uint64
,
status
Status
)
{
return
me
.
Original
.
OpenDir
(
header
,
input
)
return
me
.
Original
.
OpenDir
(
header
,
input
)
}
}
...
...
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