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
ce603372
Commit
ce603372
authored
May 02, 2012
by
Han-Wen Nienhuys
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Use go style receiver names.
parent
30e96b91
Changes
29
Show whitespace changes
Inline
Side-by-side
Showing
29 changed files
with
1385 additions
and
1385 deletions
+1385
-1385
fuse/attr.go
fuse/attr.go
+14
-14
fuse/bufferpool.go
fuse/bufferpool.go
+28
-28
fuse/cache_test.go
fuse/cache_test.go
+5
-5
fuse/default.go
fuse/default.go
+25
-25
fuse/defaultfile.go
fuse/defaultfile.go
+14
-14
fuse/defaultnode.go
fuse/defaultnode.go
+37
-37
fuse/defaultraw.go
fuse/defaultraw.go
+34
-34
fuse/direntry.go
fuse/direntry.go
+33
-33
fuse/files.go
fuse/files.go
+41
-41
fuse/fsconnector.go
fuse/fsconnector.go
+54
-54
fuse/fsetattr_test.go
fuse/fsetattr_test.go
+36
-36
fuse/fsmount.go
fuse/fsmount.go
+23
-23
fuse/fsops.go
fuse/fsops.go
+76
-76
fuse/handle.go
fuse/handle.go
+70
-70
fuse/inode.go
fuse/inode.go
+72
-72
fuse/latencymap.go
fuse/latencymap.go
+26
-26
fuse/lockingfs.go
fuse/lockingfs.go
+161
-161
fuse/loopback.go
fuse/loopback.go
+46
-46
fuse/loopback_test.go
fuse/loopback_test.go
+91
-91
fuse/memnode.go
fuse/memnode.go
+73
-73
fuse/mountstate.go
fuse/mountstate.go
+62
-62
fuse/notify_test.go
fuse/notify_test.go
+7
-7
fuse/owner_test.go
fuse/owner_test.go
+1
-1
fuse/pathfs.go
fuse/pathfs.go
+195
-195
fuse/prefixfs.go
fuse/prefixfs.go
+50
-50
fuse/readonlyfs.go
fuse/readonlyfs.go
+34
-34
fuse/request.go
fuse/request.go
+53
-53
fuse/typeprint.go
fuse/typeprint.go
+6
-6
fuse/xattr_test.go
fuse/xattr_test.go
+18
-18
No files found.
fuse/attr.go
View file @
ce603372
...
...
@@ -31,45 +31,45 @@ func (me FileMode) String() string {
return
"0"
}
func
(
m
e
FileMode
)
IsFifo
()
bool
{
return
(
uint32
(
me
)
&
syscall
.
S_IFMT
)
==
syscall
.
S_IFIFO
}
func
(
m
FileMode
)
IsFifo
()
bool
{
return
(
uint32
(
m
)
&
syscall
.
S_IFMT
)
==
syscall
.
S_IFIFO
}
// IsChar reports whether the FileInfo describes a character special file.
func
(
m
e
FileMode
)
IsChar
()
bool
{
return
(
uint32
(
me
)
&
syscall
.
S_IFMT
)
==
syscall
.
S_IFCHR
}
func
(
m
FileMode
)
IsChar
()
bool
{
return
(
uint32
(
m
)
&
syscall
.
S_IFMT
)
==
syscall
.
S_IFCHR
}
// IsDir reports whether the FileInfo describes a directory.
func
(
m
e
FileMode
)
IsDir
()
bool
{
return
(
uint32
(
me
)
&
syscall
.
S_IFMT
)
==
syscall
.
S_IFDIR
}
func
(
m
FileMode
)
IsDir
()
bool
{
return
(
uint32
(
m
)
&
syscall
.
S_IFMT
)
==
syscall
.
S_IFDIR
}
// IsBlock reports whether the FileInfo describes a block special file.
func
(
m
e
FileMode
)
IsBlock
()
bool
{
return
(
uint32
(
me
)
&
syscall
.
S_IFMT
)
==
syscall
.
S_IFBLK
}
func
(
m
FileMode
)
IsBlock
()
bool
{
return
(
uint32
(
m
)
&
syscall
.
S_IFMT
)
==
syscall
.
S_IFBLK
}
// IsRegular reports whether the FileInfo describes a regular file.
func
(
m
e
FileMode
)
IsRegular
()
bool
{
return
(
uint32
(
me
)
&
syscall
.
S_IFMT
)
==
syscall
.
S_IFREG
}
func
(
m
FileMode
)
IsRegular
()
bool
{
return
(
uint32
(
m
)
&
syscall
.
S_IFMT
)
==
syscall
.
S_IFREG
}
// IsSymlink reports whether the FileInfo describes a symbolic link.
func
(
m
e
FileMode
)
IsSymlink
()
bool
{
return
(
uint32
(
me
)
&
syscall
.
S_IFMT
)
==
syscall
.
S_IFLNK
}
func
(
m
FileMode
)
IsSymlink
()
bool
{
return
(
uint32
(
m
)
&
syscall
.
S_IFMT
)
==
syscall
.
S_IFLNK
}
// IsSocket reports whether the FileInfo describes a socket.
func
(
m
e
FileMode
)
IsSocket
()
bool
{
return
(
uint32
(
me
)
&
syscall
.
S_IFMT
)
==
syscall
.
S_IFSOCK
}
func
(
m
FileMode
)
IsSocket
()
bool
{
return
(
uint32
(
m
)
&
syscall
.
S_IFMT
)
==
syscall
.
S_IFSOCK
}
func
(
me
*
Attr
)
IsFifo
()
bool
{
return
(
uint32
(
me
.
Mode
)
&
syscall
.
S_IFMT
)
==
syscall
.
S_IFIFO
}
func
(
a
*
Attr
)
IsFifo
()
bool
{
return
(
uint32
(
a
.
Mode
)
&
syscall
.
S_IFMT
)
==
syscall
.
S_IFIFO
}
// IsChar reports whether the FileInfo describes a character special file.
func
(
me
*
Attr
)
IsChar
()
bool
{
return
(
uint32
(
me
.
Mode
)
&
syscall
.
S_IFMT
)
==
syscall
.
S_IFCHR
}
func
(
a
*
Attr
)
IsChar
()
bool
{
return
(
uint32
(
a
.
Mode
)
&
syscall
.
S_IFMT
)
==
syscall
.
S_IFCHR
}
// IsDir reports whether the FileInfo describes a directory.
func
(
me
*
Attr
)
IsDir
()
bool
{
return
(
uint32
(
me
.
Mode
)
&
syscall
.
S_IFMT
)
==
syscall
.
S_IFDIR
}
func
(
a
*
Attr
)
IsDir
()
bool
{
return
(
uint32
(
a
.
Mode
)
&
syscall
.
S_IFMT
)
==
syscall
.
S_IFDIR
}
// IsBlock reports whether the FileInfo describes a block special file.
func
(
me
*
Attr
)
IsBlock
()
bool
{
return
(
uint32
(
me
.
Mode
)
&
syscall
.
S_IFMT
)
==
syscall
.
S_IFBLK
}
func
(
a
*
Attr
)
IsBlock
()
bool
{
return
(
uint32
(
a
.
Mode
)
&
syscall
.
S_IFMT
)
==
syscall
.
S_IFBLK
}
// IsRegular reports whether the FileInfo describes a regular file.
func
(
me
*
Attr
)
IsRegular
()
bool
{
return
(
uint32
(
me
.
Mode
)
&
syscall
.
S_IFMT
)
==
syscall
.
S_IFREG
}
func
(
a
*
Attr
)
IsRegular
()
bool
{
return
(
uint32
(
a
.
Mode
)
&
syscall
.
S_IFMT
)
==
syscall
.
S_IFREG
}
// IsSymlink reports whether the FileInfo describes a symbolic link.
func
(
me
*
Attr
)
IsSymlink
()
bool
{
return
(
uint32
(
me
.
Mode
)
&
syscall
.
S_IFMT
)
==
syscall
.
S_IFLNK
}
func
(
a
*
Attr
)
IsSymlink
()
bool
{
return
(
uint32
(
a
.
Mode
)
&
syscall
.
S_IFMT
)
==
syscall
.
S_IFLNK
}
// IsSocket reports whether the FileInfo describes a socket.
func
(
me
*
Attr
)
IsSocket
()
bool
{
return
(
uint32
(
me
.
Mode
)
&
syscall
.
S_IFMT
)
==
syscall
.
S_IFSOCK
}
func
(
a
*
Attr
)
IsSocket
()
bool
{
return
(
uint32
(
a
.
Mode
)
&
syscall
.
S_IFMT
)
==
syscall
.
S_IFSOCK
}
func
(
a
*
Attr
)
Atimens
()
int64
{
return
int64
(
1e9
*
a
.
Atime
)
+
int64
(
a
.
Atimensec
)
...
...
fuse/bufferpool.go
View file @
ce603372
...
...
@@ -24,11 +24,11 @@ func NewGcBufferPool() *GcBufferPool {
return
&
GcBufferPool
{}
}
func
(
me
*
GcBufferPool
)
AllocBuffer
(
size
uint32
)
[]
byte
{
func
(
p
*
GcBufferPool
)
AllocBuffer
(
size
uint32
)
[]
byte
{
return
make
([]
byte
,
size
)
}
func
(
me
*
GcBufferPool
)
FreeBuffer
(
slice
[]
byte
)
{
func
(
p
*
GcBufferPool
)
FreeBuffer
(
slice
[]
byte
)
{
}
// BufferPool implements a pool of buffers that returns slices with
...
...
@@ -55,27 +55,27 @@ func NewBufferPool() *BufferPoolImpl {
return
bp
}
func
(
me
*
BufferPoolImpl
)
String
()
string
{
me
.
lock
.
Lock
()
defer
me
.
lock
.
Unlock
()
func
(
p
*
BufferPoolImpl
)
String
()
string
{
p
.
lock
.
Lock
()
defer
p
.
lock
.
Unlock
()
result
:=
[]
string
{}
for
exp
,
bufs
:=
range
me
.
buffersBySize
{
for
exp
,
bufs
:=
range
p
.
buffersBySize
{
if
len
(
bufs
)
>
0
{
result
=
append
(
result
,
fmt
.
Sprintf
(
"%d=%d"
,
exp
,
len
(
bufs
)))
}
}
return
fmt
.
Sprintf
(
"created: %d, outstanding %d. Sizes: %s"
,
me
.
createdBuffers
,
len
(
me
.
outstandingBuffers
),
p
.
createdBuffers
,
len
(
p
.
outstandingBuffers
),
strings
.
Join
(
result
,
", "
))
}
func
(
me
*
BufferPoolImpl
)
getBuffer
(
pageCount
int
)
[]
byte
{
for
;
pageCount
<
len
(
me
.
buffersBySize
);
pageCount
++
{
bufferList
:=
me
.
buffersBySize
[
pageCount
]
func
(
p
*
BufferPoolImpl
)
getBuffer
(
pageCount
int
)
[]
byte
{
for
;
pageCount
<
len
(
p
.
buffersBySize
);
pageCount
++
{
bufferList
:=
p
.
buffersBySize
[
pageCount
]
if
len
(
bufferList
)
>
0
{
result
:=
bufferList
[
len
(
bufferList
)
-
1
]
me
.
buffersBySize
[
pageCount
]
=
me
.
buffersBySize
[
pageCount
][
:
len
(
bufferList
)
-
1
]
p
.
buffersBySize
[
pageCount
]
=
p
.
buffersBySize
[
pageCount
][
:
len
(
bufferList
)
-
1
]
return
result
}
}
...
...
@@ -83,16 +83,16 @@ func (me *BufferPoolImpl) getBuffer(pageCount int) []byte {
return
nil
}
func
(
me
*
BufferPoolImpl
)
addBuffer
(
slice
[]
byte
,
pages
int
)
{
for
len
(
me
.
buffersBySize
)
<=
int
(
pages
)
{
me
.
buffersBySize
=
append
(
me
.
buffersBySize
,
make
([][]
byte
,
0
))
func
(
p
*
BufferPoolImpl
)
addBuffer
(
slice
[]
byte
,
pages
int
)
{
for
len
(
p
.
buffersBySize
)
<=
int
(
pages
)
{
p
.
buffersBySize
=
append
(
p
.
buffersBySize
,
make
([][]
byte
,
0
))
}
me
.
buffersBySize
[
pages
]
=
append
(
me
.
buffersBySize
[
pages
],
slice
)
p
.
buffersBySize
[
pages
]
=
append
(
p
.
buffersBySize
[
pages
],
slice
)
}
// AllocBuffer creates a buffer of at least the given size. After use,
// it should be deallocated with FreeBuffer().
func
(
me
*
BufferPoolImpl
)
AllocBuffer
(
size
uint32
)
[]
byte
{
func
(
p
*
BufferPoolImpl
)
AllocBuffer
(
size
uint32
)
[]
byte
{
sz
:=
int
(
size
)
if
sz
<
PAGESIZE
{
sz
=
PAGESIZE
...
...
@@ -103,23 +103,23 @@ func (me *BufferPoolImpl) AllocBuffer(size uint32) []byte {
}
psz
:=
sz
/
PAGESIZE
me
.
lock
.
Lock
()
defer
me
.
lock
.
Unlock
()
p
.
lock
.
Lock
()
defer
p
.
lock
.
Unlock
()
var
b
[]
byte
b
=
me
.
getBuffer
(
psz
)
b
=
p
.
getBuffer
(
psz
)
if
b
==
nil
{
me
.
createdBuffers
++
p
.
createdBuffers
++
b
=
make
([]
byte
,
size
,
psz
*
PAGESIZE
)
}
else
{
b
=
b
[
:
size
]
}
me
.
outstandingBuffers
[
uintptr
(
unsafe
.
Pointer
(
&
b
[
0
]))]
=
true
p
.
outstandingBuffers
[
uintptr
(
unsafe
.
Pointer
(
&
b
[
0
]))]
=
true
// For testing should not have more than 20 buffers outstanding.
if
paranoia
&&
(
me
.
createdBuffers
>
50
||
len
(
me
.
outstandingBuffers
)
>
50
)
{
if
paranoia
&&
(
p
.
createdBuffers
>
50
||
len
(
p
.
outstandingBuffers
)
>
50
)
{
panic
(
"Leaking buffers"
)
}
...
...
@@ -129,7 +129,7 @@ func (me *BufferPoolImpl) AllocBuffer(size uint32) []byte {
// FreeBuffer takes back a buffer if it was allocated through
// AllocBuffer. It is not an error to call FreeBuffer() on a slice
// obtained elsewhere.
func
(
me
*
BufferPoolImpl
)
FreeBuffer
(
slice
[]
byte
)
{
func
(
p
*
BufferPoolImpl
)
FreeBuffer
(
slice
[]
byte
)
{
if
slice
==
nil
{
return
}
...
...
@@ -140,11 +140,11 @@ func (me *BufferPoolImpl) FreeBuffer(slice []byte) {
slice
=
slice
[
:
psz
]
key
:=
uintptr
(
unsafe
.
Pointer
(
&
slice
[
0
]))
me
.
lock
.
Lock
()
defer
me
.
lock
.
Unlock
()
ok
:=
me
.
outstandingBuffers
[
key
]
p
.
lock
.
Lock
()
defer
p
.
lock
.
Unlock
()
ok
:=
p
.
outstandingBuffers
[
key
]
if
ok
{
me
.
addBuffer
(
slice
,
psz
)
delete
(
me
.
outstandingBuffers
,
key
)
p
.
addBuffer
(
slice
,
psz
)
delete
(
p
.
outstandingBuffers
,
key
)
}
}
fuse/cache_test.go
View file @
ce603372
...
...
@@ -16,8 +16,8 @@ type cacheFs struct {
*
LoopbackFileSystem
}
func
(
me
*
cacheFs
)
Open
(
name
string
,
flags
uint32
,
context
*
Context
)
(
fuseFile
File
,
status
Status
)
{
f
,
c
:=
me
.
LoopbackFileSystem
.
Open
(
name
,
flags
,
context
)
func
(
fs
*
cacheFs
)
Open
(
name
string
,
flags
uint32
,
context
*
Context
)
(
fuseFile
File
,
status
Status
)
{
f
,
c
:=
fs
.
LoopbackFileSystem
.
Open
(
name
,
flags
,
context
)
if
!
c
.
Ok
()
{
return
f
,
c
}
...
...
@@ -96,19 +96,19 @@ type nonseekFs struct {
Length
int
}
func
(
me
*
nonseekFs
)
GetAttr
(
name
string
,
context
*
Context
)
(
fi
*
Attr
,
status
Status
)
{
func
(
fs
*
nonseekFs
)
GetAttr
(
name
string
,
context
*
Context
)
(
fi
*
Attr
,
status
Status
)
{
if
name
==
"file"
{
return
&
Attr
{
Mode
:
S_IFREG
|
0644
},
OK
}
return
nil
,
ENOENT
}
func
(
me
*
nonseekFs
)
Open
(
name
string
,
flags
uint32
,
context
*
Context
)
(
fuseFile
File
,
status
Status
)
{
func
(
fs
*
nonseekFs
)
Open
(
name
string
,
flags
uint32
,
context
*
Context
)
(
fuseFile
File
,
status
Status
)
{
if
name
!=
"file"
{
return
nil
,
ENOENT
}
data
:=
bytes
.
Repeat
([]
byte
{
42
},
me
.
Length
)
data
:=
bytes
.
Repeat
([]
byte
{
42
},
fs
.
Length
)
f
:=
NewDataFile
(
data
)
return
&
WithFlags
{
File
:
f
,
...
...
fuse/default.go
View file @
ce603372
...
...
@@ -3,100 +3,100 @@ package fuse
import
()
// DefaultFileSystem
func
(
me
*
DefaultFileSystem
)
GetAttr
(
name
string
,
context
*
Context
)
(
*
Attr
,
Status
)
{
func
(
fs
*
DefaultFileSystem
)
GetAttr
(
name
string
,
context
*
Context
)
(
*
Attr
,
Status
)
{
return
nil
,
ENOSYS
}
func
(
me
*
DefaultFileSystem
)
GetXAttr
(
name
string
,
attr
string
,
context
*
Context
)
([]
byte
,
Status
)
{
func
(
fs
*
DefaultFileSystem
)
GetXAttr
(
name
string
,
attr
string
,
context
*
Context
)
([]
byte
,
Status
)
{
return
nil
,
ENOSYS
}
func
(
me
*
DefaultFileSystem
)
SetXAttr
(
name
string
,
attr
string
,
data
[]
byte
,
flags
int
,
context
*
Context
)
Status
{
func
(
fs
*
DefaultFileSystem
)
SetXAttr
(
name
string
,
attr
string
,
data
[]
byte
,
flags
int
,
context
*
Context
)
Status
{
return
ENOSYS
}
func
(
me
*
DefaultFileSystem
)
ListXAttr
(
name
string
,
context
*
Context
)
([]
string
,
Status
)
{
func
(
fs
*
DefaultFileSystem
)
ListXAttr
(
name
string
,
context
*
Context
)
([]
string
,
Status
)
{
return
nil
,
ENOSYS
}
func
(
me
*
DefaultFileSystem
)
RemoveXAttr
(
name
string
,
attr
string
,
context
*
Context
)
Status
{
func
(
fs
*
DefaultFileSystem
)
RemoveXAttr
(
name
string
,
attr
string
,
context
*
Context
)
Status
{
return
ENOSYS
}
func
(
me
*
DefaultFileSystem
)
Readlink
(
name
string
,
context
*
Context
)
(
string
,
Status
)
{
func
(
fs
*
DefaultFileSystem
)
Readlink
(
name
string
,
context
*
Context
)
(
string
,
Status
)
{
return
""
,
ENOSYS
}
func
(
me
*
DefaultFileSystem
)
Mknod
(
name
string
,
mode
uint32
,
dev
uint32
,
context
*
Context
)
Status
{
func
(
fs
*
DefaultFileSystem
)
Mknod
(
name
string
,
mode
uint32
,
dev
uint32
,
context
*
Context
)
Status
{
return
ENOSYS
}
func
(
me
*
DefaultFileSystem
)
Mkdir
(
name
string
,
mode
uint32
,
context
*
Context
)
Status
{
func
(
fs
*
DefaultFileSystem
)
Mkdir
(
name
string
,
mode
uint32
,
context
*
Context
)
Status
{
return
ENOSYS
}
func
(
me
*
DefaultFileSystem
)
Unlink
(
name
string
,
context
*
Context
)
(
code
Status
)
{
func
(
fs
*
DefaultFileSystem
)
Unlink
(
name
string
,
context
*
Context
)
(
code
Status
)
{
return
ENOSYS
}
func
(
me
*
DefaultFileSystem
)
Rmdir
(
name
string
,
context
*
Context
)
(
code
Status
)
{
func
(
fs
*
DefaultFileSystem
)
Rmdir
(
name
string
,
context
*
Context
)
(
code
Status
)
{
return
ENOSYS
}
func
(
me
*
DefaultFileSystem
)
Symlink
(
value
string
,
linkName
string
,
context
*
Context
)
(
code
Status
)
{
func
(
fs
*
DefaultFileSystem
)
Symlink
(
value
string
,
linkName
string
,
context
*
Context
)
(
code
Status
)
{
return
ENOSYS
}
func
(
me
*
DefaultFileSystem
)
Rename
(
oldName
string
,
newName
string
,
context
*
Context
)
(
code
Status
)
{
func
(
fs
*
DefaultFileSystem
)
Rename
(
oldName
string
,
newName
string
,
context
*
Context
)
(
code
Status
)
{
return
ENOSYS
}
func
(
me
*
DefaultFileSystem
)
Link
(
oldName
string
,
newName
string
,
context
*
Context
)
(
code
Status
)
{
func
(
fs
*
DefaultFileSystem
)
Link
(
oldName
string
,
newName
string
,
context
*
Context
)
(
code
Status
)
{
return
ENOSYS
}
func
(
me
*
DefaultFileSystem
)
Chmod
(
name
string
,
mode
uint32
,
context
*
Context
)
(
code
Status
)
{
func
(
fs
*
DefaultFileSystem
)
Chmod
(
name
string
,
mode
uint32
,
context
*
Context
)
(
code
Status
)
{
return
ENOSYS
}
func
(
me
*
DefaultFileSystem
)
Chown
(
name
string
,
uid
uint32
,
gid
uint32
,
context
*
Context
)
(
code
Status
)
{
func
(
fs
*
DefaultFileSystem
)
Chown
(
name
string
,
uid
uint32
,
gid
uint32
,
context
*
Context
)
(
code
Status
)
{
return
ENOSYS
}
func
(
me
*
DefaultFileSystem
)
Truncate
(
name
string
,
offset
uint64
,
context
*
Context
)
(
code
Status
)
{
func
(
fs
*
DefaultFileSystem
)
Truncate
(
name
string
,
offset
uint64
,
context
*
Context
)
(
code
Status
)
{
return
ENOSYS
}
func
(
me
*
DefaultFileSystem
)
Open
(
name
string
,
flags
uint32
,
context
*
Context
)
(
file
File
,
code
Status
)
{
func
(
fs
*
DefaultFileSystem
)
Open
(
name
string
,
flags
uint32
,
context
*
Context
)
(
file
File
,
code
Status
)
{
return
nil
,
ENOSYS
}
func
(
me
*
DefaultFileSystem
)
OpenDir
(
name
string
,
context
*
Context
)
(
stream
chan
DirEntry
,
status
Status
)
{
func
(
fs
*
DefaultFileSystem
)
OpenDir
(
name
string
,
context
*
Context
)
(
stream
chan
DirEntry
,
status
Status
)
{
return
nil
,
ENOSYS
}
func
(
me
*
DefaultFileSystem
)
OnMount
(
nodeFs
*
PathNodeFs
)
{
func
(
fs
*
DefaultFileSystem
)
OnMount
(
nodeFs
*
PathNodeFs
)
{
}
func
(
me
*
DefaultFileSystem
)
OnUnmount
()
{
func
(
fs
*
DefaultFileSystem
)
OnUnmount
()
{
}
func
(
me
*
DefaultFileSystem
)
Access
(
name
string
,
mode
uint32
,
context
*
Context
)
(
code
Status
)
{
func
(
fs
*
DefaultFileSystem
)
Access
(
name
string
,
mode
uint32
,
context
*
Context
)
(
code
Status
)
{
return
ENOSYS
}
func
(
me
*
DefaultFileSystem
)
Create
(
name
string
,
flags
uint32
,
mode
uint32
,
context
*
Context
)
(
file
File
,
code
Status
)
{
func
(
fs
*
DefaultFileSystem
)
Create
(
name
string
,
flags
uint32
,
mode
uint32
,
context
*
Context
)
(
file
File
,
code
Status
)
{
return
nil
,
ENOSYS
}
func
(
me
*
DefaultFileSystem
)
Utimens
(
name
string
,
AtimeNs
int64
,
CtimeNs
int64
,
context
*
Context
)
(
code
Status
)
{
func
(
fs
*
DefaultFileSystem
)
Utimens
(
name
string
,
AtimeNs
int64
,
CtimeNs
int64
,
context
*
Context
)
(
code
Status
)
{
return
ENOSYS
}
func
(
me
*
DefaultFileSystem
)
String
()
string
{
func
(
fs
*
DefaultFileSystem
)
String
()
string
{
return
"DefaultFileSystem"
}
func
(
me
*
DefaultFileSystem
)
StatFs
(
name
string
)
*
StatfsOut
{
func
(
fs
*
DefaultFileSystem
)
StatFs
(
name
string
)
*
StatfsOut
{
return
nil
}
fuse/defaultfile.go
View file @
ce603372
...
...
@@ -8,57 +8,57 @@ import (
var
_
=
log
.
Println
func
(
me
*
DefaultFile
)
SetInode
(
*
Inode
)
{
func
(
f
*
DefaultFile
)
SetInode
(
*
Inode
)
{
}
func
(
me
*
DefaultFile
)
InnerFile
()
File
{
func
(
f
*
DefaultFile
)
InnerFile
()
File
{
return
nil
}
func
(
me
*
DefaultFile
)
String
()
string
{
func
(
f
*
DefaultFile
)
String
()
string
{
return
"DefaultFile"
}
func
(
me
*
DefaultFile
)
Read
(
*
ReadIn
,
BufferPool
)
([]
byte
,
Status
)
{
func
(
f
*
DefaultFile
)
Read
(
*
ReadIn
,
BufferPool
)
([]
byte
,
Status
)
{
return
[]
byte
(
""
),
ENOSYS
}
func
(
me
*
DefaultFile
)
Write
(
*
WriteIn
,
[]
byte
)
(
uint32
,
Status
)
{
func
(
f
*
DefaultFile
)
Write
(
*
WriteIn
,
[]
byte
)
(
uint32
,
Status
)
{
return
0
,
ENOSYS
}
func
(
me
*
DefaultFile
)
Flush
()
Status
{
func
(
f
*
DefaultFile
)
Flush
()
Status
{
return
OK
}
func
(
me
*
DefaultFile
)
Release
()
{
func
(
f
*
DefaultFile
)
Release
()
{
}
func
(
me
*
DefaultFile
)
GetAttr
()
(
*
Attr
,
Status
)
{
func
(
f
*
DefaultFile
)
GetAttr
()
(
*
Attr
,
Status
)
{
return
nil
,
ENOSYS
}
func
(
me
*
DefaultFile
)
Fsync
(
flags
int
)
(
code
Status
)
{
func
(
f
*
DefaultFile
)
Fsync
(
flags
int
)
(
code
Status
)
{
return
ENOSYS
}
func
(
me
*
DefaultFile
)
Utimens
(
atimeNs
int64
,
mtimeNs
int64
)
Status
{
func
(
f
*
DefaultFile
)
Utimens
(
atimeNs
int64
,
mtimeNs
int64
)
Status
{
return
ENOSYS
}
func
(
me
*
DefaultFile
)
Truncate
(
size
uint64
)
Status
{
func
(
f
*
DefaultFile
)
Truncate
(
size
uint64
)
Status
{
return
ENOSYS
}
func
(
me
*
DefaultFile
)
Chown
(
uid
uint32
,
gid
uint32
)
Status
{
func
(
f
*
DefaultFile
)
Chown
(
uid
uint32
,
gid
uint32
)
Status
{
return
ENOSYS
}
func
(
me
*
DefaultFile
)
Chmod
(
perms
uint32
)
Status
{
func
(
f
*
DefaultFile
)
Chmod
(
perms
uint32
)
Status
{
return
ENOSYS
}
func
(
me
*
DefaultFile
)
Ioctl
(
input
*
raw
.
IoctlIn
)
(
output
*
raw
.
IoctlOut
,
data
[]
byte
,
code
Status
)
{
func
(
f
*
DefaultFile
)
Ioctl
(
input
*
raw
.
IoctlIn
)
(
output
*
raw
.
IoctlOut
,
data
[]
byte
,
code
Status
)
{
return
nil
,
nil
,
ENOSYS
}
fuse/defaultnode.go
View file @
ce603372
...
...
@@ -9,18 +9,18 @@ var _ = log.Println
type
DefaultNodeFileSystem
struct
{
}
func
(
me
*
DefaultNodeFileSystem
)
OnUnmount
()
{
func
(
fs
*
DefaultNodeFileSystem
)
OnUnmount
()
{
}
func
(
me
*
DefaultNodeFileSystem
)
OnMount
(
conn
*
FileSystemConnector
)
{
func
(
fs
*
DefaultNodeFileSystem
)
OnMount
(
conn
*
FileSystemConnector
)
{
}
func
(
me
*
DefaultNodeFileSystem
)
Root
()
FsNode
{
func
(
fs
*
DefaultNodeFileSystem
)
Root
()
FsNode
{
return
new
(
DefaultFsNode
)
}
func
(
me
*
DefaultNodeFileSystem
)
String
()
string
{
func
(
fs
*
DefaultNodeFileSystem
)
String
()
string
{
return
"DefaultNodeFileSystem"
}
...
...
@@ -31,81 +31,81 @@ type DefaultFsNode struct {
inode
*
Inode
}
func
(
me
*
DefaultFsNode
)
StatFs
()
*
StatfsOut
{
func
(
n
*
DefaultFsNode
)
StatFs
()
*
StatfsOut
{
return
nil
}
func
(
me
*
DefaultFsNode
)
SetInode
(
node
*
Inode
)
{
if
me
.
inode
!=
nil
{
func
(
n
*
DefaultFsNode
)
SetInode
(
node
*
Inode
)
{
if
n
.
inode
!=
nil
{
panic
(
"already have Inode"
)
}
if
node
==
nil
{
panic
(
"SetInode called with nil Inode."
)
}
me
.
inode
=
node
n
.
inode
=
node
}
func
(
me
*
DefaultFsNode
)
Deletable
()
bool
{
func
(
n
*
DefaultFsNode
)
Deletable
()
bool
{
return
true
}
func
(
me
*
DefaultFsNode
)
Inode
()
*
Inode
{
return
me
.
inode
func
(
n
*
DefaultFsNode
)
Inode
()
*
Inode
{
return
n
.
inode
}
func
(
me
*
DefaultFsNode
)
OnForget
()
{
func
(
n
*
DefaultFsNode
)
OnForget
()
{
}
func
(
me
*
DefaultFsNode
)
Lookup
(
name
string
,
context
*
Context
)
(
fi
*
Attr
,
node
FsNode
,
code
Status
)
{
func
(
n
*
DefaultFsNode
)
Lookup
(
name
string
,
context
*
Context
)
(
fi
*
Attr
,
node
FsNode
,
code
Status
)
{
return
nil
,
nil
,
ENOENT
}
func
(
me
*
DefaultFsNode
)
Access
(
mode
uint32
,
context
*
Context
)
(
code
Status
)
{
func
(
n
*
DefaultFsNode
)
Access
(
mode
uint32
,
context
*
Context
)
(
code
Status
)
{
return
ENOSYS
}
func
(
me
*
DefaultFsNode
)
Readlink
(
c
*
Context
)
([]
byte
,
Status
)
{
func
(
n
*
DefaultFsNode
)
Readlink
(
c
*
Context
)
([]
byte
,
Status
)
{
return
nil
,
ENOSYS
}
func
(
me
*
DefaultFsNode
)
Mknod
(
name
string
,
mode
uint32
,
dev
uint32
,
context
*
Context
)
(
fi
*
Attr
,
newNode
FsNode
,
code
Status
)
{
func
(
n
*
DefaultFsNode
)
Mknod
(
name
string
,
mode
uint32
,
dev
uint32
,
context
*
Context
)
(
fi
*
Attr
,
newNode
FsNode
,
code
Status
)
{
return
nil
,
nil
,
ENOSYS
}
func
(
me
*
DefaultFsNode
)
Mkdir
(
name
string
,
mode
uint32
,
context
*
Context
)
(
fi
*
Attr
,
newNode
FsNode
,
code
Status
)
{
func
(
n
*
DefaultFsNode
)
Mkdir
(
name
string
,
mode
uint32
,
context
*
Context
)
(
fi
*
Attr
,
newNode
FsNode
,
code
Status
)
{
return
nil
,
nil
,
ENOSYS
}
func
(
me
*
DefaultFsNode
)
Unlink
(
name
string
,
context
*
Context
)
(
code
Status
)
{
func
(
n
*
DefaultFsNode
)
Unlink
(
name
string
,
context
*
Context
)
(
code
Status
)
{
return
ENOSYS
}
func
(
me
*
DefaultFsNode
)
Rmdir
(
name
string
,
context
*
Context
)
(
code
Status
)
{
func
(
n
*
DefaultFsNode
)
Rmdir
(
name
string
,
context
*
Context
)
(
code
Status
)
{
return
ENOSYS
}
func
(
me
*
DefaultFsNode
)
Symlink
(
name
string
,
content
string
,
context
*
Context
)
(
fi
*
Attr
,
newNode
FsNode
,
code
Status
)
{
func
(
n
*
DefaultFsNode
)
Symlink
(
name
string
,
content
string
,
context
*
Context
)
(
fi
*
Attr
,
newNode
FsNode
,
code
Status
)
{
return
nil
,
nil
,
ENOSYS
}
func
(
me
*
DefaultFsNode
)
Rename
(
oldName
string
,
newParent
FsNode
,
newName
string
,
context
*
Context
)
(
code
Status
)
{
func
(
n
*
DefaultFsNode
)
Rename
(
oldName
string
,
newParent
FsNode
,
newName
string
,
context
*
Context
)
(
code
Status
)
{
return
ENOSYS
}
func
(
me
*
DefaultFsNode
)
Link
(
name
string
,
existing
FsNode
,
context
*
Context
)
(
fi
*
Attr
,
newNode
FsNode
,
code
Status
)
{
func
(
n
*
DefaultFsNode
)
Link
(
name
string
,
existing
FsNode
,
context
*
Context
)
(
fi
*
Attr
,
newNode
FsNode
,
code
Status
)
{
return
nil
,
nil
,
ENOSYS
}
func
(
me
*
DefaultFsNode
)
Create
(
name
string
,
flags
uint32
,
mode
uint32
,
context
*
Context
)
(
file
File
,
fi
*
Attr
,
newNode
FsNode
,
code
Status
)
{
func
(
n
*
DefaultFsNode
)
Create
(
name
string
,
flags
uint32
,
mode
uint32
,
context
*
Context
)
(
file
File
,
fi
*
Attr
,
newNode
FsNode
,
code
Status
)
{
return
nil
,
nil
,
nil
,
ENOSYS
}
func
(
me
*
DefaultFsNode
)
Open
(
flags
uint32
,
context
*
Context
)
(
file
File
,
code
Status
)
{
func
(
n
*
DefaultFsNode
)
Open
(
flags
uint32
,
context
*
Context
)
(
file
File
,
code
Status
)
{
return
nil
,
ENOSYS
}
func
(
me
*
DefaultFsNode
)
Flush
(
file
File
,
openFlags
uint32
,
context
*
Context
)
(
code
Status
)
{
func
(
n
*
DefaultFsNode
)
Flush
(
file
File
,
openFlags
uint32
,
context
*
Context
)
(
code
Status
)
{
return
ENOSYS
}
func
(
me
*
DefaultFsNode
)
OpenDir
(
context
*
Context
)
(
chan
DirEntry
,
Status
)
{
ch
:=
me
.
Inode
()
.
Children
()
func
(
n
*
DefaultFsNode
)
OpenDir
(
context
*
Context
)
(
chan
DirEntry
,
Status
)
{
ch
:=
n
.
Inode
()
.
Children
()
s
:=
make
(
chan
DirEntry
,
len
(
ch
))
for
name
,
child
:=
range
ch
{
fi
,
code
:=
child
.
FsNode
()
.
GetAttr
(
nil
,
context
)
...
...
@@ -117,41 +117,41 @@ func (me *DefaultFsNode) OpenDir(context *Context) (chan DirEntry, Status) {
return
s
,
OK
}
func
(
me
*
DefaultFsNode
)
GetXAttr
(
attribute
string
,
context
*
Context
)
(
data
[]
byte
,
code
Status
)
{
func
(
n
*
DefaultFsNode
)
GetXAttr
(
attribute
string
,
context
*
Context
)
(
data
[]
byte
,
code
Status
)
{
return
nil
,
ENOSYS
}
func
(
me
*
DefaultFsNode
)
RemoveXAttr
(
attr
string
,
context
*
Context
)
Status
{
func
(
n
*
DefaultFsNode
)
RemoveXAttr
(
attr
string
,
context
*
Context
)
Status
{
return
ENOSYS
}
func
(
me
*
DefaultFsNode
)
SetXAttr
(
attr
string
,
data
[]
byte
,
flags
int
,
context
*
Context
)
Status
{
func
(
n
*
DefaultFsNode
)
SetXAttr
(
attr
string
,
data
[]
byte
,
flags
int
,
context
*
Context
)
Status
{
return
ENOSYS
}
func
(
me
*
DefaultFsNode
)
ListXAttr
(
context
*
Context
)
(
attrs
[]
string
,
code
Status
)
{
func
(
n
*
DefaultFsNode
)
ListXAttr
(
context
*
Context
)
(
attrs
[]
string
,
code
Status
)
{
return
nil
,
ENOSYS
}
func
(
me
*
DefaultFsNode
)
GetAttr
(
file
File
,
context
*
Context
)
(
fi
*
Attr
,
code
Status
)
{
if
me
.
Inode
()
.
IsDir
()
{
func
(
n
*
DefaultFsNode
)
GetAttr
(
file
File
,
context
*
Context
)
(
fi
*
Attr
,
code
Status
)
{
if
n
.
Inode
()
.
IsDir
()
{
return
&
Attr
{
Mode
:
S_IFDIR
|
0755
},
OK
}
return
&
Attr
{
Mode
:
S_IFREG
|
0644
},
OK
}
func
(
me
*
DefaultFsNode
)
Chmod
(
file
File
,
perms
uint32
,
context
*
Context
)
(
code
Status
)
{
func
(
n
*
DefaultFsNode
)
Chmod
(
file
File
,
perms
uint32
,
context
*
Context
)
(
code
Status
)
{
return
ENOSYS
}
func
(
me
*
DefaultFsNode
)
Chown
(
file
File
,
uid
uint32
,
gid
uint32
,
context
*
Context
)
(
code
Status
)
{
func
(
n
*
DefaultFsNode
)
Chown
(
file
File
,
uid
uint32
,
gid
uint32
,
context
*
Context
)
(
code
Status
)
{
return
ENOSYS
}
func
(
me
*
DefaultFsNode
)
Truncate
(
file
File
,
size
uint64
,
context
*
Context
)
(
code
Status
)
{
func
(
n
*
DefaultFsNode
)
Truncate
(
file
File
,
size
uint64
,
context
*
Context
)
(
code
Status
)
{
return
ENOSYS
}
func
(
me
*
DefaultFsNode
)
Utimens
(
file
File
,
atime
int64
,
mtime
int64
,
context
*
Context
)
(
code
Status
)
{
func
(
n
*
DefaultFsNode
)
Utimens
(
file
File
,
atime
int64
,
mtime
int64
,
context
*
Context
)
(
code
Status
)
{
return
ENOSYS
}
fuse/defaultraw.go
View file @
ce603372
...
...
@@ -4,134 +4,134 @@ import (
"github.com/hanwen/go-fuse/raw"
)
func
(
me
*
DefaultRawFileSystem
)
Init
(
init
*
RawFsInit
)
{
func
(
fs
*
DefaultRawFileSystem
)
Init
(
init
*
RawFsInit
)
{
}
func
(
me
*
DefaultRawFileSystem
)
StatFs
(
h
*
raw
.
InHeader
)
*
StatfsOut
{
func
(
fs
*
DefaultRawFileSystem
)
StatFs
(
h
*
raw
.
InHeader
)
*
StatfsOut
{
return
nil
}
func
(
me
*
DefaultRawFileSystem
)
Lookup
(
h
*
raw
.
InHeader
,
name
string
)
(
out
*
raw
.
EntryOut
,
code
Status
)
{
func
(
fs
*
DefaultRawFileSystem
)
Lookup
(
h
*
raw
.
InHeader
,
name
string
)
(
out
*
raw
.
EntryOut
,
code
Status
)
{
return
nil
,
ENOSYS
}
func
(
me
*
DefaultRawFileSystem
)
Forget
(
nodeID
,
nlookup
uint64
)
{
func
(
fs
*
DefaultRawFileSystem
)
Forget
(
nodeID
,
nlookup
uint64
)
{
}
func
(
me
*
DefaultRawFileSystem
)
GetAttr
(
header
*
raw
.
InHeader
,
input
*
raw
.
GetAttrIn
)
(
out
*
raw
.
AttrOut
,
code
Status
)
{
func
(
fs
*
DefaultRawFileSystem
)
GetAttr
(
header
*
raw
.
InHeader
,
input
*
raw
.
GetAttrIn
)
(
out
*
raw
.
AttrOut
,
code
Status
)
{
return
nil
,
ENOSYS
}
func
(
me
*
DefaultRawFileSystem
)
Open
(
header
*
raw
.
InHeader
,
input
*
raw
.
OpenIn
)
(
flags
uint32
,
handle
uint64
,
status
Status
)
{
func
(
fs
*
DefaultRawFileSystem
)
Open
(
header
*
raw
.
InHeader
,
input
*
raw
.
OpenIn
)
(
flags
uint32
,
handle
uint64
,
status
Status
)
{
return
0
,
0
,
OK
}
func
(
me
*
DefaultRawFileSystem
)
SetAttr
(
header
*
raw
.
InHeader
,
input
*
raw
.
SetAttrIn
)
(
out
*
raw
.
AttrOut
,
code
Status
)
{
func
(
fs
*
DefaultRawFileSystem
)
SetAttr
(
header
*
raw
.
InHeader
,
input
*
raw
.
SetAttrIn
)
(
out
*
raw
.
AttrOut
,
code
Status
)
{
return
nil
,
ENOSYS
}
func
(
me
*
DefaultRawFileSystem
)
Readlink
(
header
*
raw
.
InHeader
)
(
out
[]
byte
,
code
Status
)
{
func
(
fs
*
DefaultRawFileSystem
)
Readlink
(
header
*
raw
.
InHeader
)
(
out
[]
byte
,
code
Status
)
{
return
nil
,
ENOSYS
}
func
(
me
*
DefaultRawFileSystem
)
Mknod
(
header
*
raw
.
InHeader
,
input
*
raw
.
MknodIn
,
name
string
)
(
out
*
raw
.
EntryOut
,
code
Status
)
{
func
(
fs
*
DefaultRawFileSystem
)
Mknod
(
header
*
raw
.
InHeader
,
input
*
raw
.
MknodIn
,
name
string
)
(
out
*
raw
.
EntryOut
,
code
Status
)
{
return
new
(
raw
.
EntryOut
),
ENOSYS
}
func
(
me
*
DefaultRawFileSystem
)
Mkdir
(
header
*
raw
.
InHeader
,
input
*
raw
.
MkdirIn
,
name
string
)
(
out
*
raw
.
EntryOut
,
code
Status
)
{
func
(
fs
*
DefaultRawFileSystem
)
Mkdir
(
header
*
raw
.
InHeader
,
input
*
raw
.
MkdirIn
,
name
string
)
(
out
*
raw
.
EntryOut
,
code
Status
)
{
return
nil
,
ENOSYS
}
func
(
me
*
DefaultRawFileSystem
)
Unlink
(
header
*
raw
.
InHeader
,
name
string
)
(
code
Status
)
{
func
(
fs
*
DefaultRawFileSystem
)
Unlink
(
header
*
raw
.
InHeader
,
name
string
)
(
code
Status
)
{
return
ENOSYS
}
func
(
me
*
DefaultRawFileSystem
)
Rmdir
(
header
*
raw
.
InHeader
,
name
string
)
(
code
Status
)
{
func
(
fs
*
DefaultRawFileSystem
)
Rmdir
(
header
*
raw
.
InHeader
,
name
string
)
(
code
Status
)
{
return
ENOSYS
}
func
(
me
*
DefaultRawFileSystem
)
Symlink
(
header
*
raw
.
InHeader
,
pointedTo
string
,
linkName
string
)
(
out
*
raw
.
EntryOut
,
code
Status
)
{
func
(
fs
*
DefaultRawFileSystem
)
Symlink
(
header
*
raw
.
InHeader
,
pointedTo
string
,
linkName
string
)
(
out
*
raw
.
EntryOut
,
code
Status
)
{
return
nil
,
ENOSYS
}
func
(
me
*
DefaultRawFileSystem
)
Rename
(
header
*
raw
.
InHeader
,
input
*
raw
.
RenameIn
,
oldName
string
,
newName
string
)
(
code
Status
)
{
func
(
fs
*
DefaultRawFileSystem
)
Rename
(
header
*
raw
.
InHeader
,
input
*
raw
.
RenameIn
,
oldName
string
,
newName
string
)
(
code
Status
)
{
return
ENOSYS
}
func
(
me
*
DefaultRawFileSystem
)
Link
(
header
*
raw
.
InHeader
,
input
*
raw
.
LinkIn
,
name
string
)
(
out
*
raw
.
EntryOut
,
code
Status
)
{
func
(
fs
*
DefaultRawFileSystem
)
Link
(
header
*
raw
.
InHeader
,
input
*
raw
.
LinkIn
,
name
string
)
(
out
*
raw
.
EntryOut
,
code
Status
)
{
return
nil
,
ENOSYS
}
func
(
me
*
DefaultRawFileSystem
)
GetXAttrSize
(
header
*
raw
.
InHeader
,
attr
string
)
(
size
int
,
code
Status
)
{
func
(
fs
*
DefaultRawFileSystem
)
GetXAttrSize
(
header
*
raw
.
InHeader
,
attr
string
)
(
size
int
,
code
Status
)
{
return
0
,
ENOSYS
}
func
(
me
*
DefaultRawFileSystem
)
GetXAttrData
(
header
*
raw
.
InHeader
,
attr
string
)
(
data
[]
byte
,
code
Status
)
{
func
(
fs
*
DefaultRawFileSystem
)
GetXAttrData
(
header
*
raw
.
InHeader
,
attr
string
)
(
data
[]
byte
,
code
Status
)
{
return
nil
,
ENOSYS
}
func
(
me
*
DefaultRawFileSystem
)
SetXAttr
(
header
*
raw
.
InHeader
,
input
*
raw
.
SetXAttrIn
,
attr
string
,
data
[]
byte
)
Status
{
func
(
fs
*
DefaultRawFileSystem
)
SetXAttr
(
header
*
raw
.
InHeader
,
input
*
raw
.
SetXAttrIn
,
attr
string
,
data
[]
byte
)
Status
{
return
ENOSYS
}
func
(
me
*
DefaultRawFileSystem
)
ListXAttr
(
header
*
raw
.
InHeader
)
(
data
[]
byte
,
code
Status
)
{
func
(
fs
*
DefaultRawFileSystem
)
ListXAttr
(
header
*
raw
.
InHeader
)
(
data
[]
byte
,
code
Status
)
{
return
nil
,
ENOSYS
}
func
(
me
*
DefaultRawFileSystem
)
RemoveXAttr
(
header
*
raw
.
InHeader
,
attr
string
)
Status
{
func
(
fs
*
DefaultRawFileSystem
)
RemoveXAttr
(
header
*
raw
.
InHeader
,
attr
string
)
Status
{
return
ENOSYS
}
func
(
me
*
DefaultRawFileSystem
)
Access
(
header
*
raw
.
InHeader
,
input
*
raw
.
AccessIn
)
(
code
Status
)
{
func
(
fs
*
DefaultRawFileSystem
)
Access
(
header
*
raw
.
InHeader
,
input
*
raw
.
AccessIn
)
(
code
Status
)
{
return
ENOSYS
}
func
(
me
*
DefaultRawFileSystem
)
Create
(
header
*
raw
.
InHeader
,
input
*
raw
.
CreateIn
,
name
string
)
(
flags
uint32
,
handle
uint64
,
out
*
raw
.
EntryOut
,
code
Status
)
{
func
(
fs
*
DefaultRawFileSystem
)
Create
(
header
*
raw
.
InHeader
,
input
*
raw
.
CreateIn
,
name
string
)
(
flags
uint32
,
handle
uint64
,
out
*
raw
.
EntryOut
,
code
Status
)
{
return
0
,
0
,
nil
,
ENOSYS
}
func
(
me
*
DefaultRawFileSystem
)
Bmap
(
header
*
raw
.
InHeader
,
input
*
raw
.
BmapIn
)
(
out
*
raw
.
BmapOut
,
code
Status
)
{
func
(
fs
*
DefaultRawFileSystem
)
Bmap
(
header
*
raw
.
InHeader
,
input
*
raw
.
BmapIn
)
(
out
*
raw
.
BmapOut
,
code
Status
)
{
return
nil
,
ENOSYS
}
func
(
me
*
DefaultRawFileSystem
)
Poll
(
header
*
raw
.
InHeader
,
input
*
raw
.
PollIn
)
(
out
*
raw
.
PollOut
,
code
Status
)
{
func
(
fs
*
DefaultRawFileSystem
)
Poll
(
header
*
raw
.
InHeader
,
input
*
raw
.
PollIn
)
(
out
*
raw
.
PollOut
,
code
Status
)
{
return
nil
,
ENOSYS
}
func
(
me
*
DefaultRawFileSystem
)
OpenDir
(
header
*
raw
.
InHeader
,
input
*
raw
.
OpenIn
)
(
flags
uint32
,
handle
uint64
,
status
Status
)
{
func
(
fs
*
DefaultRawFileSystem
)
OpenDir
(
header
*
raw
.
InHeader
,
input
*
raw
.
OpenIn
)
(
flags
uint32
,
handle
uint64
,
status
Status
)
{
return
0
,
0
,
ENOSYS
}
func
(
me
*
DefaultRawFileSystem
)
Read
(
header
*
raw
.
InHeader
,
input
*
ReadIn
,
bp
BufferPool
)
([]
byte
,
Status
)
{
func
(
fs
*
DefaultRawFileSystem
)
Read
(
header
*
raw
.
InHeader
,
input
*
ReadIn
,
bp
BufferPool
)
([]
byte
,
Status
)
{
return
nil
,
ENOSYS
}
func
(
me
*
DefaultRawFileSystem
)
Release
(
header
*
raw
.
InHeader
,
input
*
raw
.
ReleaseIn
)
{
func
(
fs
*
DefaultRawFileSystem
)
Release
(
header
*
raw
.
InHeader
,
input
*
raw
.
ReleaseIn
)
{
}
func
(
me
*
DefaultRawFileSystem
)
Write
(
header
*
raw
.
InHeader
,
input
*
WriteIn
,
data
[]
byte
)
(
written
uint32
,
code
Status
)
{
func
(
fs
*
DefaultRawFileSystem
)
Write
(
header
*
raw
.
InHeader
,
input
*
WriteIn
,
data
[]
byte
)
(
written
uint32
,
code
Status
)
{
return
0
,
ENOSYS
}
func
(
me
*
DefaultRawFileSystem
)
Flush
(
header
*
raw
.
InHeader
,
input
*
raw
.
FlushIn
)
Status
{
func
(
fs
*
DefaultRawFileSystem
)
Flush
(
header
*
raw
.
InHeader
,
input
*
raw
.
FlushIn
)
Status
{
return
OK
}
func
(
me
*
DefaultRawFileSystem
)
Fsync
(
header
*
raw
.
InHeader
,
input
*
raw
.
FsyncIn
)
(
code
Status
)
{
func
(
fs
*
DefaultRawFileSystem
)
Fsync
(
header
*
raw
.
InHeader
,
input
*
raw
.
FsyncIn
)
(
code
Status
)
{
return
ENOSYS
}
func
(
me
*
DefaultRawFileSystem
)
ReadDir
(
header
*
raw
.
InHeader
,
input
*
ReadIn
)
(
*
DirEntryList
,
Status
)
{
func
(
fs
*
DefaultRawFileSystem
)
ReadDir
(
header
*
raw
.
InHeader
,
input
*
ReadIn
)
(
*
DirEntryList
,
Status
)
{
return
nil
,
ENOSYS
}
func
(
me
*
DefaultRawFileSystem
)
ReleaseDir
(
header
*
raw
.
InHeader
,
input
*
raw
.
ReleaseIn
)
{
func
(
fs
*
DefaultRawFileSystem
)
ReleaseDir
(
header
*
raw
.
InHeader
,
input
*
raw
.
ReleaseIn
)
{
}
func
(
me
*
DefaultRawFileSystem
)
FsyncDir
(
header
*
raw
.
InHeader
,
input
*
raw
.
FsyncIn
)
(
code
Status
)
{
func
(
fs
*
DefaultRawFileSystem
)
FsyncDir
(
header
*
raw
.
InHeader
,
input
*
raw
.
FsyncIn
)
(
code
Status
)
{
return
ENOSYS
}
func
(
me
*
DefaultRawFileSystem
)
Ioctl
(
header
*
raw
.
InHeader
,
input
*
raw
.
IoctlIn
)
(
output
*
raw
.
IoctlOut
,
data
[]
byte
,
code
Status
)
{
func
(
fs
*
DefaultRawFileSystem
)
Ioctl
(
header
*
raw
.
InHeader
,
input
*
raw
.
IoctlIn
)
(
output
*
raw
.
IoctlOut
,
data
[]
byte
,
code
Status
)
{
return
nil
,
nil
,
ENOSYS
}
fuse/direntry.go
View file @
ce603372
...
...
@@ -29,46 +29,46 @@ func NewDirEntryList(max int, off *uint64) *DirEntryList {
return
&
DirEntryList
{
maxSize
:
max
,
offset
:
off
}
}
func
(
me
*
DirEntryList
)
AddString
(
name
string
,
inode
uint64
,
mode
uint32
)
bool
{
return
me
.
Add
([]
byte
(
name
),
inode
,
mode
)
func
(
l
*
DirEntryList
)
AddString
(
name
string
,
inode
uint64
,
mode
uint32
)
bool
{
return
l
.
Add
([]
byte
(
name
),
inode
,
mode
)
}
func
(
me
*
DirEntryList
)
AddDirEntry
(
e
DirEntry
)
bool
{
return
me
.
Add
([]
byte
(
e
.
Name
),
uint64
(
raw
.
FUSE_UNKNOWN_INO
),
e
.
Mode
)
func
(
l
*
DirEntryList
)
AddDirEntry
(
e
DirEntry
)
bool
{
return
l
.
Add
([]
byte
(
e
.
Name
),
uint64
(
raw
.
FUSE_UNKNOWN_INO
),
e
.
Mode
)
}
func
(
me
*
DirEntryList
)
Add
(
name
[]
byte
,
inode
uint64
,
mode
uint32
)
bool
{
lastLen
:=
me
.
buf
.
Len
()
(
*
me
.
offset
)
++
func
(
l
*
DirEntryList
)
Add
(
name
[]
byte
,
inode
uint64
,
mode
uint32
)
bool
{
lastLen
:=
l
.
buf
.
Len
()
(
*
l
.
offset
)
++
dirent
:=
raw
.
Dirent
{
Off
:
*
me
.
offset
,
Off
:
*
l
.
offset
,
Ino
:
inode
,
NameLen
:
uint32
(
len
(
name
)),
Typ
:
ModeToType
(
mode
),
}
_
,
err
:=
me
.
buf
.
Write
(
asSlice
(
unsafe
.
Pointer
(
&
dirent
),
unsafe
.
Sizeof
(
raw
.
Dirent
{})))
_
,
err
:=
l
.
buf
.
Write
(
asSlice
(
unsafe
.
Pointer
(
&
dirent
),
unsafe
.
Sizeof
(
raw
.
Dirent
{})))
if
err
!=
nil
{
panic
(
"Serialization of Dirent failed"
)
}
me
.
buf
.
Write
(
name
)
l
.
buf
.
Write
(
name
)
padding
:=
8
-
len
(
name
)
&
7
if
padding
<
8
{
me
.
buf
.
Write
(
make
([]
byte
,
padding
))
l
.
buf
.
Write
(
make
([]
byte
,
padding
))
}
if
me
.
buf
.
Len
()
>
me
.
maxSize
{
me
.
buf
.
Truncate
(
lastLen
)
(
*
me
.
offset
)
--
if
l
.
buf
.
Len
()
>
l
.
maxSize
{
l
.
buf
.
Truncate
(
lastLen
)
(
*
l
.
offset
)
--
return
false
}
return
true
}
func
(
me
*
DirEntryList
)
Bytes
()
[]
byte
{
return
me
.
buf
.
Bytes
()
func
(
l
*
DirEntryList
)
Bytes
()
[]
byte
{
return
l
.
buf
.
Bytes
()
}
////////////////////////////////////////////////////////////////
...
...
@@ -85,36 +85,36 @@ type connectorDir struct {
lastOffset
uint64
}
func
(
me
*
connectorDir
)
ReadDir
(
input
*
ReadIn
)
(
*
DirEntryList
,
Status
)
{
if
me
.
stream
==
nil
&&
len
(
me
.
extra
)
==
0
{
func
(
d
*
connectorDir
)
ReadDir
(
input
*
ReadIn
)
(
*
DirEntryList
,
Status
)
{
if
d
.
stream
==
nil
&&
len
(
d
.
extra
)
==
0
{
return
nil
,
OK
}
list
:=
NewDirEntryList
(
int
(
input
.
Size
),
&
me
.
lastOffset
)
if
me
.
leftOver
.
Name
!=
""
{
success
:=
list
.
AddDirEntry
(
me
.
leftOver
)
list
:=
NewDirEntryList
(
int
(
input
.
Size
),
&
d
.
lastOffset
)
if
d
.
leftOver
.
Name
!=
""
{
success
:=
list
.
AddDirEntry
(
d
.
leftOver
)
if
!
success
{
panic
(
"No space for single entry."
)
}
me
.
leftOver
.
Name
=
""
d
.
leftOver
.
Name
=
""
}
for
len
(
me
.
extra
)
>
0
{
e
:=
me
.
extra
[
len
(
me
.
extra
)
-
1
]
me
.
extra
=
me
.
extra
[
:
len
(
me
.
extra
)
-
1
]
for
len
(
d
.
extra
)
>
0
{
e
:=
d
.
extra
[
len
(
d
.
extra
)
-
1
]
d
.
extra
=
d
.
extra
[
:
len
(
d
.
extra
)
-
1
]
success
:=
list
.
AddDirEntry
(
e
)
if
!
success
{
me
.
leftOver
=
e
d
.
leftOver
=
e
return
list
,
OK
}
}
for
{
d
,
isOpen
:=
<-
me
.
stream
d
e
,
isOpen
:=
<-
d
.
stream
if
!
isOpen
{
me
.
stream
=
nil
d
.
stream
=
nil
break
}
if
!
list
.
AddDirEntry
(
d
)
{
me
.
leftOver
=
d
if
!
list
.
AddDirEntry
(
d
e
)
{
d
.
leftOver
=
de
break
}
}
...
...
@@ -122,9 +122,9 @@ func (me *connectorDir) ReadDir(input *ReadIn) (*DirEntryList, Status) {
}
// Read everything so we make goroutines exit.
func
(
me
*
connectorDir
)
Release
()
{
for
ok
:=
true
;
ok
&&
me
.
stream
!=
nil
;
{
_
,
ok
=
<-
me
.
stream
func
(
d
*
connectorDir
)
Release
()
{
for
ok
:=
true
;
ok
&&
d
.
stream
!=
nil
;
{
_
,
ok
=
<-
d
.
stream
if
!
ok
{
break
}
...
...
fuse/files.go
View file @
ce603372
...
...
@@ -17,17 +17,17 @@ type DataFile struct {
DefaultFile
}
func
(
me
*
DataFile
)
String
()
string
{
l
:=
len
(
me
.
data
)
func
(
f
*
DataFile
)
String
()
string
{
l
:=
len
(
f
.
data
)
if
l
>
10
{
l
=
10
}
return
fmt
.
Sprintf
(
"DataFile(%x)"
,
me
.
data
[
:
l
])
return
fmt
.
Sprintf
(
"DataFile(%x)"
,
f
.
data
[
:
l
])
}
func
(
me
*
DataFile
)
GetAttr
()
(
*
Attr
,
Status
)
{
return
&
Attr
{
Mode
:
S_IFREG
|
0644
,
Size
:
uint64
(
len
(
me
.
data
))},
OK
func
(
f
*
DataFile
)
GetAttr
()
(
*
Attr
,
Status
)
{
return
&
Attr
{
Mode
:
S_IFREG
|
0644
,
Size
:
uint64
(
len
(
f
.
data
))},
OK
}
func
NewDataFile
(
data
[]
byte
)
*
DataFile
{
...
...
@@ -36,13 +36,13 @@ func NewDataFile(data []byte) *DataFile {
return
f
}
func
(
me
*
DataFile
)
Read
(
input
*
ReadIn
,
bp
BufferPool
)
([]
byte
,
Status
)
{
func
(
f
*
DataFile
)
Read
(
input
*
ReadIn
,
bp
BufferPool
)
([]
byte
,
Status
)
{
end
:=
int
(
input
.
Offset
)
+
int
(
input
.
Size
)
if
end
>
len
(
me
.
data
)
{
end
=
len
(
me
.
data
)
if
end
>
len
(
f
.
data
)
{
end
=
len
(
f
.
data
)
}
return
me
.
data
[
input
.
Offset
:
end
],
OK
return
f
.
data
[
input
.
Offset
:
end
],
OK
}
////////////////
...
...
@@ -56,27 +56,27 @@ func NewDevNullFile() *DevNullFile {
return
new
(
DevNullFile
)
}
func
(
me
*
DevNullFile
)
String
()
string
{
func
(
f
*
DevNullFile
)
String
()
string
{
return
"DevNullFile"
}
func
(
me
*
DevNullFile
)
Read
(
input
*
ReadIn
,
bp
BufferPool
)
([]
byte
,
Status
)
{
func
(
f
*
DevNullFile
)
Read
(
input
*
ReadIn
,
bp
BufferPool
)
([]
byte
,
Status
)
{
return
[]
byte
{},
OK
}
func
(
me
*
DevNullFile
)
Write
(
input
*
WriteIn
,
content
[]
byte
)
(
uint32
,
Status
)
{
func
(
f
*
DevNullFile
)
Write
(
input
*
WriteIn
,
content
[]
byte
)
(
uint32
,
Status
)
{
return
uint32
(
len
(
content
)),
OK
}
func
(
me
*
DevNullFile
)
Flush
()
Status
{
func
(
f
*
DevNullFile
)
Flush
()
Status
{
return
OK
}
func
(
me
*
DevNullFile
)
Fsync
(
flags
int
)
(
code
Status
)
{
func
(
f
*
DevNullFile
)
Fsync
(
flags
int
)
(
code
Status
)
{
return
OK
}
func
(
me
*
DevNullFile
)
Truncate
(
size
uint64
)
(
code
Status
)
{
func
(
f
*
DevNullFile
)
Truncate
(
size
uint64
)
(
code
Status
)
{
return
OK
}
...
...
@@ -89,54 +89,54 @@ type LoopbackFile struct {
DefaultFile
}
func
(
me
*
LoopbackFile
)
String
()
string
{
return
fmt
.
Sprintf
(
"LoopbackFile(%s)"
,
me
.
File
.
Name
())
func
(
f
*
LoopbackFile
)
String
()
string
{
return
fmt
.
Sprintf
(
"LoopbackFile(%s)"
,
f
.
File
.
Name
())
}
func
(
me
*
LoopbackFile
)
Read
(
input
*
ReadIn
,
buffers
BufferPool
)
([]
byte
,
Status
)
{
func
(
f
*
LoopbackFile
)
Read
(
input
*
ReadIn
,
buffers
BufferPool
)
([]
byte
,
Status
)
{
slice
:=
buffers
.
AllocBuffer
(
input
.
Size
)
n
,
err
:=
me
.
File
.
ReadAt
(
slice
,
int64
(
input
.
Offset
))
n
,
err
:=
f
.
File
.
ReadAt
(
slice
,
int64
(
input
.
Offset
))
if
err
==
io
.
EOF
{
err
=
nil
}
return
slice
[
:
n
],
ToStatus
(
err
)
}
func
(
me
*
LoopbackFile
)
Write
(
input
*
WriteIn
,
data
[]
byte
)
(
uint32
,
Status
)
{
n
,
err
:=
me
.
File
.
WriteAt
(
data
,
int64
(
input
.
Offset
))
func
(
f
*
LoopbackFile
)
Write
(
input
*
WriteIn
,
data
[]
byte
)
(
uint32
,
Status
)
{
n
,
err
:=
f
.
File
.
WriteAt
(
data
,
int64
(
input
.
Offset
))
return
uint32
(
n
),
ToStatus
(
err
)
}
func
(
me
*
LoopbackFile
)
Release
()
{
me
.
File
.
Close
()
func
(
f
*
LoopbackFile
)
Release
()
{
f
.
File
.
Close
()
}
func
(
me
*
LoopbackFile
)
Flush
()
Status
{
func
(
f
*
LoopbackFile
)
Flush
()
Status
{
return
OK
}
func
(
me
*
LoopbackFile
)
Fsync
(
flags
int
)
(
code
Status
)
{
return
ToStatus
(
syscall
.
Fsync
(
int
(
me
.
File
.
Fd
())))
func
(
f
*
LoopbackFile
)
Fsync
(
flags
int
)
(
code
Status
)
{
return
ToStatus
(
syscall
.
Fsync
(
int
(
f
.
File
.
Fd
())))
}
func
(
me
*
LoopbackFile
)
Truncate
(
size
uint64
)
Status
{
return
ToStatus
(
syscall
.
Ftruncate
(
int
(
me
.
File
.
Fd
()),
int64
(
size
)))
func
(
f
*
LoopbackFile
)
Truncate
(
size
uint64
)
Status
{
return
ToStatus
(
syscall
.
Ftruncate
(
int
(
f
.
File
.
Fd
()),
int64
(
size
)))
}
// futimens missing from 6g runtime.
func
(
me
*
LoopbackFile
)
Chmod
(
mode
uint32
)
Status
{
return
ToStatus
(
me
.
File
.
Chmod
(
os
.
FileMode
(
mode
)))
func
(
f
*
LoopbackFile
)
Chmod
(
mode
uint32
)
Status
{
return
ToStatus
(
f
.
File
.
Chmod
(
os
.
FileMode
(
mode
)))
}
func
(
me
*
LoopbackFile
)
Chown
(
uid
uint32
,
gid
uint32
)
Status
{
return
ToStatus
(
me
.
File
.
Chown
(
int
(
uid
),
int
(
gid
)))
func
(
f
*
LoopbackFile
)
Chown
(
uid
uint32
,
gid
uint32
)
Status
{
return
ToStatus
(
f
.
File
.
Chown
(
int
(
uid
),
int
(
gid
)))
}
func
(
me
*
LoopbackFile
)
GetAttr
()
(
*
Attr
,
Status
)
{
func
(
f
*
LoopbackFile
)
GetAttr
()
(
*
Attr
,
Status
)
{
st
:=
syscall
.
Stat_t
{}
err
:=
syscall
.
Fstat
(
int
(
me
.
File
.
Fd
()),
&
st
)
err
:=
syscall
.
Fstat
(
int
(
f
.
File
.
Fd
()),
&
st
)
if
err
!=
nil
{
return
nil
,
ToStatus
(
err
)
}
...
...
@@ -152,26 +152,26 @@ type ReadOnlyFile struct {
File
}
func
(
me
*
ReadOnlyFile
)
String
()
string
{
return
fmt
.
Sprintf
(
"ReadOnlyFile(%s)"
,
me
.
File
.
String
())
func
(
f
*
ReadOnlyFile
)
String
()
string
{
return
fmt
.
Sprintf
(
"ReadOnlyFile(%s)"
,
f
.
File
.
String
())
}
func
(
me
*
ReadOnlyFile
)
Write
(
input
*
WriteIn
,
data
[]
byte
)
(
uint32
,
Status
)
{
func
(
f
*
ReadOnlyFile
)
Write
(
input
*
WriteIn
,
data
[]
byte
)
(
uint32
,
Status
)
{
return
0
,
EPERM
}
func
(
me
*
ReadOnlyFile
)
Fsync
(
flag
int
)
(
code
Status
)
{
func
(
f
*
ReadOnlyFile
)
Fsync
(
flag
int
)
(
code
Status
)
{
return
OK
}
func
(
me
*
ReadOnlyFile
)
Truncate
(
size
uint64
)
Status
{
func
(
f
*
ReadOnlyFile
)
Truncate
(
size
uint64
)
Status
{
return
EPERM
}
func
(
me
*
ReadOnlyFile
)
Chmod
(
mode
uint32
)
Status
{
func
(
f
*
ReadOnlyFile
)
Chmod
(
mode
uint32
)
Status
{
return
EPERM
}
func
(
me
*
ReadOnlyFile
)
Chown
(
uid
uint32
,
gid
uint32
)
Status
{
func
(
f
*
ReadOnlyFile
)
Chown
(
uid
uint32
,
gid
uint32
)
Status
{
return
EPERM
}
fuse/fsconnector.go
View file @
ce603372
...
...
@@ -53,36 +53,36 @@ func NewFileSystemOptions() *FileSystemOptions {
}
}
func
NewFileSystemConnector
(
nodeFs
NodeFileSystem
,
opts
*
FileSystemOptions
)
(
me
*
FileSystemConnector
)
{
me
=
new
(
FileSystemConnector
)
func
NewFileSystemConnector
(
nodeFs
NodeFileSystem
,
opts
*
FileSystemOptions
)
(
c
*
FileSystemConnector
)
{
c
=
new
(
FileSystemConnector
)
if
opts
==
nil
{
opts
=
NewFileSystemOptions
()
}
me
.
inodeMap
=
NewHandleMap
(
opts
.
PortableInodes
)
me
.
rootNode
=
newInode
(
true
,
nodeFs
.
Root
())
c
.
inodeMap
=
NewHandleMap
(
opts
.
PortableInodes
)
c
.
rootNode
=
newInode
(
true
,
nodeFs
.
Root
())
me
.
verify
()
me
.
MountRoot
(
nodeFs
,
opts
)
c
.
verify
()
c
.
MountRoot
(
nodeFs
,
opts
)
// FUSE does not issue a LOOKUP for 1 (obviously), but it does
// issue a forget. This lookupUpdate is to make the counts match.
me
.
lookupUpdate
(
me
.
rootNode
)
return
me
c
.
lookupUpdate
(
c
.
rootNode
)
return
c
}
func
(
me
*
FileSystemConnector
)
verify
()
{
func
(
c
*
FileSystemConnector
)
verify
()
{
if
!
paranoia
{
return
}
root
:=
me
.
rootNode
root
.
verify
(
me
.
rootNode
.
mountPoint
)
root
:=
c
.
rootNode
root
.
verify
(
c
.
rootNode
.
mountPoint
)
}
// Generate EntryOut and increase the lookup count for an inode.
func
(
me
*
FileSystemConnector
)
childLookup
(
fi
*
raw
.
Attr
,
fsi
FsNode
)
(
out
*
raw
.
EntryOut
)
{
func
(
c
*
FileSystemConnector
)
childLookup
(
fi
*
raw
.
Attr
,
fsi
FsNode
)
(
out
*
raw
.
EntryOut
)
{
n
:=
fsi
.
Inode
()
out
=
n
.
mount
.
attrToEntry
(
fi
)
out
.
Ino
=
me
.
lookupUpdate
(
n
)
out
.
Ino
=
c
.
lookupUpdate
(
n
)
out
.
NodeId
=
out
.
Ino
if
out
.
Nlink
==
0
{
// With Nlink == 0, newer kernels will refuse link
...
...
@@ -92,7 +92,7 @@ func (me *FileSystemConnector) childLookup(fi *raw.Attr, fsi FsNode) (out *raw.E
return
out
}
func
(
me
*
FileSystemConnector
)
findMount
(
parent
*
Inode
,
name
string
)
(
mount
*
fileSystemMount
)
{
func
(
c
*
FileSystemConnector
)
findMount
(
parent
*
Inode
,
name
string
)
(
mount
*
fileSystemMount
)
{
parent
.
treeLock
.
RLock
()
defer
parent
.
treeLock
.
RUnlock
()
if
parent
.
mounts
==
nil
{
...
...
@@ -102,61 +102,61 @@ func (me *FileSystemConnector) findMount(parent *Inode, name string) (mount *fil
return
parent
.
mounts
[
name
]
}
func
(
me
*
FileSystemConnector
)
toInode
(
nodeid
uint64
)
*
Inode
{
func
(
c
*
FileSystemConnector
)
toInode
(
nodeid
uint64
)
*
Inode
{
if
nodeid
==
raw
.
FUSE_ROOT_ID
{
return
me
.
rootNode
return
c
.
rootNode
}
i
:=
(
*
Inode
)(
unsafe
.
Pointer
(
me
.
inodeMap
.
Decode
(
nodeid
)))
i
:=
(
*
Inode
)(
unsafe
.
Pointer
(
c
.
inodeMap
.
Decode
(
nodeid
)))
return
i
}
// Must run outside treeLock. Returns the nodeId.
func
(
me
*
FileSystemConnector
)
lookupUpdate
(
node
*
Inode
)
uint64
{
func
(
c
*
FileSystemConnector
)
lookupUpdate
(
node
*
Inode
)
uint64
{
node
.
treeLock
.
Lock
()
defer
node
.
treeLock
.
Unlock
()
if
node
.
lookupCount
==
0
{
node
.
nodeId
=
me
.
inodeMap
.
Register
(
&
node
.
handled
,
node
)
node
.
nodeId
=
c
.
inodeMap
.
Register
(
&
node
.
handled
,
node
)
}
node
.
lookupCount
+=
1
return
node
.
nodeId
}
// Must run outside treeLock.
func
(
me
*
FileSystemConnector
)
forgetUpdate
(
node
*
Inode
,
forgetCount
int
)
{
defer
me
.
verify
()
func
(
c
*
FileSystemConnector
)
forgetUpdate
(
node
*
Inode
,
forgetCount
int
)
{
defer
c
.
verify
()
node
.
treeLock
.
Lock
()
defer
node
.
treeLock
.
Unlock
()
node
.
lookupCount
-=
forgetCount
if
node
.
lookupCount
==
0
{
me
.
inodeMap
.
Forget
(
node
.
nodeId
)
c
.
inodeMap
.
Forget
(
node
.
nodeId
)
node
.
nodeId
=
0
}
else
if
node
.
lookupCount
<
0
{
log
.
Panicf
(
"lookupCount underflow: %d: %v"
,
node
.
lookupCount
,
me
)
log
.
Panicf
(
"lookupCount underflow: %d: %v"
,
node
.
lookupCount
,
c
)
}
me
.
recursiveConsiderDropInode
(
node
)
c
.
recursiveConsiderDropInode
(
node
)
}
// InodeCount returns the number of inodes registered with the kernel.
func
(
me
*
FileSystemConnector
)
InodeHandleCount
()
int
{
return
me
.
inodeMap
.
Count
()
func
(
c
*
FileSystemConnector
)
InodeHandleCount
()
int
{
return
c
.
inodeMap
.
Count
()
}
func
(
me
*
FileSystemConnector
)
considerDropInode
(
node
*
Inode
)
{
func
(
c
*
FileSystemConnector
)
considerDropInode
(
node
*
Inode
)
{
node
.
treeLock
.
Lock
()
defer
node
.
treeLock
.
Unlock
()
me
.
recursiveConsiderDropInode
(
node
)
c
.
recursiveConsiderDropInode
(
node
)
}
// Must hold treeLock.
func
(
me
*
FileSystemConnector
)
recursiveConsiderDropInode
(
n
*
Inode
)
(
drop
bool
)
{
func
(
c
*
FileSystemConnector
)
recursiveConsiderDropInode
(
n
*
Inode
)
(
drop
bool
)
{
delChildren
:=
[]
string
{}
for
k
,
v
:=
range
n
.
children
{
// Only consider children from the same mount, or
// already unmounted mountpoints.
if
v
.
mountPoint
==
nil
&&
me
.
recursiveConsiderDropInode
(
v
)
{
if
v
.
mountPoint
==
nil
&&
c
.
recursiveConsiderDropInode
(
v
)
{
delChildren
=
append
(
delChildren
,
k
)
}
}
...
...
@@ -171,7 +171,7 @@ func (me *FileSystemConnector) recursiveConsiderDropInode(n *Inode) (drop bool)
if
len
(
n
.
children
)
>
0
||
n
.
lookupCount
>
0
||
!
n
.
FsNode
()
.
Deletable
()
{
return
false
}
if
n
==
me
.
rootNode
||
n
.
mountPoint
!=
nil
{
if
n
==
c
.
rootNode
||
n
.
mountPoint
!=
nil
{
return
false
}
...
...
@@ -183,9 +183,9 @@ func (me *FileSystemConnector) recursiveConsiderDropInode(n *Inode) (drop bool)
// Finds a node within the currently known inodes, returns the last
// known node and the remaining unknown path components. If parent is
// nil, start from FUSE mountpoint.
func
(
me
*
FileSystemConnector
)
Node
(
parent
*
Inode
,
fullPath
string
)
(
*
Inode
,
[]
string
)
{
func
(
c
*
FileSystemConnector
)
Node
(
parent
*
Inode
,
fullPath
string
)
(
*
Inode
,
[]
string
)
{
if
parent
==
nil
{
parent
=
me
.
rootNode
parent
=
c
.
rootNode
}
if
fullPath
==
""
{
return
parent
,
nil
...
...
@@ -221,13 +221,13 @@ func (me *FileSystemConnector) Node(parent *Inode, fullPath string) (*Inode, []s
return
node
,
nil
}
func
(
me
*
FileSystemConnector
)
LookupNode
(
parent
*
Inode
,
path
string
)
*
Inode
{
func
(
c
*
FileSystemConnector
)
LookupNode
(
parent
*
Inode
,
path
string
)
*
Inode
{
if
path
==
""
{
return
parent
}
components
:=
strings
.
Split
(
path
,
"/"
)
for
_
,
r
:=
range
components
{
_
,
child
,
_
:=
me
.
internalLookup
(
parent
,
r
,
nil
)
_
,
child
,
_
:=
c
.
internalLookup
(
parent
,
r
,
nil
)
if
child
==
nil
{
return
nil
}
...
...
@@ -240,11 +240,11 @@ func (me *FileSystemConnector) LookupNode(parent *Inode, path string) *Inode {
////////////////////////////////////////////////////////////////
func
(
me
*
FileSystemConnector
)
MountRoot
(
nodeFs
NodeFileSystem
,
opts
*
FileSystemOptions
)
{
me
.
rootNode
.
mountFs
(
nodeFs
,
opts
)
me
.
rootNode
.
mount
.
connector
=
me
nodeFs
.
OnMount
(
me
)
me
.
verify
()
func
(
c
*
FileSystemConnector
)
MountRoot
(
nodeFs
NodeFileSystem
,
opts
*
FileSystemOptions
)
{
c
.
rootNode
.
mountFs
(
nodeFs
,
opts
)
c
.
rootNode
.
mount
.
connector
=
c
nodeFs
.
OnMount
(
c
)
c
.
verify
()
}
// Mount() generates a synthetic directory node, and mounts the file
...
...
@@ -258,7 +258,7 @@ func (me *FileSystemConnector) MountRoot(nodeFs NodeFileSystem, opts *FileSystem
// ENOENT: the directory containing the mount point does not exist.
//
// EBUSY: the intended mount point already exists.
func
(
me
*
FileSystemConnector
)
Mount
(
parent
*
Inode
,
name
string
,
nodeFs
NodeFileSystem
,
opts
*
FileSystemOptions
)
Status
{
func
(
c
*
FileSystemConnector
)
Mount
(
parent
*
Inode
,
name
string
,
nodeFs
NodeFileSystem
,
opts
*
FileSystemOptions
)
Status
{
parent
.
treeLock
.
Lock
()
defer
parent
.
treeLock
.
Unlock
()
node
:=
parent
.
children
[
name
]
...
...
@@ -268,11 +268,11 @@ func (me *FileSystemConnector) Mount(parent *Inode, name string, nodeFs NodeFile
node
=
newInode
(
true
,
nodeFs
.
Root
())
if
opts
==
nil
{
opts
=
me
.
rootNode
.
mountPoint
.
options
opts
=
c
.
rootNode
.
mountPoint
.
options
}
node
.
mountFs
(
nodeFs
,
opts
)
node
.
mount
.
connector
=
me
node
.
mount
.
connector
=
c
parent
.
addChild
(
name
,
node
)
if
parent
.
mounts
==
nil
{
...
...
@@ -280,12 +280,12 @@ func (me *FileSystemConnector) Mount(parent *Inode, name string, nodeFs NodeFile
}
parent
.
mounts
[
name
]
=
node
.
mountPoint
node
.
mountPoint
.
parentInode
=
parent
if
me
.
Debug
{
if
c
.
Debug
{
log
.
Println
(
"Mount: "
,
nodeFs
,
"on subdir"
,
name
,
"parent"
,
parent
.
nodeId
)
}
me
.
verify
()
nodeFs
.
OnMount
(
me
)
c
.
verify
()
nodeFs
.
OnMount
(
c
)
return
OK
}
...
...
@@ -296,7 +296,7 @@ func (me *FileSystemConnector) Mount(parent *Inode, name string, nodeFs NodeFile
// EINVAL: path does not exist, or is not a mount point.
//
// EBUSY: there are open files, or submounts below this node.
func
(
me
*
FileSystemConnector
)
Unmount
(
node
*
Inode
)
Status
{
func
(
c
*
FileSystemConnector
)
Unmount
(
node
*
Inode
)
Status
{
if
node
.
mountPoint
==
nil
{
log
.
Println
(
"not a mountpoint:"
,
node
.
nodeId
)
return
EINVAL
...
...
@@ -325,14 +325,14 @@ func (me *FileSystemConnector) Unmount(node *Inode) Status {
delete
(
parentNode
.
children
,
name
)
mount
.
fs
.
OnUnmount
()
me
.
EntryNotify
(
parentNode
,
name
)
c
.
EntryNotify
(
parentNode
,
name
)
return
OK
}
func
(
me
*
FileSystemConnector
)
FileNotify
(
node
*
Inode
,
off
int64
,
length
int64
)
Status
{
func
(
c
*
FileSystemConnector
)
FileNotify
(
node
*
Inode
,
off
int64
,
length
int64
)
Status
{
n
:=
node
.
nodeId
if
node
==
me
.
rootNode
{
if
node
==
c
.
rootNode
{
n
=
raw
.
FUSE_ROOT_ID
}
if
n
==
0
{
...
...
@@ -343,16 +343,16 @@ func (me *FileSystemConnector) FileNotify(node *Inode, off int64, length int64)
Off
:
off
,
Ino
:
n
,
}
return
me
.
fsInit
.
InodeNotify
(
&
out
)
return
c
.
fsInit
.
InodeNotify
(
&
out
)
}
func
(
me
*
FileSystemConnector
)
EntryNotify
(
dir
*
Inode
,
name
string
)
Status
{
func
(
c
*
FileSystemConnector
)
EntryNotify
(
dir
*
Inode
,
name
string
)
Status
{
n
:=
dir
.
nodeId
if
dir
==
me
.
rootNode
{
if
dir
==
c
.
rootNode
{
n
=
raw
.
FUSE_ROOT_ID
}
if
n
==
0
{
return
OK
}
return
me
.
fsInit
.
EntryNotify
(
n
,
name
)
return
c
.
fsInit
.
EntryNotify
(
n
,
name
)
}
fuse/fsetattr_test.go
View file @
ce603372
...
...
@@ -18,62 +18,62 @@ type MutableDataFile struct {
GetAttrCalled
bool
}
func
(
me
*
MutableDataFile
)
String
()
string
{
func
(
f
*
MutableDataFile
)
String
()
string
{
return
"MutableDataFile"
}
func
(
me
*
MutableDataFile
)
Read
(
r
*
ReadIn
,
bp
BufferPool
)
([]
byte
,
Status
)
{
return
me
.
data
[
r
.
Offset
:
r
.
Offset
+
uint64
(
r
.
Size
)],
OK
func
(
f
*
MutableDataFile
)
Read
(
r
*
ReadIn
,
bp
BufferPool
)
([]
byte
,
Status
)
{
return
f
.
data
[
r
.
Offset
:
r
.
Offset
+
uint64
(
r
.
Size
)],
OK
}
func
(
me
*
MutableDataFile
)
Write
(
w
*
WriteIn
,
d
[]
byte
)
(
uint32
,
Status
)
{
func
(
f
*
MutableDataFile
)
Write
(
w
*
WriteIn
,
d
[]
byte
)
(
uint32
,
Status
)
{
end
:=
uint64
(
w
.
Size
)
+
w
.
Offset
if
int
(
end
)
>
len
(
me
.
data
)
{
data
:=
make
([]
byte
,
len
(
me
.
data
),
end
)
copy
(
data
,
me
.
data
)
me
.
data
=
data
if
int
(
end
)
>
len
(
f
.
data
)
{
data
:=
make
([]
byte
,
len
(
f
.
data
),
end
)
copy
(
data
,
f
.
data
)
f
.
data
=
data
}
copy
(
me
.
data
[
w
.
Offset
:
end
],
d
)
copy
(
f
.
data
[
w
.
Offset
:
end
],
d
)
return
w
.
Size
,
OK
}
func
(
me
*
MutableDataFile
)
Flush
()
Status
{
func
(
f
*
MutableDataFile
)
Flush
()
Status
{
return
OK
}
func
(
me
*
MutableDataFile
)
Release
()
{
func
(
f
*
MutableDataFile
)
Release
()
{
}
func
(
me
*
MutableDataFile
)
getAttr
()
*
Attr
{
f
:=
me
.
Attr
f
.
Size
=
uint64
(
len
(
me
.
data
))
return
&
f
func
(
f
*
MutableDataFile
)
getAttr
()
*
Attr
{
a
:=
f
.
Attr
a
.
Size
=
uint64
(
len
(
f
.
data
))
return
&
a
}
func
(
me
*
MutableDataFile
)
GetAttr
()
(
*
Attr
,
Status
)
{
me
.
GetAttrCalled
=
true
return
me
.
getAttr
(),
OK
func
(
f
*
MutableDataFile
)
GetAttr
()
(
*
Attr
,
Status
)
{
f
.
GetAttrCalled
=
true
return
f
.
getAttr
(),
OK
}
func
(
me
*
MutableDataFile
)
Utimens
(
atimeNs
int64
,
mtimeNs
int64
)
Status
{
me
.
Attr
.
SetNs
(
atimeNs
,
mtimeNs
,
-
1
)
func
(
f
*
MutableDataFile
)
Utimens
(
atimeNs
int64
,
mtimeNs
int64
)
Status
{
f
.
Attr
.
SetNs
(
atimeNs
,
mtimeNs
,
-
1
)
return
OK
}
func
(
me
*
MutableDataFile
)
Truncate
(
size
uint64
)
Status
{
me
.
data
=
me
.
data
[
:
size
]
func
(
f
*
MutableDataFile
)
Truncate
(
size
uint64
)
Status
{
f
.
data
=
f
.
data
[
:
size
]
return
OK
}
func
(
me
*
MutableDataFile
)
Chown
(
uid
uint32
,
gid
uint32
)
Status
{
me
.
Attr
.
Uid
=
uid
me
.
Attr
.
Gid
=
gid
func
(
f
*
MutableDataFile
)
Chown
(
uid
uint32
,
gid
uint32
)
Status
{
f
.
Attr
.
Uid
=
uid
f
.
Attr
.
Gid
=
gid
return
OK
}
func
(
me
*
MutableDataFile
)
Chmod
(
perms
uint32
)
Status
{
me
.
Attr
.
Mode
=
(
me
.
Attr
.
Mode
&^
07777
)
|
perms
func
(
f
*
MutableDataFile
)
Chmod
(
perms
uint32
)
Status
{
f
.
Attr
.
Mode
=
(
f
.
Attr
.
Mode
&^
07777
)
|
perms
return
OK
}
...
...
@@ -84,34 +84,34 @@ type FSetAttrFs struct {
file
*
MutableDataFile
}
func
(
me
*
FSetAttrFs
)
GetXAttr
(
name
string
,
attr
string
,
context
*
Context
)
([]
byte
,
Status
)
{
func
(
fs
*
FSetAttrFs
)
GetXAttr
(
name
string
,
attr
string
,
context
*
Context
)
([]
byte
,
Status
)
{
return
nil
,
ENODATA
}
func
(
me
*
FSetAttrFs
)
GetAttr
(
name
string
,
context
*
Context
)
(
*
Attr
,
Status
)
{
func
(
fs
*
FSetAttrFs
)
GetAttr
(
name
string
,
context
*
Context
)
(
*
Attr
,
Status
)
{
if
name
==
""
{
return
&
Attr
{
Mode
:
S_IFDIR
|
0700
},
OK
}
if
name
==
"file"
&&
me
.
file
!=
nil
{
a
:=
me
.
file
.
getAttr
()
if
name
==
"file"
&&
fs
.
file
!=
nil
{
a
:=
fs
.
file
.
getAttr
()
a
.
Mode
|=
S_IFREG
return
a
,
OK
}
return
nil
,
ENOENT
}
func
(
me
*
FSetAttrFs
)
Open
(
name
string
,
flags
uint32
,
context
*
Context
)
(
File
,
Status
)
{
func
(
fs
*
FSetAttrFs
)
Open
(
name
string
,
flags
uint32
,
context
*
Context
)
(
File
,
Status
)
{
if
name
==
"file"
{
return
me
.
file
,
OK
return
fs
.
file
,
OK
}
return
nil
,
ENOENT
}
func
(
me
*
FSetAttrFs
)
Create
(
name
string
,
flags
uint32
,
mode
uint32
,
context
*
Context
)
(
File
,
Status
)
{
func
(
fs
*
FSetAttrFs
)
Create
(
name
string
,
flags
uint32
,
mode
uint32
,
context
*
Context
)
(
File
,
Status
)
{
if
name
==
"file"
{
f
:=
NewFile
()
me
.
file
=
f
me
.
file
.
Attr
.
Mode
=
mode
fs
.
file
=
f
fs
.
file
.
Attr
.
Mode
=
mode
return
f
,
OK
}
return
nil
,
ENOENT
...
...
fuse/fsmount.go
View file @
ce603372
...
...
@@ -45,9 +45,9 @@ type fileSystemMount struct {
}
// Must called with lock for parent held.
func
(
m
e
*
fileSystemMount
)
mountName
()
string
{
for
k
,
v
:=
range
m
e
.
parentInode
.
mounts
{
if
m
e
==
v
{
func
(
m
*
fileSystemMount
)
mountName
()
string
{
for
k
,
v
:=
range
m
.
parentInode
.
mounts
{
if
m
==
v
{
return
k
}
}
...
...
@@ -55,44 +55,44 @@ func (me *fileSystemMount) mountName() string {
return
""
}
func
(
m
e
*
fileSystemMount
)
setOwner
(
attr
*
raw
.
Attr
)
{
if
m
e
.
options
.
Owner
!=
nil
{
attr
.
Owner
=
*
(
*
raw
.
Owner
)(
m
e
.
options
.
Owner
)
func
(
m
*
fileSystemMount
)
setOwner
(
attr
*
raw
.
Attr
)
{
if
m
.
options
.
Owner
!=
nil
{
attr
.
Owner
=
*
(
*
raw
.
Owner
)(
m
.
options
.
Owner
)
}
}
func
(
m
e
*
fileSystemMount
)
attrToEntry
(
attr
*
raw
.
Attr
)
(
out
*
raw
.
EntryOut
)
{
func
(
m
*
fileSystemMount
)
attrToEntry
(
attr
*
raw
.
Attr
)
(
out
*
raw
.
EntryOut
)
{
out
=
&
raw
.
EntryOut
{}
out
.
Attr
=
*
attr
splitDuration
(
m
e
.
options
.
EntryTimeout
,
&
out
.
EntryValid
,
&
out
.
EntryValidNsec
)
splitDuration
(
m
e
.
options
.
AttrTimeout
,
&
out
.
AttrValid
,
&
out
.
AttrValidNsec
)
m
e
.
setOwner
(
&
out
.
Attr
)
splitDuration
(
m
.
options
.
EntryTimeout
,
&
out
.
EntryValid
,
&
out
.
EntryValidNsec
)
splitDuration
(
m
.
options
.
AttrTimeout
,
&
out
.
AttrValid
,
&
out
.
AttrValidNsec
)
m
.
setOwner
(
&
out
.
Attr
)
if
attr
.
Mode
&
S_IFDIR
==
0
&&
attr
.
Nlink
==
0
{
out
.
Nlink
=
1
}
return
out
}
func
(
m
e
*
fileSystemMount
)
fillAttr
(
a
*
raw
.
Attr
,
nodeId
uint64
)
(
out
*
raw
.
AttrOut
)
{
func
(
m
*
fileSystemMount
)
fillAttr
(
a
*
raw
.
Attr
,
nodeId
uint64
)
(
out
*
raw
.
AttrOut
)
{
out
=
&
raw
.
AttrOut
{}
out
.
Attr
=
*
a
splitDuration
(
m
e
.
options
.
AttrTimeout
,
&
out
.
AttrValid
,
&
out
.
AttrValidNsec
)
m
e
.
setOwner
(
&
out
.
Attr
)
splitDuration
(
m
.
options
.
AttrTimeout
,
&
out
.
AttrValid
,
&
out
.
AttrValidNsec
)
m
.
setOwner
(
&
out
.
Attr
)
out
.
Ino
=
nodeId
return
out
}
func
(
m
e
*
fileSystemMount
)
getOpenedFile
(
h
uint64
)
*
openedFile
{
b
:=
(
*
openedFile
)(
unsafe
.
Pointer
(
m
e
.
openFiles
.
Decode
(
h
)))
if
m
e
.
connector
.
Debug
&&
b
.
WithFlags
.
Description
!=
""
{
func
(
m
*
fileSystemMount
)
getOpenedFile
(
h
uint64
)
*
openedFile
{
b
:=
(
*
openedFile
)(
unsafe
.
Pointer
(
m
.
openFiles
.
Decode
(
h
)))
if
m
.
connector
.
Debug
&&
b
.
WithFlags
.
Description
!=
""
{
log
.
Printf
(
"File %d = %q"
,
h
,
b
.
WithFlags
.
Description
)
}
return
b
}
func
(
m
e
*
fileSystemMount
)
unregisterFileHandle
(
handle
uint64
,
node
*
Inode
)
*
openedFile
{
obj
:=
m
e
.
openFiles
.
Forget
(
handle
)
func
(
m
*
fileSystemMount
)
unregisterFileHandle
(
handle
uint64
,
node
*
Inode
)
*
openedFile
{
obj
:=
m
.
openFiles
.
Forget
(
handle
)
opened
:=
(
*
openedFile
)(
unsafe
.
Pointer
(
obj
))
node
.
openFilesMutex
.
Lock
()
defer
node
.
openFilesMutex
.
Unlock
()
...
...
@@ -112,7 +112,7 @@ func (me *fileSystemMount) unregisterFileHandle(handle uint64, node *Inode) *ope
return
opened
}
func
(
m
e
*
fileSystemMount
)
registerFileHandle
(
node
*
Inode
,
dir
rawDir
,
f
File
,
flags
uint32
)
(
uint64
,
*
openedFile
)
{
func
(
m
*
fileSystemMount
)
registerFileHandle
(
node
*
Inode
,
dir
rawDir
,
f
File
,
flags
uint32
)
(
uint64
,
*
openedFile
)
{
node
.
openFilesMutex
.
Lock
()
defer
node
.
openFilesMutex
.
Unlock
()
b
:=
&
openedFile
{
...
...
@@ -139,16 +139,16 @@ func (me *fileSystemMount) registerFileHandle(node *Inode, dir rawDir, f File, f
b
.
WithFlags
.
File
.
SetInode
(
node
)
}
node
.
openFiles
=
append
(
node
.
openFiles
,
b
)
handle
:=
m
e
.
openFiles
.
Register
(
&
b
.
Handled
,
b
)
handle
:=
m
.
openFiles
.
Register
(
&
b
.
Handled
,
b
)
return
handle
,
b
}
// Creates a return entry for a non-existent path.
func
(
m
e
*
fileSystemMount
)
negativeEntry
()
(
*
raw
.
EntryOut
,
Status
)
{
if
m
e
.
options
.
NegativeTimeout
>
0.0
{
func
(
m
*
fileSystemMount
)
negativeEntry
()
(
*
raw
.
EntryOut
,
Status
)
{
if
m
.
options
.
NegativeTimeout
>
0.0
{
out
:=
new
(
raw
.
EntryOut
)
out
.
NodeId
=
0
splitDuration
(
m
e
.
options
.
NegativeTimeout
,
&
out
.
EntryValid
,
&
out
.
EntryValidNsec
)
splitDuration
(
m
.
options
.
NegativeTimeout
,
&
out
.
EntryValid
,
&
out
.
EntryValidNsec
)
return
out
,
OK
}
return
nil
,
ENOENT
...
...
fuse/fsops.go
View file @
ce603372
...
...
@@ -12,11 +12,11 @@ import (
var
_
=
log
.
Println
func
(
me
*
FileSystemConnector
)
Init
(
fsInit
*
RawFsInit
)
{
me
.
fsInit
=
*
fsInit
func
(
c
*
FileSystemConnector
)
Init
(
fsInit
*
RawFsInit
)
{
c
.
fsInit
=
*
fsInit
}
func
(
me
*
FileSystemConnector
)
lookupMountUpdate
(
mount
*
fileSystemMount
)
(
fi
*
Attr
,
node
*
Inode
,
code
Status
)
{
func
(
c
*
FileSystemConnector
)
lookupMountUpdate
(
mount
*
fileSystemMount
)
(
fi
*
Attr
,
node
*
Inode
,
code
Status
)
{
fi
,
code
=
mount
.
fs
.
Root
()
.
GetAttr
(
nil
,
nil
)
if
!
code
.
Ok
()
{
log
.
Println
(
"Root getattr should not return error"
,
code
)
...
...
@@ -26,9 +26,9 @@ func (me *FileSystemConnector) lookupMountUpdate(mount *fileSystemMount) (fi *At
return
fi
,
mount
.
mountInode
,
OK
}
func
(
me
*
FileSystemConnector
)
internalLookup
(
parent
*
Inode
,
name
string
,
context
*
Context
)
(
fi
*
Attr
,
node
*
Inode
,
code
Status
)
{
if
subMount
:=
me
.
findMount
(
parent
,
name
);
subMount
!=
nil
{
return
me
.
lookupMountUpdate
(
subMount
)
func
(
c
*
FileSystemConnector
)
internalLookup
(
parent
*
Inode
,
name
string
,
context
*
Context
)
(
fi
*
Attr
,
node
*
Inode
,
code
Status
)
{
if
subMount
:=
c
.
findMount
(
parent
,
name
);
subMount
!=
nil
{
return
c
.
lookupMountUpdate
(
subMount
)
}
child
:=
parent
.
GetChild
(
name
)
...
...
@@ -53,14 +53,14 @@ func (me *FileSystemConnector) internalLookup(parent *Inode, name string, contex
return
fi
,
child
,
code
}
func
(
me
*
FileSystemConnector
)
Lookup
(
header
*
raw
.
InHeader
,
name
string
)
(
out
*
raw
.
EntryOut
,
code
Status
)
{
parent
:=
me
.
toInode
(
header
.
NodeId
)
func
(
c
*
FileSystemConnector
)
Lookup
(
header
*
raw
.
InHeader
,
name
string
)
(
out
*
raw
.
EntryOut
,
code
Status
)
{
parent
:=
c
.
toInode
(
header
.
NodeId
)
if
!
parent
.
IsDir
()
{
log
.
Printf
(
"Lookup %q called on non-Directory node %d"
,
name
,
header
.
NodeId
)
return
nil
,
ENOTDIR
}
context
:=
(
*
Context
)(
&
header
.
Context
)
fi
,
child
,
code
:=
me
.
internalLookup
(
parent
,
name
,
context
)
fi
,
child
,
code
:=
c
.
internalLookup
(
parent
,
name
,
context
)
if
!
code
.
Ok
()
{
if
code
==
ENOENT
{
return
parent
.
mount
.
negativeEntry
()
...
...
@@ -73,20 +73,20 @@ func (me *FileSystemConnector) Lookup(header *raw.InHeader, name string) (out *r
rawAttr
:=
(
*
raw
.
Attr
)(
fi
)
out
=
child
.
mount
.
attrToEntry
(
rawAttr
)
out
.
NodeId
=
me
.
lookupUpdate
(
child
)
out
.
NodeId
=
c
.
lookupUpdate
(
child
)
out
.
Generation
=
1
out
.
Ino
=
out
.
NodeId
return
out
,
OK
}
func
(
me
*
FileSystemConnector
)
Forget
(
nodeID
,
nlookup
uint64
)
{
node
:=
me
.
toInode
(
nodeID
)
me
.
forgetUpdate
(
node
,
int
(
nlookup
))
func
(
c
*
FileSystemConnector
)
Forget
(
nodeID
,
nlookup
uint64
)
{
node
:=
c
.
toInode
(
nodeID
)
c
.
forgetUpdate
(
node
,
int
(
nlookup
))
}
func
(
me
*
FileSystemConnector
)
GetAttr
(
header
*
raw
.
InHeader
,
input
*
raw
.
GetAttrIn
)
(
out
*
raw
.
AttrOut
,
code
Status
)
{
node
:=
me
.
toInode
(
header
.
NodeId
)
func
(
c
*
FileSystemConnector
)
GetAttr
(
header
*
raw
.
InHeader
,
input
*
raw
.
GetAttrIn
)
(
out
*
raw
.
AttrOut
,
code
Status
)
{
node
:=
c
.
toInode
(
header
.
NodeId
)
var
f
File
if
input
.
Flags
&
raw
.
FUSE_GETATTR_FH
!=
0
{
...
...
@@ -105,8 +105,8 @@ func (me *FileSystemConnector) GetAttr(header *raw.InHeader, input *raw.GetAttrI
return
out
,
OK
}
func
(
me
*
FileSystemConnector
)
OpenDir
(
header
*
raw
.
InHeader
,
input
*
raw
.
OpenIn
)
(
flags
uint32
,
handle
uint64
,
code
Status
)
{
node
:=
me
.
toInode
(
header
.
NodeId
)
func
(
c
*
FileSystemConnector
)
OpenDir
(
header
*
raw
.
InHeader
,
input
*
raw
.
OpenIn
)
(
flags
uint32
,
handle
uint64
,
code
Status
)
{
node
:=
c
.
toInode
(
header
.
NodeId
)
stream
,
err
:=
node
.
fsInode
.
OpenDir
((
*
Context
)(
&
header
.
Context
))
if
err
!=
OK
{
return
0
,
0
,
err
...
...
@@ -124,8 +124,8 @@ func (me *FileSystemConnector) OpenDir(header *raw.InHeader, input *raw.OpenIn)
return
opened
.
FuseFlags
,
h
,
OK
}
func
(
me
*
FileSystemConnector
)
ReadDir
(
header
*
raw
.
InHeader
,
input
*
ReadIn
)
(
*
DirEntryList
,
Status
)
{
node
:=
me
.
toInode
(
header
.
NodeId
)
func
(
c
*
FileSystemConnector
)
ReadDir
(
header
*
raw
.
InHeader
,
input
*
ReadIn
)
(
*
DirEntryList
,
Status
)
{
node
:=
c
.
toInode
(
header
.
NodeId
)
opened
:=
node
.
mount
.
getOpenedFile
(
input
.
Fh
)
de
,
code
:=
opened
.
dir
.
ReadDir
(
input
)
if
code
!=
OK
{
...
...
@@ -134,8 +134,8 @@ func (me *FileSystemConnector) ReadDir(header *raw.InHeader, input *ReadIn) (*Di
return
de
,
OK
}
func
(
me
*
FileSystemConnector
)
Open
(
header
*
raw
.
InHeader
,
input
*
raw
.
OpenIn
)
(
flags
uint32
,
handle
uint64
,
status
Status
)
{
node
:=
me
.
toInode
(
header
.
NodeId
)
func
(
c
*
FileSystemConnector
)
Open
(
header
*
raw
.
InHeader
,
input
*
raw
.
OpenIn
)
(
flags
uint32
,
handle
uint64
,
status
Status
)
{
node
:=
c
.
toInode
(
header
.
NodeId
)
f
,
code
:=
node
.
fsInode
.
Open
(
input
.
Flags
,
(
*
Context
)(
&
header
.
Context
))
if
!
code
.
Ok
()
{
return
0
,
0
,
code
...
...
@@ -144,8 +144,8 @@ func (me *FileSystemConnector) Open(header *raw.InHeader, input *raw.OpenIn) (fl
return
opened
.
FuseFlags
,
h
,
OK
}
func
(
me
*
FileSystemConnector
)
SetAttr
(
header
*
raw
.
InHeader
,
input
*
raw
.
SetAttrIn
)
(
out
*
raw
.
AttrOut
,
code
Status
)
{
node
:=
me
.
toInode
(
header
.
NodeId
)
func
(
c
*
FileSystemConnector
)
SetAttr
(
header
*
raw
.
InHeader
,
input
*
raw
.
SetAttrIn
)
(
out
*
raw
.
AttrOut
,
code
Status
)
{
node
:=
c
.
toInode
(
header
.
NodeId
)
var
f
File
if
input
.
Valid
&
raw
.
FATTR_FH
!=
0
{
opened
:=
node
.
mount
.
getOpenedFile
(
input
.
Fh
)
...
...
@@ -196,60 +196,60 @@ func (me *FileSystemConnector) SetAttr(header *raw.InHeader, input *raw.SetAttrI
return
out
,
code
}
func
(
me
*
FileSystemConnector
)
Readlink
(
header
*
raw
.
InHeader
)
(
out
[]
byte
,
code
Status
)
{
n
:=
me
.
toInode
(
header
.
NodeId
)
func
(
c
*
FileSystemConnector
)
Readlink
(
header
*
raw
.
InHeader
)
(
out
[]
byte
,
code
Status
)
{
n
:=
c
.
toInode
(
header
.
NodeId
)
return
n
.
fsInode
.
Readlink
((
*
Context
)(
&
header
.
Context
))
}
func
(
me
*
FileSystemConnector
)
Mknod
(
header
*
raw
.
InHeader
,
input
*
raw
.
MknodIn
,
name
string
)
(
out
*
raw
.
EntryOut
,
code
Status
)
{
parent
:=
me
.
toInode
(
header
.
NodeId
)
func
(
c
*
FileSystemConnector
)
Mknod
(
header
*
raw
.
InHeader
,
input
*
raw
.
MknodIn
,
name
string
)
(
out
*
raw
.
EntryOut
,
code
Status
)
{
parent
:=
c
.
toInode
(
header
.
NodeId
)
fi
,
fsNode
,
code
:=
parent
.
fsInode
.
Mknod
(
name
,
input
.
Mode
,
uint32
(
input
.
Rdev
),
(
*
Context
)(
&
header
.
Context
))
rawAttr
:=
(
*
raw
.
Attr
)(
fi
)
if
code
.
Ok
()
{
out
=
me
.
childLookup
(
rawAttr
,
fsNode
)
out
=
c
.
childLookup
(
rawAttr
,
fsNode
)
}
return
out
,
code
}
func
(
me
*
FileSystemConnector
)
Mkdir
(
header
*
raw
.
InHeader
,
input
*
raw
.
MkdirIn
,
name
string
)
(
out
*
raw
.
EntryOut
,
code
Status
)
{
parent
:=
me
.
toInode
(
header
.
NodeId
)
func
(
c
*
FileSystemConnector
)
Mkdir
(
header
*
raw
.
InHeader
,
input
*
raw
.
MkdirIn
,
name
string
)
(
out
*
raw
.
EntryOut
,
code
Status
)
{
parent
:=
c
.
toInode
(
header
.
NodeId
)
fi
,
fsInode
,
code
:=
parent
.
fsInode
.
Mkdir
(
name
,
input
.
Mode
,
(
*
Context
)(
&
header
.
Context
))
if
code
.
Ok
()
{
rawAttr
:=
(
*
raw
.
Attr
)(
fi
)
out
=
me
.
childLookup
(
rawAttr
,
fsInode
)
out
=
c
.
childLookup
(
rawAttr
,
fsInode
)
}
return
out
,
code
}
func
(
me
*
FileSystemConnector
)
Unlink
(
header
*
raw
.
InHeader
,
name
string
)
(
code
Status
)
{
parent
:=
me
.
toInode
(
header
.
NodeId
)
func
(
c
*
FileSystemConnector
)
Unlink
(
header
*
raw
.
InHeader
,
name
string
)
(
code
Status
)
{
parent
:=
c
.
toInode
(
header
.
NodeId
)
return
parent
.
fsInode
.
Unlink
(
name
,
(
*
Context
)(
&
header
.
Context
))
}
func
(
me
*
FileSystemConnector
)
Rmdir
(
header
*
raw
.
InHeader
,
name
string
)
(
code
Status
)
{
parent
:=
me
.
toInode
(
header
.
NodeId
)
func
(
c
*
FileSystemConnector
)
Rmdir
(
header
*
raw
.
InHeader
,
name
string
)
(
code
Status
)
{
parent
:=
c
.
toInode
(
header
.
NodeId
)
return
parent
.
fsInode
.
Rmdir
(
name
,
(
*
Context
)(
&
header
.
Context
))
}
func
(
me
*
FileSystemConnector
)
Symlink
(
header
*
raw
.
InHeader
,
pointedTo
string
,
linkName
string
)
(
out
*
raw
.
EntryOut
,
code
Status
)
{
parent
:=
me
.
toInode
(
header
.
NodeId
)
func
(
c
*
FileSystemConnector
)
Symlink
(
header
*
raw
.
InHeader
,
pointedTo
string
,
linkName
string
)
(
out
*
raw
.
EntryOut
,
code
Status
)
{
parent
:=
c
.
toInode
(
header
.
NodeId
)
fi
,
fsNode
,
code
:=
parent
.
fsInode
.
Symlink
(
linkName
,
pointedTo
,
(
*
Context
)(
&
header
.
Context
))
if
code
.
Ok
()
{
rawAttr
:=
(
*
raw
.
Attr
)(
fi
)
out
=
me
.
childLookup
(
rawAttr
,
fsNode
)
out
=
c
.
childLookup
(
rawAttr
,
fsNode
)
}
return
out
,
code
}
func
(
me
*
FileSystemConnector
)
Rename
(
header
*
raw
.
InHeader
,
input
*
raw
.
RenameIn
,
oldName
string
,
newName
string
)
(
code
Status
)
{
oldParent
:=
me
.
toInode
(
header
.
NodeId
)
isMountPoint
:=
me
.
findMount
(
oldParent
,
oldName
)
!=
nil
func
(
c
*
FileSystemConnector
)
Rename
(
header
*
raw
.
InHeader
,
input
*
raw
.
RenameIn
,
oldName
string
,
newName
string
)
(
code
Status
)
{
oldParent
:=
c
.
toInode
(
header
.
NodeId
)
isMountPoint
:=
c
.
findMount
(
oldParent
,
oldName
)
!=
nil
if
isMountPoint
{
return
EBUSY
}
newParent
:=
me
.
toInode
(
input
.
Newdir
)
newParent
:=
c
.
toInode
(
input
.
Newdir
)
if
oldParent
.
mount
!=
newParent
.
mount
{
return
EXDEV
}
...
...
@@ -257,9 +257,9 @@ func (me *FileSystemConnector) Rename(header *raw.InHeader, input *raw.RenameIn,
return
oldParent
.
fsInode
.
Rename
(
oldName
,
newParent
.
fsInode
,
newName
,
(
*
Context
)(
&
header
.
Context
))
}
func
(
me
*
FileSystemConnector
)
Link
(
header
*
raw
.
InHeader
,
input
*
raw
.
LinkIn
,
name
string
)
(
out
*
raw
.
EntryOut
,
code
Status
)
{
existing
:=
me
.
toInode
(
input
.
Oldnodeid
)
parent
:=
me
.
toInode
(
header
.
NodeId
)
func
(
c
*
FileSystemConnector
)
Link
(
header
*
raw
.
InHeader
,
input
*
raw
.
LinkIn
,
name
string
)
(
out
*
raw
.
EntryOut
,
code
Status
)
{
existing
:=
c
.
toInode
(
input
.
Oldnodeid
)
parent
:=
c
.
toInode
(
header
.
NodeId
)
if
existing
.
mount
!=
parent
.
mount
{
return
nil
,
EXDEV
...
...
@@ -268,65 +268,65 @@ func (me *FileSystemConnector) Link(header *raw.InHeader, input *raw.LinkIn, nam
fi
,
fsInode
,
code
:=
parent
.
fsInode
.
Link
(
name
,
existing
.
fsInode
,
(
*
Context
)(
&
header
.
Context
))
if
code
.
Ok
()
{
rawAttr
:=
(
*
raw
.
Attr
)(
fi
)
out
=
me
.
childLookup
(
rawAttr
,
fsInode
)
out
=
c
.
childLookup
(
rawAttr
,
fsInode
)
}
return
out
,
code
}
func
(
me
*
FileSystemConnector
)
Access
(
header
*
raw
.
InHeader
,
input
*
raw
.
AccessIn
)
(
code
Status
)
{
n
:=
me
.
toInode
(
header
.
NodeId
)
func
(
c
*
FileSystemConnector
)
Access
(
header
*
raw
.
InHeader
,
input
*
raw
.
AccessIn
)
(
code
Status
)
{
n
:=
c
.
toInode
(
header
.
NodeId
)
return
n
.
fsInode
.
Access
(
input
.
Mask
,
(
*
Context
)(
&
header
.
Context
))
}
func
(
me
*
FileSystemConnector
)
Create
(
header
*
raw
.
InHeader
,
input
*
raw
.
CreateIn
,
name
string
)
(
flags
uint32
,
h
uint64
,
out
*
raw
.
EntryOut
,
code
Status
)
{
parent
:=
me
.
toInode
(
header
.
NodeId
)
func
(
c
*
FileSystemConnector
)
Create
(
header
*
raw
.
InHeader
,
input
*
raw
.
CreateIn
,
name
string
)
(
flags
uint32
,
h
uint64
,
out
*
raw
.
EntryOut
,
code
Status
)
{
parent
:=
c
.
toInode
(
header
.
NodeId
)
f
,
fi
,
fsNode
,
code
:=
parent
.
fsInode
.
Create
(
name
,
uint32
(
input
.
Flags
),
input
.
Mode
,
(
*
Context
)(
&
header
.
Context
))
if
!
code
.
Ok
()
{
return
0
,
0
,
nil
,
code
}
rawAttr
:=
(
*
raw
.
Attr
)(
fi
)
out
=
me
.
childLookup
(
rawAttr
,
fsNode
)
out
=
c
.
childLookup
(
rawAttr
,
fsNode
)
handle
,
opened
:=
parent
.
mount
.
registerFileHandle
(
fsNode
.
Inode
(),
nil
,
f
,
input
.
Flags
)
return
opened
.
FuseFlags
,
handle
,
out
,
code
}
func
(
me
*
FileSystemConnector
)
Release
(
header
*
raw
.
InHeader
,
input
*
raw
.
ReleaseIn
)
{
node
:=
me
.
toInode
(
header
.
NodeId
)
func
(
c
*
FileSystemConnector
)
Release
(
header
*
raw
.
InHeader
,
input
*
raw
.
ReleaseIn
)
{
node
:=
c
.
toInode
(
header
.
NodeId
)
opened
:=
node
.
mount
.
unregisterFileHandle
(
input
.
Fh
,
node
)
opened
.
WithFlags
.
File
.
Release
()
}
func
(
me
*
FileSystemConnector
)
ReleaseDir
(
header
*
raw
.
InHeader
,
input
*
raw
.
ReleaseIn
)
{
node
:=
me
.
toInode
(
header
.
NodeId
)
func
(
c
*
FileSystemConnector
)
ReleaseDir
(
header
*
raw
.
InHeader
,
input
*
raw
.
ReleaseIn
)
{
node
:=
c
.
toInode
(
header
.
NodeId
)
opened
:=
node
.
mount
.
unregisterFileHandle
(
input
.
Fh
,
node
)
opened
.
dir
.
Release
()
me
.
considerDropInode
(
node
)
c
.
considerDropInode
(
node
)
}
func
(
me
*
FileSystemConnector
)
GetXAttrSize
(
header
*
raw
.
InHeader
,
attribute
string
)
(
sz
int
,
code
Status
)
{
node
:=
me
.
toInode
(
header
.
NodeId
)
data
,
c
:=
node
.
fsInode
.
GetXAttr
(
attribute
,
(
*
Context
)(
&
header
.
Context
))
return
len
(
data
),
c
func
(
c
*
FileSystemConnector
)
GetXAttrSize
(
header
*
raw
.
InHeader
,
attribute
string
)
(
sz
int
,
code
Status
)
{
node
:=
c
.
toInode
(
header
.
NodeId
)
data
,
errno
:=
node
.
fsInode
.
GetXAttr
(
attribute
,
(
*
Context
)(
&
header
.
Context
))
return
len
(
data
),
errno
}
func
(
me
*
FileSystemConnector
)
GetXAttrData
(
header
*
raw
.
InHeader
,
attribute
string
)
(
data
[]
byte
,
code
Status
)
{
node
:=
me
.
toInode
(
header
.
NodeId
)
func
(
c
*
FileSystemConnector
)
GetXAttrData
(
header
*
raw
.
InHeader
,
attribute
string
)
(
data
[]
byte
,
code
Status
)
{
node
:=
c
.
toInode
(
header
.
NodeId
)
return
node
.
fsInode
.
GetXAttr
(
attribute
,
(
*
Context
)(
&
header
.
Context
))
}
func
(
me
*
FileSystemConnector
)
RemoveXAttr
(
header
*
raw
.
InHeader
,
attr
string
)
Status
{
node
:=
me
.
toInode
(
header
.
NodeId
)
func
(
c
*
FileSystemConnector
)
RemoveXAttr
(
header
*
raw
.
InHeader
,
attr
string
)
Status
{
node
:=
c
.
toInode
(
header
.
NodeId
)
return
node
.
fsInode
.
RemoveXAttr
(
attr
,
(
*
Context
)(
&
header
.
Context
))
}
func
(
me
*
FileSystemConnector
)
SetXAttr
(
header
*
raw
.
InHeader
,
input
*
raw
.
SetXAttrIn
,
attr
string
,
data
[]
byte
)
Status
{
node
:=
me
.
toInode
(
header
.
NodeId
)
func
(
c
*
FileSystemConnector
)
SetXAttr
(
header
*
raw
.
InHeader
,
input
*
raw
.
SetXAttrIn
,
attr
string
,
data
[]
byte
)
Status
{
node
:=
c
.
toInode
(
header
.
NodeId
)
return
node
.
fsInode
.
SetXAttr
(
attr
,
data
,
int
(
input
.
Flags
),
(
*
Context
)(
&
header
.
Context
))
}
func
(
me
*
FileSystemConnector
)
ListXAttr
(
header
*
raw
.
InHeader
)
(
data
[]
byte
,
code
Status
)
{
node
:=
me
.
toInode
(
header
.
NodeId
)
func
(
c
*
FileSystemConnector
)
ListXAttr
(
header
*
raw
.
InHeader
)
(
data
[]
byte
,
code
Status
)
{
node
:=
c
.
toInode
(
header
.
NodeId
)
attrs
,
code
:=
node
.
fsInode
.
ListXAttr
((
*
Context
)(
&
header
.
Context
))
if
code
!=
OK
{
return
nil
,
code
...
...
@@ -344,25 +344,25 @@ func (me *FileSystemConnector) ListXAttr(header *raw.InHeader) (data []byte, cod
////////////////
// files.
func
(
me
*
FileSystemConnector
)
Write
(
header
*
raw
.
InHeader
,
input
*
WriteIn
,
data
[]
byte
)
(
written
uint32
,
code
Status
)
{
node
:=
me
.
toInode
(
header
.
NodeId
)
func
(
c
*
FileSystemConnector
)
Write
(
header
*
raw
.
InHeader
,
input
*
WriteIn
,
data
[]
byte
)
(
written
uint32
,
code
Status
)
{
node
:=
c
.
toInode
(
header
.
NodeId
)
opened
:=
node
.
mount
.
getOpenedFile
(
input
.
Fh
)
return
opened
.
WithFlags
.
File
.
Write
(
input
,
data
)
}
func
(
me
*
FileSystemConnector
)
Read
(
header
*
raw
.
InHeader
,
input
*
ReadIn
,
bp
BufferPool
)
([]
byte
,
Status
)
{
node
:=
me
.
toInode
(
header
.
NodeId
)
func
(
c
*
FileSystemConnector
)
Read
(
header
*
raw
.
InHeader
,
input
*
ReadIn
,
bp
BufferPool
)
([]
byte
,
Status
)
{
node
:=
c
.
toInode
(
header
.
NodeId
)
opened
:=
node
.
mount
.
getOpenedFile
(
input
.
Fh
)
return
opened
.
WithFlags
.
File
.
Read
(
input
,
bp
)
}
func
(
me
*
FileSystemConnector
)
StatFs
(
header
*
raw
.
InHeader
)
*
StatfsOut
{
node
:=
me
.
toInode
(
header
.
NodeId
)
func
(
c
*
FileSystemConnector
)
StatFs
(
header
*
raw
.
InHeader
)
*
StatfsOut
{
node
:=
c
.
toInode
(
header
.
NodeId
)
return
node
.
FsNode
()
.
StatFs
()
}
func
(
me
*
FileSystemConnector
)
Flush
(
header
*
raw
.
InHeader
,
input
*
raw
.
FlushIn
)
Status
{
node
:=
me
.
toInode
(
header
.
NodeId
)
func
(
c
*
FileSystemConnector
)
Flush
(
header
*
raw
.
InHeader
,
input
*
raw
.
FlushIn
)
Status
{
node
:=
c
.
toInode
(
header
.
NodeId
)
opened
:=
node
.
mount
.
getOpenedFile
(
input
.
Fh
)
return
opened
.
WithFlags
.
File
.
Flush
()
}
...
...
fuse/handle.go
View file @
ce603372
...
...
@@ -43,26 +43,26 @@ type portableHandleMap struct {
handles
map
[
uint64
]
*
Handled
}
func
(
m
e
*
portableHandleMap
)
Register
(
obj
*
Handled
,
asInt
interface
{})
uint64
{
func
(
m
*
portableHandleMap
)
Register
(
obj
*
Handled
,
asInt
interface
{})
uint64
{
if
obj
.
check
!=
0
{
panic
(
_ALREADY_MSG
)
}
m
e
.
Lock
()
defer
m
e
.
Unlock
()
m
.
Lock
()
defer
m
.
Unlock
()
for
{
h
:=
uint64
(
m
e
.
nextFree
)
m
e
.
nextFree
++
h
:=
uint64
(
m
.
nextFree
)
m
.
nextFree
++
// HACK - we make sure we start with 1, so we always
// assign root to 1.
if
h
<
1
{
continue
}
old
:=
m
e
.
handles
[
h
]
old
:=
m
.
handles
[
h
]
if
old
!=
nil
{
continue
}
m
e
.
handles
[
h
]
=
obj
m
.
handles
[
h
]
=
obj
obj
.
check
=
0xbaabbaab
return
h
}
...
...
@@ -70,31 +70,31 @@ func (me *portableHandleMap) Register(obj *Handled, asInt interface{}) uint64 {
return
0
}
func
(
m
e
*
portableHandleMap
)
Count
()
int
{
m
e
.
RLock
()
defer
m
e
.
RUnlock
()
return
len
(
m
e
.
handles
)
func
(
m
*
portableHandleMap
)
Count
()
int
{
m
.
RLock
()
defer
m
.
RUnlock
()
return
len
(
m
.
handles
)
}
func
(
m
e
*
portableHandleMap
)
Decode
(
h
uint64
)
*
Handled
{
m
e
.
RLock
()
defer
m
e
.
RUnlock
()
return
m
e
.
handles
[
h
]
func
(
m
*
portableHandleMap
)
Decode
(
h
uint64
)
*
Handled
{
m
.
RLock
()
defer
m
.
RUnlock
()
return
m
.
handles
[
h
]
}
func
(
m
e
*
portableHandleMap
)
Forget
(
h
uint64
)
*
Handled
{
m
e
.
Lock
()
defer
m
e
.
Unlock
()
v
:=
m
e
.
handles
[
h
]
func
(
m
*
portableHandleMap
)
Forget
(
h
uint64
)
*
Handled
{
m
.
Lock
()
defer
m
.
Unlock
()
v
:=
m
.
handles
[
h
]
v
.
check
=
0
delete
(
m
e
.
handles
,
h
)
delete
(
m
.
handles
,
h
)
return
v
}
func
(
m
e
*
portableHandleMap
)
Has
(
h
uint64
)
bool
{
m
e
.
RLock
()
defer
m
e
.
RUnlock
()
return
m
e
.
handles
[
h
]
!=
nil
func
(
m
*
portableHandleMap
)
Has
(
h
uint64
)
bool
{
m
.
RLock
()
defer
m
.
RUnlock
()
return
m
.
handles
[
h
]
!=
nil
}
// 32 bits version of HandleMap
...
...
@@ -103,37 +103,37 @@ type int32HandleMap struct {
handles
map
[
uint32
]
*
Handled
}
func
(
m
e
*
int32HandleMap
)
Register
(
obj
*
Handled
,
asInt
interface
{})
uint64
{
m
e
.
mutex
.
Lock
()
defer
m
e
.
mutex
.
Unlock
()
func
(
m
*
int32HandleMap
)
Register
(
obj
*
Handled
,
asInt
interface
{})
uint64
{
m
.
mutex
.
Lock
()
defer
m
.
mutex
.
Unlock
()
handle
:=
uint32
(
uintptr
(
unsafe
.
Pointer
(
obj
)))
m
e
.
handles
[
handle
]
=
obj
m
.
handles
[
handle
]
=
obj
return
uint64
(
handle
)
}
func
(
m
e
*
int32HandleMap
)
Has
(
h
uint64
)
bool
{
m
e
.
mutex
.
Lock
()
defer
m
e
.
mutex
.
Unlock
()
return
m
e
.
handles
[
uint32
(
h
)]
!=
nil
func
(
m
*
int32HandleMap
)
Has
(
h
uint64
)
bool
{
m
.
mutex
.
Lock
()
defer
m
.
mutex
.
Unlock
()
return
m
.
handles
[
uint32
(
h
)]
!=
nil
}
func
(
m
e
*
int32HandleMap
)
Count
()
int
{
m
e
.
mutex
.
Lock
()
defer
m
e
.
mutex
.
Unlock
()
return
len
(
m
e
.
handles
)
func
(
m
*
int32HandleMap
)
Count
()
int
{
m
.
mutex
.
Lock
()
defer
m
.
mutex
.
Unlock
()
return
len
(
m
.
handles
)
}
func
(
m
e
*
int32HandleMap
)
Forget
(
handle
uint64
)
*
Handled
{
val
:=
m
e
.
Decode
(
handle
)
func
(
m
*
int32HandleMap
)
Forget
(
handle
uint64
)
*
Handled
{
val
:=
m
.
Decode
(
handle
)
m
e
.
mutex
.
Lock
()
defer
m
e
.
mutex
.
Unlock
()
m
.
mutex
.
Lock
()
defer
m
.
mutex
.
Unlock
()
val
.
check
=
0
delete
(
m
e
.
handles
,
uint32
(
handle
))
delete
(
m
.
handles
,
uint32
(
handle
))
return
val
}
func
(
m
e
*
int32HandleMap
)
Decode
(
handle
uint64
)
*
Handled
{
func
(
m
*
int32HandleMap
)
Decode
(
handle
uint64
)
*
Handled
{
val
:=
(
*
Handled
)(
unsafe
.
Pointer
(
uintptr
(
handle
&
((
1
<<
32
)
-
1
))))
return
val
}
...
...
@@ -147,15 +147,15 @@ type int64HandleMap struct {
var
baseAddress
uint64
func
(
m
e
*
int64HandleMap
)
verify
()
{
func
(
m
*
int64HandleMap
)
verify
()
{
if
!
paranoia
{
return
}
m
e
.
mutex
.
Lock
()
defer
m
e
.
mutex
.
Unlock
()
for
k
,
v
:=
range
m
e
.
handles
{
if
m
e
.
Decode
(
k
)
!=
v
{
m
.
mutex
.
Lock
()
defer
m
.
mutex
.
Unlock
()
for
k
,
v
:=
range
m
.
handles
{
if
m
.
Decode
(
k
)
!=
v
{
panic
(
"handle map out of sync"
)
}
}
...
...
@@ -188,17 +188,17 @@ func NewHandleMap(portable bool) (hm HandleMap) {
return
nil
}
func
(
m
e
*
int64HandleMap
)
Count
()
int
{
m
e
.
mutex
.
Lock
()
defer
m
e
.
mutex
.
Unlock
()
return
len
(
m
e
.
handles
)
func
(
m
*
int64HandleMap
)
Count
()
int
{
m
.
mutex
.
Lock
()
defer
m
.
mutex
.
Unlock
()
return
len
(
m
.
handles
)
}
func
(
m
e
*
int64HandleMap
)
Register
(
obj
*
Handled
,
asInterface
interface
{})
(
handle
uint64
)
{
defer
m
e
.
verify
()
func
(
m
*
int64HandleMap
)
Register
(
obj
*
Handled
,
asInterface
interface
{})
(
handle
uint64
)
{
defer
m
.
verify
()
m
e
.
mutex
.
Lock
()
defer
m
e
.
mutex
.
Unlock
()
m
.
mutex
.
Lock
()
defer
m
.
mutex
.
Unlock
()
handle
=
uint64
(
uintptr
(
unsafe
.
Pointer
(
obj
)))
...
...
@@ -212,9 +212,9 @@ func (me *int64HandleMap) Register(obj *Handled, asInterface interface{}) (handl
handle
-=
baseAddress
handle
>>=
3
check
:=
m
e
.
nextFree
m
e
.
nextFree
++
m
e
.
nextFree
=
me
.
nextFree
&
(
1
<<
(
64
-
48
+
3
)
-
1
)
check
:=
m
.
nextFree
m
.
nextFree
++
m
.
nextFree
=
m
.
nextFree
&
(
1
<<
(
64
-
48
+
3
)
-
1
)
handle
|=
uint64
(
check
)
<<
(
48
-
3
)
if
obj
.
check
!=
0
{
...
...
@@ -223,29 +223,29 @@ func (me *int64HandleMap) Register(obj *Handled, asInterface interface{}) (handl
obj
.
check
=
check
obj
.
object
=
asInterface
m
e
.
handles
[
handle
]
=
obj
m
.
handles
[
handle
]
=
obj
return
handle
}
func
(
m
e
*
int64HandleMap
)
Forget
(
handle
uint64
)
(
val
*
Handled
)
{
defer
m
e
.
verify
()
func
(
m
*
int64HandleMap
)
Forget
(
handle
uint64
)
(
val
*
Handled
)
{
defer
m
.
verify
()
val
=
m
e
.
Decode
(
handle
)
val
=
m
.
Decode
(
handle
)
m
e
.
mutex
.
Lock
()
defer
m
e
.
mutex
.
Unlock
()
delete
(
m
e
.
handles
,
handle
)
m
.
mutex
.
Lock
()
defer
m
.
mutex
.
Unlock
()
delete
(
m
.
handles
,
handle
)
val
.
check
=
0
return
val
}
func
(
m
e
*
int64HandleMap
)
Has
(
handle
uint64
)
bool
{
m
e
.
mutex
.
Lock
()
defer
m
e
.
mutex
.
Unlock
()
return
m
e
.
handles
[
handle
]
!=
nil
func
(
m
*
int64HandleMap
)
Has
(
handle
uint64
)
bool
{
m
.
mutex
.
Lock
()
defer
m
.
mutex
.
Unlock
()
return
m
.
handles
[
handle
]
!=
nil
}
func
(
m
e
*
int64HandleMap
)
Decode
(
handle
uint64
)
(
val
*
Handled
)
{
func
(
m
*
int64HandleMap
)
Decode
(
handle
uint64
)
(
val
*
Handled
)
{
ptrBits
:=
uintptr
(
handle
&
(
1
<<
45
-
1
))
check
:=
uint32
(
handle
>>
45
)
val
=
(
*
Handled
)(
unsafe
.
Pointer
(
ptrBits
<<
3
+
uintptr
(
baseAddress
)))
...
...
fuse/inode.go
View file @
ce603372
...
...
@@ -73,11 +73,11 @@ func newInode(isDir bool, fsNode FsNode) *Inode {
// public methods.
// Returns any open file, preferably a r/w one.
func
(
me
*
Inode
)
AnyFile
()
(
file
File
)
{
me
.
openFilesMutex
.
Lock
()
defer
me
.
openFilesMutex
.
Unlock
()
func
(
n
*
Inode
)
AnyFile
()
(
file
File
)
{
n
.
openFilesMutex
.
Lock
()
defer
n
.
openFilesMutex
.
Unlock
()
for
_
,
f
:=
range
me
.
openFiles
{
for
_
,
f
:=
range
n
.
openFiles
{
if
file
==
nil
||
f
.
WithFlags
.
OpenFlags
&
O_ANYWRITE
!=
0
{
file
=
f
.
WithFlags
.
File
}
...
...
@@ -85,12 +85,12 @@ func (me *Inode) AnyFile() (file File) {
return
file
}
func
(
me
*
Inode
)
Children
()
(
out
map
[
string
]
*
Inode
)
{
me
.
treeLock
.
RLock
()
defer
me
.
treeLock
.
RUnlock
()
func
(
n
*
Inode
)
Children
()
(
out
map
[
string
]
*
Inode
)
{
n
.
treeLock
.
RLock
()
defer
n
.
treeLock
.
RUnlock
()
out
=
map
[
string
]
*
Inode
{}
for
k
,
v
:=
range
me
.
children
{
for
k
,
v
:=
range
n
.
children
{
out
[
k
]
=
v
}
return
out
...
...
@@ -98,29 +98,29 @@ func (me *Inode) Children() (out map[string]*Inode) {
// FsChildren returns all the children from the same filesystem. It
// will skip mountpoints.
func
(
me
*
Inode
)
FsChildren
()
(
out
map
[
string
]
*
Inode
)
{
me
.
treeLock
.
RLock
()
defer
me
.
treeLock
.
RUnlock
()
func
(
n
*
Inode
)
FsChildren
()
(
out
map
[
string
]
*
Inode
)
{
n
.
treeLock
.
RLock
()
defer
n
.
treeLock
.
RUnlock
()
out
=
map
[
string
]
*
Inode
{}
for
k
,
v
:=
range
me
.
children
{
if
v
.
mount
==
me
.
mount
{
for
k
,
v
:=
range
n
.
children
{
if
v
.
mount
==
n
.
mount
{
out
[
k
]
=
v
}
}
return
out
}
func
(
me
*
Inode
)
FsNode
()
FsNode
{
return
me
.
fsInode
func
(
n
*
Inode
)
FsNode
()
FsNode
{
return
n
.
fsInode
}
// Files() returns an opens file that have bits in common with the
// give mask. Use mask==0 to return all files.
func
(
me
*
Inode
)
Files
(
mask
uint32
)
(
files
[]
WithFlags
)
{
me
.
openFilesMutex
.
Lock
()
defer
me
.
openFilesMutex
.
Unlock
()
for
_
,
f
:=
range
me
.
openFiles
{
func
(
n
*
Inode
)
Files
(
mask
uint32
)
(
files
[]
WithFlags
)
{
n
.
openFilesMutex
.
Lock
()
defer
n
.
openFilesMutex
.
Unlock
()
for
_
,
f
:=
range
n
.
openFiles
{
if
mask
==
0
||
f
.
WithFlags
.
OpenFlags
&
mask
!=
0
{
files
=
append
(
files
,
f
.
WithFlags
)
}
...
...
@@ -128,77 +128,77 @@ func (me *Inode) Files(mask uint32) (files []WithFlags) {
return
files
}
func
(
me
*
Inode
)
IsDir
()
bool
{
return
me
.
children
!=
nil
func
(
n
*
Inode
)
IsDir
()
bool
{
return
n
.
children
!=
nil
}
func
(
me
*
Inode
)
New
(
isDir
bool
,
fsi
FsNode
)
*
Inode
{
func
(
n
*
Inode
)
New
(
isDir
bool
,
fsi
FsNode
)
*
Inode
{
ch
:=
newInode
(
isDir
,
fsi
)
ch
.
mount
=
me
.
mount
ch
.
treeLock
=
me
.
treeLock
ch
.
mount
=
n
.
mount
ch
.
treeLock
=
n
.
treeLock
return
ch
}
func
(
me
*
Inode
)
GetChild
(
name
string
)
(
child
*
Inode
)
{
me
.
treeLock
.
RLock
()
defer
me
.
treeLock
.
RUnlock
()
func
(
n
*
Inode
)
GetChild
(
name
string
)
(
child
*
Inode
)
{
n
.
treeLock
.
RLock
()
defer
n
.
treeLock
.
RUnlock
()
return
me
.
children
[
name
]
return
n
.
children
[
name
]
}
func
(
me
*
Inode
)
AddChild
(
name
string
,
child
*
Inode
)
{
func
(
n
*
Inode
)
AddChild
(
name
string
,
child
*
Inode
)
{
if
child
==
nil
{
log
.
Panicf
(
"adding nil child as %q"
,
name
)
}
me
.
treeLock
.
Lock
()
defer
me
.
treeLock
.
Unlock
()
me
.
addChild
(
name
,
child
)
n
.
treeLock
.
Lock
()
defer
n
.
treeLock
.
Unlock
()
n
.
addChild
(
name
,
child
)
}
func
(
me
*
Inode
)
RmChild
(
name
string
)
(
ch
*
Inode
)
{
me
.
treeLock
.
Lock
()
defer
me
.
treeLock
.
Unlock
()
return
me
.
rmChild
(
name
)
func
(
n
*
Inode
)
RmChild
(
name
string
)
(
ch
*
Inode
)
{
n
.
treeLock
.
Lock
()
defer
n
.
treeLock
.
Unlock
()
return
n
.
rmChild
(
name
)
}
//////////////////////////////////////////////////////////////
// private
// Must be called with treeLock for the mount held.
func
(
me
*
Inode
)
addChild
(
name
string
,
child
*
Inode
)
{
func
(
n
*
Inode
)
addChild
(
name
string
,
child
*
Inode
)
{
if
paranoia
{
ch
:=
me
.
children
[
name
]
ch
:=
n
.
children
[
name
]
if
ch
!=
nil
{
log
.
Panicf
(
"Already have an Inode with same name: %v: %v"
,
name
,
ch
)
}
}
me
.
children
[
name
]
=
child
n
.
children
[
name
]
=
child
}
// Must be called with treeLock for the mount held.
func
(
me
*
Inode
)
rmChild
(
name
string
)
(
ch
*
Inode
)
{
ch
=
me
.
children
[
name
]
func
(
n
*
Inode
)
rmChild
(
name
string
)
(
ch
*
Inode
)
{
ch
=
n
.
children
[
name
]
if
ch
!=
nil
{
delete
(
me
.
children
,
name
)
delete
(
n
.
children
,
name
)
}
return
ch
}
// Can only be called on untouched inodes.
func
(
me
*
Inode
)
mountFs
(
fs
NodeFileSystem
,
opts
*
FileSystemOptions
)
{
me
.
mountPoint
=
&
fileSystemMount
{
func
(
n
*
Inode
)
mountFs
(
fs
NodeFileSystem
,
opts
*
FileSystemOptions
)
{
n
.
mountPoint
=
&
fileSystemMount
{
fs
:
fs
,
openFiles
:
NewHandleMap
(
false
),
mountInode
:
me
,
mountInode
:
n
,
options
:
opts
,
}
me
.
mount
=
me
.
mountPoint
me
.
treeLock
=
&
me
.
mountPoint
.
treeLock
n
.
mount
=
n
.
mountPoint
n
.
treeLock
=
&
n
.
mountPoint
.
treeLock
}
// Must be called with treeLock held.
func
(
me
*
Inode
)
canUnmount
()
bool
{
for
_
,
v
:=
range
me
.
children
{
func
(
n
*
Inode
)
canUnmount
()
bool
{
for
_
,
v
:=
range
n
.
children
{
if
v
.
mountPoint
!=
nil
{
// This access may be out of date, but it is no
// problem to err on the safe side.
...
...
@@ -209,16 +209,16 @@ func (me *Inode) canUnmount() bool {
}
}
me
.
openFilesMutex
.
Lock
()
defer
me
.
openFilesMutex
.
Unlock
()
return
len
(
me
.
openFiles
)
==
0
n
.
openFilesMutex
.
Lock
()
defer
n
.
openFilesMutex
.
Unlock
()
return
len
(
n
.
openFiles
)
==
0
}
func
(
me
*
Inode
)
getMountDirEntries
()
(
out
[]
DirEntry
)
{
me
.
treeLock
.
RLock
()
defer
me
.
treeLock
.
RUnlock
()
func
(
n
*
Inode
)
getMountDirEntries
()
(
out
[]
DirEntry
)
{
n
.
treeLock
.
RLock
()
defer
n
.
treeLock
.
RUnlock
()
for
k
:=
range
me
.
mounts
{
for
k
:=
range
n
.
mounts
{
out
=
append
(
out
,
DirEntry
{
Name
:
k
,
Mode
:
S_IFDIR
,
...
...
@@ -229,33 +229,33 @@ func (me *Inode) getMountDirEntries() (out []DirEntry) {
const
initDirSize
=
20
func
(
me
*
Inode
)
verify
(
cur
*
fileSystemMount
)
{
if
me
.
lookupCount
<
0
{
log
.
Panicf
(
"negative lookup count %d on node %d"
,
me
.
lookupCount
,
me
.
nodeId
)
func
(
n
*
Inode
)
verify
(
cur
*
fileSystemMount
)
{
if
n
.
lookupCount
<
0
{
log
.
Panicf
(
"negative lookup count %d on node %d"
,
n
.
lookupCount
,
n
.
nodeId
)
}
if
(
me
.
lookupCount
==
0
)
!=
(
me
.
nodeId
==
0
)
{
log
.
Panicf
(
"kernel registration mismatch: lookup %d id %d"
,
me
.
lookupCount
,
me
.
nodeId
)
if
(
n
.
lookupCount
==
0
)
!=
(
n
.
nodeId
==
0
)
{
log
.
Panicf
(
"kernel registration mismatch: lookup %d id %d"
,
n
.
lookupCount
,
n
.
nodeId
)
}
if
me
.
mountPoint
!=
nil
{
if
me
!=
me
.
mountPoint
.
mountInode
{
log
.
Panicf
(
"mountpoint mismatch %v %v"
,
me
,
me
.
mountPoint
.
mountInode
)
if
n
.
mountPoint
!=
nil
{
if
n
!=
n
.
mountPoint
.
mountInode
{
log
.
Panicf
(
"mountpoint mismatch %v %v"
,
n
,
n
.
mountPoint
.
mountInode
)
}
cur
=
me
.
mountPoint
cur
=
n
.
mountPoint
}
if
me
.
mount
!=
cur
{
log
.
Panicf
(
"
me.mount not set correctly %v %v"
,
me
.
mount
,
cur
)
if
n
.
mount
!=
cur
{
log
.
Panicf
(
"
n.mount not set correctly %v %v"
,
n
.
mount
,
cur
)
}
for
name
,
m
:=
range
me
.
mounts
{
if
m
.
mountInode
!=
me
.
children
[
name
]
{
for
name
,
m
:=
range
n
.
mounts
{
if
m
.
mountInode
!=
n
.
children
[
name
]
{
log
.
Panicf
(
"mountpoint parent mismatch: node:%v name:%v ch:%v"
,
me
.
mountPoint
,
name
,
me
.
children
)
n
.
mountPoint
,
name
,
n
.
children
)
}
}
for
n
,
ch
:=
range
me
.
children
{
for
n
m
,
ch
:=
range
n
.
children
{
if
ch
==
nil
{
log
.
Panicf
(
"Found nil child: %q"
,
n
)
log
.
Panicf
(
"Found nil child: %q"
,
n
m
)
}
ch
.
verify
(
cur
)
}
...
...
fuse/latencymap.go
View file @
ce603372
...
...
@@ -30,43 +30,43 @@ func NewLatencyMap() *LatencyMap {
return
m
}
func
(
m
e
*
LatencyMap
)
AddMany
(
args
[]
LatencyArg
)
{
m
e
.
Mutex
.
Lock
()
defer
m
e
.
Mutex
.
Unlock
()
func
(
m
*
LatencyMap
)
AddMany
(
args
[]
LatencyArg
)
{
m
.
Mutex
.
Lock
()
defer
m
.
Mutex
.
Unlock
()
for
_
,
v
:=
range
args
{
m
e
.
add
(
v
.
Name
,
v
.
Arg
,
v
.
DtNs
)
m
.
add
(
v
.
Name
,
v
.
Arg
,
v
.
DtNs
)
}
}
func
(
m
e
*
LatencyMap
)
Add
(
name
string
,
arg
string
,
dtNs
int64
)
{
m
e
.
Mutex
.
Lock
()
defer
m
e
.
Mutex
.
Unlock
()
m
e
.
add
(
name
,
arg
,
dtNs
)
func
(
m
*
LatencyMap
)
Add
(
name
string
,
arg
string
,
dtNs
int64
)
{
m
.
Mutex
.
Lock
()
defer
m
.
Mutex
.
Unlock
()
m
.
add
(
name
,
arg
,
dtNs
)
}
func
(
m
e
*
LatencyMap
)
add
(
name
string
,
arg
string
,
dtNs
int64
)
{
e
:=
m
e
.
stats
[
name
]
func
(
m
*
LatencyMap
)
add
(
name
string
,
arg
string
,
dtNs
int64
)
{
e
:=
m
.
stats
[
name
]
if
e
==
nil
{
e
=
new
(
latencyMapEntry
)
m
e
.
stats
[
name
]
=
e
m
.
stats
[
name
]
=
e
}
e
.
count
++
e
.
ns
+=
dtNs
if
arg
!=
""
{
m
,
ok
:=
me
.
secondaryStats
[
name
]
_
,
ok
:=
m
.
secondaryStats
[
name
]
if
!
ok
{
m
=
make
(
map
[
string
]
int64
)
me
.
secondaryStats
[
name
]
=
m
m
.
secondaryStats
[
name
]
=
make
(
map
[
string
]
int64
)
}
// TODO - do something with secondaryStats[name]
}
}
func
(
m
e
*
LatencyMap
)
Counts
()
map
[
string
]
int
{
m
e
.
Mutex
.
Lock
()
defer
m
e
.
Mutex
.
Unlock
()
func
(
m
*
LatencyMap
)
Counts
()
map
[
string
]
int
{
m
.
Mutex
.
Lock
()
defer
m
.
Mutex
.
Unlock
()
r
:=
make
(
map
[
string
]
int
)
for
k
,
v
:=
range
m
e
.
stats
{
for
k
,
v
:=
range
m
.
stats
{
r
[
k
]
=
v
.
count
}
return
r
...
...
@@ -74,24 +74,24 @@ func (me *LatencyMap) Counts() map[string]int {
// Latencies returns a map. Use 1e-3 for unit to get ms
// results.
func
(
m
e
*
LatencyMap
)
Latencies
(
unit
float64
)
map
[
string
]
float64
{
m
e
.
Mutex
.
Lock
()
defer
m
e
.
Mutex
.
Unlock
()
func
(
m
*
LatencyMap
)
Latencies
(
unit
float64
)
map
[
string
]
float64
{
m
.
Mutex
.
Lock
()
defer
m
.
Mutex
.
Unlock
()
r
:=
make
(
map
[
string
]
float64
)
mult
:=
1
/
(
1e9
*
unit
)
for
key
,
ent
:=
range
m
e
.
stats
{
for
key
,
ent
:=
range
m
.
stats
{
lat
:=
mult
*
float64
(
ent
.
ns
)
/
float64
(
ent
.
count
)
r
[
key
]
=
lat
}
return
r
}
func
(
m
e
*
LatencyMap
)
TopArgs
(
name
string
)
[]
string
{
m
e
.
Mutex
.
Lock
()
defer
m
e
.
Mutex
.
Unlock
()
func
(
m
*
LatencyMap
)
TopArgs
(
name
string
)
[]
string
{
m
.
Mutex
.
Lock
()
defer
m
.
Mutex
.
Unlock
()
counts
:=
m
e
.
secondaryStats
[
name
]
counts
:=
m
.
secondaryStats
[
name
]
results
:=
make
([]
string
,
0
,
len
(
counts
))
for
k
,
v
:=
range
counts
{
results
=
append
(
results
,
fmt
.
Sprintf
(
"% 9d %s"
,
v
,
k
))
...
...
fuse/lockingfs.go
View file @
ce603372
...
...
@@ -22,123 +22,123 @@ func NewLockingFileSystem(pfs FileSystem) *LockingFileSystem {
return
l
}
func
(
me
*
LockingFileSystem
)
locked
()
func
()
{
me
.
lock
.
Lock
()
return
func
()
{
me
.
lock
.
Unlock
()
}
func
(
fs
*
LockingFileSystem
)
locked
()
func
()
{
fs
.
lock
.
Lock
()
return
func
()
{
fs
.
lock
.
Unlock
()
}
}
func
(
me
*
LockingFileSystem
)
GetAttr
(
name
string
,
context
*
Context
)
(
*
Attr
,
Status
)
{
defer
me
.
locked
()()
return
me
.
FileSystem
.
GetAttr
(
name
,
context
)
func
(
fs
*
LockingFileSystem
)
GetAttr
(
name
string
,
context
*
Context
)
(
*
Attr
,
Status
)
{
defer
fs
.
locked
()()
return
fs
.
FileSystem
.
GetAttr
(
name
,
context
)
}
func
(
me
*
LockingFileSystem
)
Readlink
(
name
string
,
context
*
Context
)
(
string
,
Status
)
{
defer
me
.
locked
()()
return
me
.
FileSystem
.
Readlink
(
name
,
context
)
func
(
fs
*
LockingFileSystem
)
Readlink
(
name
string
,
context
*
Context
)
(
string
,
Status
)
{
defer
fs
.
locked
()()
return
fs
.
FileSystem
.
Readlink
(
name
,
context
)
}
func
(
me
*
LockingFileSystem
)
Mknod
(
name
string
,
mode
uint32
,
dev
uint32
,
context
*
Context
)
Status
{
defer
me
.
locked
()()
return
me
.
FileSystem
.
Mknod
(
name
,
mode
,
dev
,
context
)
func
(
fs
*
LockingFileSystem
)
Mknod
(
name
string
,
mode
uint32
,
dev
uint32
,
context
*
Context
)
Status
{
defer
fs
.
locked
()()
return
fs
.
FileSystem
.
Mknod
(
name
,
mode
,
dev
,
context
)
}
func
(
me
*
LockingFileSystem
)
Mkdir
(
name
string
,
mode
uint32
,
context
*
Context
)
Status
{
defer
me
.
locked
()()
return
me
.
FileSystem
.
Mkdir
(
name
,
mode
,
context
)
func
(
fs
*
LockingFileSystem
)
Mkdir
(
name
string
,
mode
uint32
,
context
*
Context
)
Status
{
defer
fs
.
locked
()()
return
fs
.
FileSystem
.
Mkdir
(
name
,
mode
,
context
)
}
func
(
me
*
LockingFileSystem
)
Unlink
(
name
string
,
context
*
Context
)
(
code
Status
)
{
defer
me
.
locked
()()
return
me
.
FileSystem
.
Unlink
(
name
,
context
)
func
(
fs
*
LockingFileSystem
)
Unlink
(
name
string
,
context
*
Context
)
(
code
Status
)
{
defer
fs
.
locked
()()
return
fs
.
FileSystem
.
Unlink
(
name
,
context
)
}
func
(
me
*
LockingFileSystem
)
Rmdir
(
name
string
,
context
*
Context
)
(
code
Status
)
{
defer
me
.
locked
()()
return
me
.
FileSystem
.
Rmdir
(
name
,
context
)
func
(
fs
*
LockingFileSystem
)
Rmdir
(
name
string
,
context
*
Context
)
(
code
Status
)
{
defer
fs
.
locked
()()
return
fs
.
FileSystem
.
Rmdir
(
name
,
context
)
}
func
(
me
*
LockingFileSystem
)
Symlink
(
value
string
,
linkName
string
,
context
*
Context
)
(
code
Status
)
{
defer
me
.
locked
()()
return
me
.
FileSystem
.
Symlink
(
value
,
linkName
,
context
)
func
(
fs
*
LockingFileSystem
)
Symlink
(
value
string
,
linkName
string
,
context
*
Context
)
(
code
Status
)
{
defer
fs
.
locked
()()
return
fs
.
FileSystem
.
Symlink
(
value
,
linkName
,
context
)
}
func
(
me
*
LockingFileSystem
)
Rename
(
oldName
string
,
newName
string
,
context
*
Context
)
(
code
Status
)
{
defer
me
.
locked
()()
return
me
.
FileSystem
.
Rename
(
oldName
,
newName
,
context
)
func
(
fs
*
LockingFileSystem
)
Rename
(
oldName
string
,
newName
string
,
context
*
Context
)
(
code
Status
)
{
defer
fs
.
locked
()()
return
fs
.
FileSystem
.
Rename
(
oldName
,
newName
,
context
)
}
func
(
me
*
LockingFileSystem
)
Link
(
oldName
string
,
newName
string
,
context
*
Context
)
(
code
Status
)
{
defer
me
.
locked
()()
return
me
.
FileSystem
.
Link
(
oldName
,
newName
,
context
)
func
(
fs
*
LockingFileSystem
)
Link
(
oldName
string
,
newName
string
,
context
*
Context
)
(
code
Status
)
{
defer
fs
.
locked
()()
return
fs
.
FileSystem
.
Link
(
oldName
,
newName
,
context
)
}
func
(
me
*
LockingFileSystem
)
Chmod
(
name
string
,
mode
uint32
,
context
*
Context
)
(
code
Status
)
{
defer
me
.
locked
()()
return
me
.
FileSystem
.
Chmod
(
name
,
mode
,
context
)
func
(
fs
*
LockingFileSystem
)
Chmod
(
name
string
,
mode
uint32
,
context
*
Context
)
(
code
Status
)
{
defer
fs
.
locked
()()
return
fs
.
FileSystem
.
Chmod
(
name
,
mode
,
context
)
}
func
(
me
*
LockingFileSystem
)
Chown
(
name
string
,
uid
uint32
,
gid
uint32
,
context
*
Context
)
(
code
Status
)
{
defer
me
.
locked
()()
return
me
.
FileSystem
.
Chown
(
name
,
uid
,
gid
,
context
)
func
(
fs
*
LockingFileSystem
)
Chown
(
name
string
,
uid
uint32
,
gid
uint32
,
context
*
Context
)
(
code
Status
)
{
defer
fs
.
locked
()()
return
fs
.
FileSystem
.
Chown
(
name
,
uid
,
gid
,
context
)
}
func
(
me
*
LockingFileSystem
)
Truncate
(
name
string
,
offset
uint64
,
context
*
Context
)
(
code
Status
)
{
defer
me
.
locked
()()
return
me
.
FileSystem
.
Truncate
(
name
,
offset
,
context
)
func
(
fs
*
LockingFileSystem
)
Truncate
(
name
string
,
offset
uint64
,
context
*
Context
)
(
code
Status
)
{
defer
fs
.
locked
()()
return
fs
.
FileSystem
.
Truncate
(
name
,
offset
,
context
)
}
func
(
me
*
LockingFileSystem
)
Open
(
name
string
,
flags
uint32
,
context
*
Context
)
(
file
File
,
code
Status
)
{
return
me
.
FileSystem
.
Open
(
name
,
flags
,
context
)
func
(
fs
*
LockingFileSystem
)
Open
(
name
string
,
flags
uint32
,
context
*
Context
)
(
file
File
,
code
Status
)
{
return
fs
.
FileSystem
.
Open
(
name
,
flags
,
context
)
}
func
(
me
*
LockingFileSystem
)
OpenDir
(
name
string
,
context
*
Context
)
(
stream
chan
DirEntry
,
status
Status
)
{
defer
me
.
locked
()()
return
me
.
FileSystem
.
OpenDir
(
name
,
context
)
func
(
fs
*
LockingFileSystem
)
OpenDir
(
name
string
,
context
*
Context
)
(
stream
chan
DirEntry
,
status
Status
)
{
defer
fs
.
locked
()()
return
fs
.
FileSystem
.
OpenDir
(
name
,
context
)
}
func
(
me
*
LockingFileSystem
)
OnMount
(
nodeFs
*
PathNodeFs
)
{
defer
me
.
locked
()()
me
.
FileSystem
.
OnMount
(
nodeFs
)
func
(
fs
*
LockingFileSystem
)
OnMount
(
nodeFs
*
PathNodeFs
)
{
defer
fs
.
locked
()()
fs
.
FileSystem
.
OnMount
(
nodeFs
)
}
func
(
me
*
LockingFileSystem
)
OnUnmount
()
{
defer
me
.
locked
()()
me
.
FileSystem
.
OnUnmount
()
func
(
fs
*
LockingFileSystem
)
OnUnmount
()
{
defer
fs
.
locked
()()
fs
.
FileSystem
.
OnUnmount
()
}
func
(
me
*
LockingFileSystem
)
Access
(
name
string
,
mode
uint32
,
context
*
Context
)
(
code
Status
)
{
defer
me
.
locked
()()
return
me
.
FileSystem
.
Access
(
name
,
mode
,
context
)
func
(
fs
*
LockingFileSystem
)
Access
(
name
string
,
mode
uint32
,
context
*
Context
)
(
code
Status
)
{
defer
fs
.
locked
()()
return
fs
.
FileSystem
.
Access
(
name
,
mode
,
context
)
}
func
(
me
*
LockingFileSystem
)
Create
(
name
string
,
flags
uint32
,
mode
uint32
,
context
*
Context
)
(
file
File
,
code
Status
)
{
defer
me
.
locked
()()
return
me
.
FileSystem
.
Create
(
name
,
flags
,
mode
,
context
)
func
(
fs
*
LockingFileSystem
)
Create
(
name
string
,
flags
uint32
,
mode
uint32
,
context
*
Context
)
(
file
File
,
code
Status
)
{
defer
fs
.
locked
()()
return
fs
.
FileSystem
.
Create
(
name
,
flags
,
mode
,
context
)
}
func
(
me
*
LockingFileSystem
)
Utimens
(
name
string
,
AtimeNs
int64
,
CtimeNs
int64
,
context
*
Context
)
(
code
Status
)
{
defer
me
.
locked
()()
return
me
.
FileSystem
.
Utimens
(
name
,
AtimeNs
,
CtimeNs
,
context
)
func
(
fs
*
LockingFileSystem
)
Utimens
(
name
string
,
AtimeNs
int64
,
CtimeNs
int64
,
context
*
Context
)
(
code
Status
)
{
defer
fs
.
locked
()()
return
fs
.
FileSystem
.
Utimens
(
name
,
AtimeNs
,
CtimeNs
,
context
)
}
func
(
me
*
LockingFileSystem
)
GetXAttr
(
name
string
,
attr
string
,
context
*
Context
)
([]
byte
,
Status
)
{
defer
me
.
locked
()()
return
me
.
FileSystem
.
GetXAttr
(
name
,
attr
,
context
)
func
(
fs
*
LockingFileSystem
)
GetXAttr
(
name
string
,
attr
string
,
context
*
Context
)
([]
byte
,
Status
)
{
defer
fs
.
locked
()()
return
fs
.
FileSystem
.
GetXAttr
(
name
,
attr
,
context
)
}
func
(
me
*
LockingFileSystem
)
SetXAttr
(
name
string
,
attr
string
,
data
[]
byte
,
flags
int
,
context
*
Context
)
Status
{
defer
me
.
locked
()()
return
me
.
FileSystem
.
SetXAttr
(
name
,
attr
,
data
,
flags
,
context
)
func
(
fs
*
LockingFileSystem
)
SetXAttr
(
name
string
,
attr
string
,
data
[]
byte
,
flags
int
,
context
*
Context
)
Status
{
defer
fs
.
locked
()()
return
fs
.
FileSystem
.
SetXAttr
(
name
,
attr
,
data
,
flags
,
context
)
}
func
(
me
*
LockingFileSystem
)
ListXAttr
(
name
string
,
context
*
Context
)
([]
string
,
Status
)
{
defer
me
.
locked
()()
return
me
.
FileSystem
.
ListXAttr
(
name
,
context
)
func
(
fs
*
LockingFileSystem
)
ListXAttr
(
name
string
,
context
*
Context
)
([]
string
,
Status
)
{
defer
fs
.
locked
()()
return
fs
.
FileSystem
.
ListXAttr
(
name
,
context
)
}
func
(
me
*
LockingFileSystem
)
RemoveXAttr
(
name
string
,
attr
string
,
context
*
Context
)
Status
{
defer
me
.
locked
()()
return
me
.
FileSystem
.
RemoveXAttr
(
name
,
attr
,
context
)
func
(
fs
*
LockingFileSystem
)
RemoveXAttr
(
name
string
,
attr
string
,
context
*
Context
)
Status
{
defer
fs
.
locked
()()
return
fs
.
FileSystem
.
RemoveXAttr
(
name
,
attr
,
context
)
}
////////////////////////////////////////////////////////////////
...
...
@@ -149,9 +149,9 @@ type LockingRawFileSystem struct {
lock
sync
.
Mutex
}
func
(
me
*
LockingRawFileSystem
)
locked
()
func
()
{
me
.
lock
.
Lock
()
return
func
()
{
me
.
lock
.
Unlock
()
}
func
(
fs
*
LockingRawFileSystem
)
locked
()
func
()
{
fs
.
lock
.
Lock
()
return
func
()
{
fs
.
lock
.
Unlock
()
}
}
func
NewLockingRawFileSystem
(
rfs
RawFileSystem
)
*
LockingRawFileSystem
{
...
...
@@ -160,147 +160,147 @@ func NewLockingRawFileSystem(rfs RawFileSystem) *LockingRawFileSystem {
return
l
}
func
(
me
*
LockingRawFileSystem
)
Lookup
(
h
*
raw
.
InHeader
,
name
string
)
(
out
*
raw
.
EntryOut
,
code
Status
)
{
defer
me
.
locked
()()
return
me
.
RawFileSystem
.
Lookup
(
h
,
name
)
func
(
fs
*
LockingRawFileSystem
)
Lookup
(
h
*
raw
.
InHeader
,
name
string
)
(
out
*
raw
.
EntryOut
,
code
Status
)
{
defer
fs
.
locked
()()
return
fs
.
RawFileSystem
.
Lookup
(
h
,
name
)
}
func
(
me
*
LockingRawFileSystem
)
Forget
(
nodeID
uint64
,
nlookup
uint64
)
{
defer
me
.
locked
()()
me
.
RawFileSystem
.
Forget
(
nodeID
,
nlookup
)
func
(
fs
*
LockingRawFileSystem
)
Forget
(
nodeID
uint64
,
nlookup
uint64
)
{
defer
fs
.
locked
()()
fs
.
RawFileSystem
.
Forget
(
nodeID
,
nlookup
)
}
func
(
me
*
LockingRawFileSystem
)
GetAttr
(
header
*
raw
.
InHeader
,
input
*
raw
.
GetAttrIn
)
(
out
*
raw
.
AttrOut
,
code
Status
)
{
defer
me
.
locked
()()
return
me
.
RawFileSystem
.
GetAttr
(
header
,
input
)
func
(
fs
*
LockingRawFileSystem
)
GetAttr
(
header
*
raw
.
InHeader
,
input
*
raw
.
GetAttrIn
)
(
out
*
raw
.
AttrOut
,
code
Status
)
{
defer
fs
.
locked
()()
return
fs
.
RawFileSystem
.
GetAttr
(
header
,
input
)
}
func
(
me
*
LockingRawFileSystem
)
Open
(
header
*
raw
.
InHeader
,
input
*
raw
.
OpenIn
)
(
flags
uint32
,
handle
uint64
,
status
Status
)
{
defer
me
.
locked
()()
return
me
.
RawFileSystem
.
Open
(
header
,
input
)
func
(
fs
*
LockingRawFileSystem
)
Open
(
header
*
raw
.
InHeader
,
input
*
raw
.
OpenIn
)
(
flags
uint32
,
handle
uint64
,
status
Status
)
{
defer
fs
.
locked
()()
return
fs
.
RawFileSystem
.
Open
(
header
,
input
)
}
func
(
me
*
LockingRawFileSystem
)
SetAttr
(
header
*
raw
.
InHeader
,
input
*
raw
.
SetAttrIn
)
(
out
*
raw
.
AttrOut
,
code
Status
)
{
defer
me
.
locked
()()
return
me
.
RawFileSystem
.
SetAttr
(
header
,
input
)
func
(
fs
*
LockingRawFileSystem
)
SetAttr
(
header
*
raw
.
InHeader
,
input
*
raw
.
SetAttrIn
)
(
out
*
raw
.
AttrOut
,
code
Status
)
{
defer
fs
.
locked
()()
return
fs
.
RawFileSystem
.
SetAttr
(
header
,
input
)
}
func
(
me
*
LockingRawFileSystem
)
Readlink
(
header
*
raw
.
InHeader
)
(
out
[]
byte
,
code
Status
)
{
defer
me
.
locked
()()
return
me
.
RawFileSystem
.
Readlink
(
header
)
func
(
fs
*
LockingRawFileSystem
)
Readlink
(
header
*
raw
.
InHeader
)
(
out
[]
byte
,
code
Status
)
{
defer
fs
.
locked
()()
return
fs
.
RawFileSystem
.
Readlink
(
header
)
}
func
(
me
*
LockingRawFileSystem
)
Mknod
(
header
*
raw
.
InHeader
,
input
*
raw
.
MknodIn
,
name
string
)
(
out
*
raw
.
EntryOut
,
code
Status
)
{
defer
me
.
locked
()()
return
me
.
RawFileSystem
.
Mknod
(
header
,
input
,
name
)
func
(
fs
*
LockingRawFileSystem
)
Mknod
(
header
*
raw
.
InHeader
,
input
*
raw
.
MknodIn
,
name
string
)
(
out
*
raw
.
EntryOut
,
code
Status
)
{
defer
fs
.
locked
()()
return
fs
.
RawFileSystem
.
Mknod
(
header
,
input
,
name
)
}
func
(
me
*
LockingRawFileSystem
)
Mkdir
(
header
*
raw
.
InHeader
,
input
*
raw
.
MkdirIn
,
name
string
)
(
out
*
raw
.
EntryOut
,
code
Status
)
{
defer
me
.
locked
()()
return
me
.
RawFileSystem
.
Mkdir
(
header
,
input
,
name
)
func
(
fs
*
LockingRawFileSystem
)
Mkdir
(
header
*
raw
.
InHeader
,
input
*
raw
.
MkdirIn
,
name
string
)
(
out
*
raw
.
EntryOut
,
code
Status
)
{
defer
fs
.
locked
()()
return
fs
.
RawFileSystem
.
Mkdir
(
header
,
input
,
name
)
}
func
(
me
*
LockingRawFileSystem
)
Unlink
(
header
*
raw
.
InHeader
,
name
string
)
(
code
Status
)
{
defer
me
.
locked
()()
return
me
.
RawFileSystem
.
Unlink
(
header
,
name
)
func
(
fs
*
LockingRawFileSystem
)
Unlink
(
header
*
raw
.
InHeader
,
name
string
)
(
code
Status
)
{
defer
fs
.
locked
()()
return
fs
.
RawFileSystem
.
Unlink
(
header
,
name
)
}
func
(
me
*
LockingRawFileSystem
)
Rmdir
(
header
*
raw
.
InHeader
,
name
string
)
(
code
Status
)
{
defer
me
.
locked
()()
return
me
.
RawFileSystem
.
Rmdir
(
header
,
name
)
func
(
fs
*
LockingRawFileSystem
)
Rmdir
(
header
*
raw
.
InHeader
,
name
string
)
(
code
Status
)
{
defer
fs
.
locked
()()
return
fs
.
RawFileSystem
.
Rmdir
(
header
,
name
)
}
func
(
me
*
LockingRawFileSystem
)
Symlink
(
header
*
raw
.
InHeader
,
pointedTo
string
,
linkName
string
)
(
out
*
raw
.
EntryOut
,
code
Status
)
{
defer
me
.
locked
()()
return
me
.
RawFileSystem
.
Symlink
(
header
,
pointedTo
,
linkName
)
func
(
fs
*
LockingRawFileSystem
)
Symlink
(
header
*
raw
.
InHeader
,
pointedTo
string
,
linkName
string
)
(
out
*
raw
.
EntryOut
,
code
Status
)
{
defer
fs
.
locked
()()
return
fs
.
RawFileSystem
.
Symlink
(
header
,
pointedTo
,
linkName
)
}
func
(
me
*
LockingRawFileSystem
)
Rename
(
header
*
raw
.
InHeader
,
input
*
raw
.
RenameIn
,
oldName
string
,
newName
string
)
(
code
Status
)
{
defer
me
.
locked
()()
return
me
.
RawFileSystem
.
Rename
(
header
,
input
,
oldName
,
newName
)
func
(
fs
*
LockingRawFileSystem
)
Rename
(
header
*
raw
.
InHeader
,
input
*
raw
.
RenameIn
,
oldName
string
,
newName
string
)
(
code
Status
)
{
defer
fs
.
locked
()()
return
fs
.
RawFileSystem
.
Rename
(
header
,
input
,
oldName
,
newName
)
}
func
(
me
*
LockingRawFileSystem
)
Link
(
header
*
raw
.
InHeader
,
input
*
raw
.
LinkIn
,
name
string
)
(
out
*
raw
.
EntryOut
,
code
Status
)
{
defer
me
.
locked
()()
return
me
.
RawFileSystem
.
Link
(
header
,
input
,
name
)
func
(
fs
*
LockingRawFileSystem
)
Link
(
header
*
raw
.
InHeader
,
input
*
raw
.
LinkIn
,
name
string
)
(
out
*
raw
.
EntryOut
,
code
Status
)
{
defer
fs
.
locked
()()
return
fs
.
RawFileSystem
.
Link
(
header
,
input
,
name
)
}
func
(
me
*
LockingRawFileSystem
)
SetXAttr
(
header
*
raw
.
InHeader
,
input
*
raw
.
SetXAttrIn
,
attr
string
,
data
[]
byte
)
Status
{
defer
me
.
locked
()()
return
me
.
RawFileSystem
.
SetXAttr
(
header
,
input
,
attr
,
data
)
func
(
fs
*
LockingRawFileSystem
)
SetXAttr
(
header
*
raw
.
InHeader
,
input
*
raw
.
SetXAttrIn
,
attr
string
,
data
[]
byte
)
Status
{
defer
fs
.
locked
()()
return
fs
.
RawFileSystem
.
SetXAttr
(
header
,
input
,
attr
,
data
)
}
func
(
me
*
LockingRawFileSystem
)
GetXAttrData
(
header
*
raw
.
InHeader
,
attr
string
)
(
data
[]
byte
,
code
Status
)
{
defer
me
.
locked
()()
return
me
.
RawFileSystem
.
GetXAttrData
(
header
,
attr
)
func
(
fs
*
LockingRawFileSystem
)
GetXAttrData
(
header
*
raw
.
InHeader
,
attr
string
)
(
data
[]
byte
,
code
Status
)
{
defer
fs
.
locked
()()
return
fs
.
RawFileSystem
.
GetXAttrData
(
header
,
attr
)
}
func
(
me
*
LockingRawFileSystem
)
GetXAttrSize
(
header
*
raw
.
InHeader
,
attr
string
)
(
sz
int
,
code
Status
)
{
defer
me
.
locked
()()
return
me
.
RawFileSystem
.
GetXAttrSize
(
header
,
attr
)
func
(
fs
*
LockingRawFileSystem
)
GetXAttrSize
(
header
*
raw
.
InHeader
,
attr
string
)
(
sz
int
,
code
Status
)
{
defer
fs
.
locked
()()
return
fs
.
RawFileSystem
.
GetXAttrSize
(
header
,
attr
)
}
func
(
me
*
LockingRawFileSystem
)
ListXAttr
(
header
*
raw
.
InHeader
)
(
data
[]
byte
,
code
Status
)
{
defer
me
.
locked
()()
return
me
.
RawFileSystem
.
ListXAttr
(
header
)
func
(
fs
*
LockingRawFileSystem
)
ListXAttr
(
header
*
raw
.
InHeader
)
(
data
[]
byte
,
code
Status
)
{
defer
fs
.
locked
()()
return
fs
.
RawFileSystem
.
ListXAttr
(
header
)
}
func
(
me
*
LockingRawFileSystem
)
RemoveXAttr
(
header
*
raw
.
InHeader
,
attr
string
)
Status
{
defer
me
.
locked
()()
return
me
.
RawFileSystem
.
RemoveXAttr
(
header
,
attr
)
func
(
fs
*
LockingRawFileSystem
)
RemoveXAttr
(
header
*
raw
.
InHeader
,
attr
string
)
Status
{
defer
fs
.
locked
()()
return
fs
.
RawFileSystem
.
RemoveXAttr
(
header
,
attr
)
}
func
(
me
*
LockingRawFileSystem
)
Access
(
header
*
raw
.
InHeader
,
input
*
raw
.
AccessIn
)
(
code
Status
)
{
defer
me
.
locked
()()
return
me
.
RawFileSystem
.
Access
(
header
,
input
)
func
(
fs
*
LockingRawFileSystem
)
Access
(
header
*
raw
.
InHeader
,
input
*
raw
.
AccessIn
)
(
code
Status
)
{
defer
fs
.
locked
()()
return
fs
.
RawFileSystem
.
Access
(
header
,
input
)
}
func
(
me
*
LockingRawFileSystem
)
Create
(
header
*
raw
.
InHeader
,
input
*
raw
.
CreateIn
,
name
string
)
(
flags
uint32
,
handle
uint64
,
out
*
raw
.
EntryOut
,
code
Status
)
{
defer
me
.
locked
()()
return
me
.
RawFileSystem
.
Create
(
header
,
input
,
name
)
func
(
fs
*
LockingRawFileSystem
)
Create
(
header
*
raw
.
InHeader
,
input
*
raw
.
CreateIn
,
name
string
)
(
flags
uint32
,
handle
uint64
,
out
*
raw
.
EntryOut
,
code
Status
)
{
defer
fs
.
locked
()()
return
fs
.
RawFileSystem
.
Create
(
header
,
input
,
name
)
}
func
(
me
*
LockingRawFileSystem
)
OpenDir
(
header
*
raw
.
InHeader
,
input
*
raw
.
OpenIn
)
(
flags
uint32
,
h
uint64
,
status
Status
)
{
defer
me
.
locked
()()
return
me
.
RawFileSystem
.
OpenDir
(
header
,
input
)
func
(
fs
*
LockingRawFileSystem
)
OpenDir
(
header
*
raw
.
InHeader
,
input
*
raw
.
OpenIn
)
(
flags
uint32
,
h
uint64
,
status
Status
)
{
defer
fs
.
locked
()()
return
fs
.
RawFileSystem
.
OpenDir
(
header
,
input
)
}
func
(
me
*
LockingRawFileSystem
)
Release
(
header
*
raw
.
InHeader
,
input
*
raw
.
ReleaseIn
)
{
defer
me
.
locked
()()
me
.
RawFileSystem
.
Release
(
header
,
input
)
func
(
fs
*
LockingRawFileSystem
)
Release
(
header
*
raw
.
InHeader
,
input
*
raw
.
ReleaseIn
)
{
defer
fs
.
locked
()()
fs
.
RawFileSystem
.
Release
(
header
,
input
)
}
func
(
me
*
LockingRawFileSystem
)
ReleaseDir
(
header
*
raw
.
InHeader
,
h
*
raw
.
ReleaseIn
)
{
defer
me
.
locked
()()
me
.
RawFileSystem
.
ReleaseDir
(
header
,
h
)
func
(
fs
*
LockingRawFileSystem
)
ReleaseDir
(
header
*
raw
.
InHeader
,
h
*
raw
.
ReleaseIn
)
{
defer
fs
.
locked
()()
fs
.
RawFileSystem
.
ReleaseDir
(
header
,
h
)
}
func
(
me
*
LockingRawFileSystem
)
Read
(
header
*
raw
.
InHeader
,
input
*
ReadIn
,
bp
BufferPool
)
([]
byte
,
Status
)
{
defer
me
.
locked
()()
return
me
.
RawFileSystem
.
Read
(
header
,
input
,
bp
)
func
(
fs
*
LockingRawFileSystem
)
Read
(
header
*
raw
.
InHeader
,
input
*
ReadIn
,
bp
BufferPool
)
([]
byte
,
Status
)
{
defer
fs
.
locked
()()
return
fs
.
RawFileSystem
.
Read
(
header
,
input
,
bp
)
}
func
(
me
*
LockingRawFileSystem
)
Write
(
header
*
raw
.
InHeader
,
input
*
WriteIn
,
data
[]
byte
)
(
written
uint32
,
code
Status
)
{
defer
me
.
locked
()()
return
me
.
RawFileSystem
.
Write
(
header
,
input
,
data
)
func
(
fs
*
LockingRawFileSystem
)
Write
(
header
*
raw
.
InHeader
,
input
*
WriteIn
,
data
[]
byte
)
(
written
uint32
,
code
Status
)
{
defer
fs
.
locked
()()
return
fs
.
RawFileSystem
.
Write
(
header
,
input
,
data
)
}
func
(
me
*
LockingRawFileSystem
)
Flush
(
header
*
raw
.
InHeader
,
input
*
raw
.
FlushIn
)
Status
{
defer
me
.
locked
()()
return
me
.
RawFileSystem
.
Flush
(
header
,
input
)
func
(
fs
*
LockingRawFileSystem
)
Flush
(
header
*
raw
.
InHeader
,
input
*
raw
.
FlushIn
)
Status
{
defer
fs
.
locked
()()
return
fs
.
RawFileSystem
.
Flush
(
header
,
input
)
}
func
(
me
*
LockingRawFileSystem
)
Fsync
(
header
*
raw
.
InHeader
,
input
*
raw
.
FsyncIn
)
(
code
Status
)
{
defer
me
.
locked
()()
return
me
.
RawFileSystem
.
Fsync
(
header
,
input
)
func
(
fs
*
LockingRawFileSystem
)
Fsync
(
header
*
raw
.
InHeader
,
input
*
raw
.
FsyncIn
)
(
code
Status
)
{
defer
fs
.
locked
()()
return
fs
.
RawFileSystem
.
Fsync
(
header
,
input
)
}
func
(
me
*
LockingRawFileSystem
)
ReadDir
(
header
*
raw
.
InHeader
,
input
*
ReadIn
)
(
*
DirEntryList
,
Status
)
{
defer
me
.
locked
()()
return
me
.
RawFileSystem
.
ReadDir
(
header
,
input
)
func
(
fs
*
LockingRawFileSystem
)
ReadDir
(
header
*
raw
.
InHeader
,
input
*
ReadIn
)
(
*
DirEntryList
,
Status
)
{
defer
fs
.
locked
()()
return
fs
.
RawFileSystem
.
ReadDir
(
header
,
input
)
}
func
(
me
*
LockingRawFileSystem
)
FsyncDir
(
header
*
raw
.
InHeader
,
input
*
raw
.
FsyncIn
)
(
code
Status
)
{
defer
me
.
locked
()()
return
me
.
RawFileSystem
.
FsyncDir
(
header
,
input
)
func
(
fs
*
LockingRawFileSystem
)
FsyncDir
(
header
*
raw
.
InHeader
,
input
*
raw
.
FsyncIn
)
(
code
Status
)
{
defer
fs
.
locked
()()
return
fs
.
RawFileSystem
.
FsyncDir
(
header
,
input
)
}
fuse/loopback.go
View file @
ce603372
...
...
@@ -32,12 +32,12 @@ func NewLoopbackFileSystem(root string) (out *LoopbackFileSystem) {
return
out
}
func
(
me
*
LoopbackFileSystem
)
GetPath
(
relPath
string
)
string
{
return
filepath
.
Join
(
me
.
Root
,
relPath
)
func
(
fs
*
LoopbackFileSystem
)
GetPath
(
relPath
string
)
string
{
return
filepath
.
Join
(
fs
.
Root
,
relPath
)
}
func
(
me
*
LoopbackFileSystem
)
GetAttr
(
name
string
,
context
*
Context
)
(
a
*
Attr
,
code
Status
)
{
fullPath
:=
me
.
GetPath
(
name
)
func
(
fs
*
LoopbackFileSystem
)
GetAttr
(
name
string
,
context
*
Context
)
(
a
*
Attr
,
code
Status
)
{
fullPath
:=
fs
.
GetPath
(
name
)
var
err
error
=
nil
st
:=
syscall
.
Stat_t
{}
if
name
==
""
{
...
...
@@ -55,10 +55,10 @@ func (me *LoopbackFileSystem) GetAttr(name string, context *Context) (a *Attr, c
return
a
,
OK
}
func
(
me
*
LoopbackFileSystem
)
OpenDir
(
name
string
,
context
*
Context
)
(
stream
chan
DirEntry
,
status
Status
)
{
func
(
fs
*
LoopbackFileSystem
)
OpenDir
(
name
string
,
context
*
Context
)
(
stream
chan
DirEntry
,
status
Status
)
{
// What other ways beyond O_RDONLY are there to open
// directories?
f
,
err
:=
os
.
Open
(
me
.
GetPath
(
name
))
f
,
err
:=
os
.
Open
(
fs
.
GetPath
(
name
))
if
err
!=
nil
{
return
nil
,
ToStatus
(
err
)
}
...
...
@@ -94,99 +94,99 @@ func (me *LoopbackFileSystem) OpenDir(name string, context *Context) (stream cha
return
output
,
OK
}
func
(
me
*
LoopbackFileSystem
)
Open
(
name
string
,
flags
uint32
,
context
*
Context
)
(
fuseFile
File
,
status
Status
)
{
f
,
err
:=
os
.
OpenFile
(
me
.
GetPath
(
name
),
int
(
flags
),
0
)
func
(
fs
*
LoopbackFileSystem
)
Open
(
name
string
,
flags
uint32
,
context
*
Context
)
(
fuseFile
File
,
status
Status
)
{
f
,
err
:=
os
.
OpenFile
(
fs
.
GetPath
(
name
),
int
(
flags
),
0
)
if
err
!=
nil
{
return
nil
,
ToStatus
(
err
)
}
return
&
LoopbackFile
{
File
:
f
},
OK
}
func
(
me
*
LoopbackFileSystem
)
Chmod
(
path
string
,
mode
uint32
,
context
*
Context
)
(
code
Status
)
{
err
:=
os
.
Chmod
(
me
.
GetPath
(
path
),
os
.
FileMode
(
mode
))
func
(
fs
*
LoopbackFileSystem
)
Chmod
(
path
string
,
mode
uint32
,
context
*
Context
)
(
code
Status
)
{
err
:=
os
.
Chmod
(
fs
.
GetPath
(
path
),
os
.
FileMode
(
mode
))
return
ToStatus
(
err
)
}
func
(
me
*
LoopbackFileSystem
)
Chown
(
path
string
,
uid
uint32
,
gid
uint32
,
context
*
Context
)
(
code
Status
)
{
return
ToStatus
(
os
.
Chown
(
me
.
GetPath
(
path
),
int
(
uid
),
int
(
gid
)))
func
(
fs
*
LoopbackFileSystem
)
Chown
(
path
string
,
uid
uint32
,
gid
uint32
,
context
*
Context
)
(
code
Status
)
{
return
ToStatus
(
os
.
Chown
(
fs
.
GetPath
(
path
),
int
(
uid
),
int
(
gid
)))
}
func
(
me
*
LoopbackFileSystem
)
Truncate
(
path
string
,
offset
uint64
,
context
*
Context
)
(
code
Status
)
{
return
ToStatus
(
os
.
Truncate
(
me
.
GetPath
(
path
),
int64
(
offset
)))
func
(
fs
*
LoopbackFileSystem
)
Truncate
(
path
string
,
offset
uint64
,
context
*
Context
)
(
code
Status
)
{
return
ToStatus
(
os
.
Truncate
(
fs
.
GetPath
(
path
),
int64
(
offset
)))
}
func
(
me
*
LoopbackFileSystem
)
Utimens
(
path
string
,
AtimeNs
int64
,
MtimeNs
int64
,
context
*
Context
)
(
code
Status
)
{
return
ToStatus
(
os
.
Chtimes
(
me
.
GetPath
(
path
),
time
.
Unix
(
0
,
AtimeNs
),
time
.
Unix
(
0
,
MtimeNs
)))
func
(
fs
*
LoopbackFileSystem
)
Utimens
(
path
string
,
AtimeNs
int64
,
MtimeNs
int64
,
context
*
Context
)
(
code
Status
)
{
return
ToStatus
(
os
.
Chtimes
(
fs
.
GetPath
(
path
),
time
.
Unix
(
0
,
AtimeNs
),
time
.
Unix
(
0
,
MtimeNs
)))
}
func
(
me
*
LoopbackFileSystem
)
Readlink
(
name
string
,
context
*
Context
)
(
out
string
,
code
Status
)
{
f
,
err
:=
os
.
Readlink
(
me
.
GetPath
(
name
))
func
(
fs
*
LoopbackFileSystem
)
Readlink
(
name
string
,
context
*
Context
)
(
out
string
,
code
Status
)
{
f
,
err
:=
os
.
Readlink
(
fs
.
GetPath
(
name
))
return
f
,
ToStatus
(
err
)
}
func
(
me
*
LoopbackFileSystem
)
Mknod
(
name
string
,
mode
uint32
,
dev
uint32
,
context
*
Context
)
(
code
Status
)
{
return
ToStatus
(
syscall
.
Mknod
(
me
.
GetPath
(
name
),
mode
,
int
(
dev
)))
func
(
fs
*
LoopbackFileSystem
)
Mknod
(
name
string
,
mode
uint32
,
dev
uint32
,
context
*
Context
)
(
code
Status
)
{
return
ToStatus
(
syscall
.
Mknod
(
fs
.
GetPath
(
name
),
mode
,
int
(
dev
)))
}
func
(
me
*
LoopbackFileSystem
)
Mkdir
(
path
string
,
mode
uint32
,
context
*
Context
)
(
code
Status
)
{
return
ToStatus
(
os
.
Mkdir
(
me
.
GetPath
(
path
),
os
.
FileMode
(
mode
)))
func
(
fs
*
LoopbackFileSystem
)
Mkdir
(
path
string
,
mode
uint32
,
context
*
Context
)
(
code
Status
)
{
return
ToStatus
(
os
.
Mkdir
(
fs
.
GetPath
(
path
),
os
.
FileMode
(
mode
)))
}
// Don't use os.Remove, it removes twice (unlink followed by rmdir).
func
(
me
*
LoopbackFileSystem
)
Unlink
(
name
string
,
context
*
Context
)
(
code
Status
)
{
return
ToStatus
(
syscall
.
Unlink
(
me
.
GetPath
(
name
)))
func
(
fs
*
LoopbackFileSystem
)
Unlink
(
name
string
,
context
*
Context
)
(
code
Status
)
{
return
ToStatus
(
syscall
.
Unlink
(
fs
.
GetPath
(
name
)))
}
func
(
me
*
LoopbackFileSystem
)
Rmdir
(
name
string
,
context
*
Context
)
(
code
Status
)
{
return
ToStatus
(
syscall
.
Rmdir
(
me
.
GetPath
(
name
)))
func
(
fs
*
LoopbackFileSystem
)
Rmdir
(
name
string
,
context
*
Context
)
(
code
Status
)
{
return
ToStatus
(
syscall
.
Rmdir
(
fs
.
GetPath
(
name
)))
}
func
(
me
*
LoopbackFileSystem
)
Symlink
(
pointedTo
string
,
linkName
string
,
context
*
Context
)
(
code
Status
)
{
return
ToStatus
(
os
.
Symlink
(
pointedTo
,
me
.
GetPath
(
linkName
)))
func
(
fs
*
LoopbackFileSystem
)
Symlink
(
pointedTo
string
,
linkName
string
,
context
*
Context
)
(
code
Status
)
{
return
ToStatus
(
os
.
Symlink
(
pointedTo
,
fs
.
GetPath
(
linkName
)))
}
func
(
me
*
LoopbackFileSystem
)
Rename
(
oldPath
string
,
newPath
string
,
context
*
Context
)
(
code
Status
)
{
err
:=
os
.
Rename
(
me
.
GetPath
(
oldPath
),
me
.
GetPath
(
newPath
))
func
(
fs
*
LoopbackFileSystem
)
Rename
(
oldPath
string
,
newPath
string
,
context
*
Context
)
(
code
Status
)
{
err
:=
os
.
Rename
(
fs
.
GetPath
(
oldPath
),
fs
.
GetPath
(
newPath
))
return
ToStatus
(
err
)
}
func
(
me
*
LoopbackFileSystem
)
Link
(
orig
string
,
newName
string
,
context
*
Context
)
(
code
Status
)
{
return
ToStatus
(
os
.
Link
(
me
.
GetPath
(
orig
),
me
.
GetPath
(
newName
)))
func
(
fs
*
LoopbackFileSystem
)
Link
(
orig
string
,
newName
string
,
context
*
Context
)
(
code
Status
)
{
return
ToStatus
(
os
.
Link
(
fs
.
GetPath
(
orig
),
fs
.
GetPath
(
newName
)))
}
func
(
me
*
LoopbackFileSystem
)
Access
(
name
string
,
mode
uint32
,
context
*
Context
)
(
code
Status
)
{
return
ToStatus
(
syscall
.
Access
(
me
.
GetPath
(
name
),
mode
))
func
(
fs
*
LoopbackFileSystem
)
Access
(
name
string
,
mode
uint32
,
context
*
Context
)
(
code
Status
)
{
return
ToStatus
(
syscall
.
Access
(
fs
.
GetPath
(
name
),
mode
))
}
func
(
me
*
LoopbackFileSystem
)
Create
(
path
string
,
flags
uint32
,
mode
uint32
,
context
*
Context
)
(
fuseFile
File
,
code
Status
)
{
f
,
err
:=
os
.
OpenFile
(
me
.
GetPath
(
path
),
int
(
flags
)
|
os
.
O_CREATE
,
os
.
FileMode
(
mode
))
func
(
fs
*
LoopbackFileSystem
)
Create
(
path
string
,
flags
uint32
,
mode
uint32
,
context
*
Context
)
(
fuseFile
File
,
code
Status
)
{
f
,
err
:=
os
.
OpenFile
(
fs
.
GetPath
(
path
),
int
(
flags
)
|
os
.
O_CREATE
,
os
.
FileMode
(
mode
))
return
&
LoopbackFile
{
File
:
f
},
ToStatus
(
err
)
}
func
(
me
*
LoopbackFileSystem
)
GetXAttr
(
name
string
,
attr
string
,
context
*
Context
)
([]
byte
,
Status
)
{
func
(
fs
*
LoopbackFileSystem
)
GetXAttr
(
name
string
,
attr
string
,
context
*
Context
)
([]
byte
,
Status
)
{
data
:=
make
([]
byte
,
1024
)
data
,
errNo
:=
GetXAttr
(
me
.
GetPath
(
name
),
attr
,
data
)
data
,
errNo
:=
GetXAttr
(
fs
.
GetPath
(
name
),
attr
,
data
)
return
data
,
Status
(
errNo
)
}
func
(
me
*
LoopbackFileSystem
)
ListXAttr
(
name
string
,
context
*
Context
)
([]
string
,
Status
)
{
data
,
errNo
:=
ListXAttr
(
me
.
GetPath
(
name
))
func
(
fs
*
LoopbackFileSystem
)
ListXAttr
(
name
string
,
context
*
Context
)
([]
string
,
Status
)
{
data
,
errNo
:=
ListXAttr
(
fs
.
GetPath
(
name
))
return
data
,
Status
(
errNo
)
}
func
(
me
*
LoopbackFileSystem
)
RemoveXAttr
(
name
string
,
attr
string
,
context
*
Context
)
Status
{
return
Status
(
Removexattr
(
me
.
GetPath
(
name
),
attr
))
func
(
fs
*
LoopbackFileSystem
)
RemoveXAttr
(
name
string
,
attr
string
,
context
*
Context
)
Status
{
return
Status
(
Removexattr
(
fs
.
GetPath
(
name
),
attr
))
}
func
(
me
*
LoopbackFileSystem
)
String
()
string
{
return
fmt
.
Sprintf
(
"LoopbackFileSystem(%s)"
,
me
.
Root
)
func
(
fs
*
LoopbackFileSystem
)
String
()
string
{
return
fmt
.
Sprintf
(
"LoopbackFileSystem(%s)"
,
fs
.
Root
)
}
func
(
me
*
LoopbackFileSystem
)
StatFs
(
name
string
)
*
StatfsOut
{
func
(
fs
*
LoopbackFileSystem
)
StatFs
(
name
string
)
*
StatfsOut
{
s
:=
syscall
.
Statfs_t
{}
err
:=
syscall
.
Statfs
(
me
.
GetPath
(
name
),
&
s
)
err
:=
syscall
.
Statfs
(
fs
.
GetPath
(
name
),
&
s
)
if
err
==
nil
{
return
&
StatfsOut
{
raw
.
Kstatfs
{
...
...
fuse/loopback_test.go
View file @
ce603372
...
...
@@ -96,14 +96,14 @@ func NewTestCase(t *testing.T) *testCase {
}
// Unmount and del.
func
(
me
*
testCase
)
Cleanup
()
{
err
:=
me
.
state
.
Unmount
()
func
(
tc
*
testCase
)
Cleanup
()
{
err
:=
tc
.
state
.
Unmount
()
CheckSuccess
(
err
)
os
.
RemoveAll
(
me
.
tmpDir
)
os
.
RemoveAll
(
tc
.
tmpDir
)
}
func
(
me
*
testCase
)
rootNode
()
*
Inode
{
return
me
.
pathFs
.
Root
()
.
Inode
()
func
(
tc
*
testCase
)
rootNode
()
*
Inode
{
return
tc
.
pathFs
.
Root
()
.
Inode
()
}
////////////////
...
...
@@ -135,7 +135,7 @@ func TestTouch(t *testing.T) {
}
}
func
(
me
*
testCase
)
TestReadThrough
(
t
*
testing
.
T
)
{
func
(
tc
*
testCase
)
TestReadThrough
(
t
*
testing
.
T
)
{
ts
:=
NewTestCase
(
t
)
defer
ts
.
Cleanup
()
...
...
@@ -166,26 +166,26 @@ func (me *testCase) TestReadThrough(t *testing.T) {
}
func
TestRemove
(
t
*
testing
.
T
)
{
me
:=
NewTestCase
(
t
)
defer
me
.
Cleanup
()
tc
:=
NewTestCase
(
t
)
defer
tc
.
Cleanup
()
err
:=
ioutil
.
WriteFile
(
me
.
origFile
,
[]
byte
(
contents
),
0700
)
err
:=
ioutil
.
WriteFile
(
tc
.
origFile
,
[]
byte
(
contents
),
0700
)
CheckSuccess
(
err
)
err
=
os
.
Remove
(
me
.
mountFile
)
err
=
os
.
Remove
(
tc
.
mountFile
)
CheckSuccess
(
err
)
_
,
err
=
os
.
Lstat
(
me
.
origFile
)
_
,
err
=
os
.
Lstat
(
tc
.
origFile
)
if
err
==
nil
{
t
.
Errorf
(
"Lstat() after delete should have generated error."
)
}
}
func
TestWriteThrough
(
t
*
testing
.
T
)
{
me
:=
NewTestCase
(
t
)
defer
me
.
Cleanup
()
tc
:=
NewTestCase
(
t
)
defer
tc
.
Cleanup
()
// Create (for write), write.
f
,
err
:=
os
.
OpenFile
(
me
.
mountFile
,
os
.
O_WRONLY
|
os
.
O_CREATE
,
0644
)
f
,
err
:=
os
.
OpenFile
(
tc
.
mountFile
,
os
.
O_WRONLY
|
os
.
O_CREATE
,
0644
)
CheckSuccess
(
err
)
defer
f
.
Close
()
...
...
@@ -195,12 +195,12 @@ func TestWriteThrough(t *testing.T) {
t
.
Errorf
(
"Write mismatch: %v of %v"
,
n
,
len
(
contents
))
}
fi
,
err
:=
os
.
Lstat
(
me
.
origFile
)
fi
,
err
:=
os
.
Lstat
(
tc
.
origFile
)
if
fi
.
Mode
()
.
Perm
()
!=
0644
{
t
.
Errorf
(
"create mode error %o"
,
fi
.
Mode
()
&
0777
)
}
f
,
err
=
os
.
Open
(
me
.
origFile
)
f
,
err
=
os
.
Open
(
tc
.
origFile
)
CheckSuccess
(
err
)
defer
f
.
Close
()
...
...
@@ -214,39 +214,39 @@ func TestWriteThrough(t *testing.T) {
}
func
TestMkdirRmdir
(
t
*
testing
.
T
)
{
me
:=
NewTestCase
(
t
)
defer
me
.
Cleanup
()
tc
:=
NewTestCase
(
t
)
defer
tc
.
Cleanup
()
// Mkdir/Rmdir.
err
:=
os
.
Mkdir
(
me
.
mountSubdir
,
0777
)
err
:=
os
.
Mkdir
(
tc
.
mountSubdir
,
0777
)
CheckSuccess
(
err
)
fi
,
err
:=
os
.
Lstat
(
me
.
origSubdir
)
fi
,
err
:=
os
.
Lstat
(
tc
.
origSubdir
)
if
!
fi
.
IsDir
()
{
t
.
Errorf
(
"Not a directory: %v"
,
fi
)
}
err
=
os
.
Remove
(
me
.
mountSubdir
)
err
=
os
.
Remove
(
tc
.
mountSubdir
)
CheckSuccess
(
err
)
}
func
TestLinkCreate
(
t
*
testing
.
T
)
{
me
:=
NewTestCase
(
t
)
defer
me
.
Cleanup
()
tc
:=
NewTestCase
(
t
)
defer
tc
.
Cleanup
()
err
:=
ioutil
.
WriteFile
(
me
.
origFile
,
[]
byte
(
contents
),
0700
)
err
:=
ioutil
.
WriteFile
(
tc
.
origFile
,
[]
byte
(
contents
),
0700
)
CheckSuccess
(
err
)
err
=
os
.
Mkdir
(
me
.
origSubdir
,
0777
)
err
=
os
.
Mkdir
(
tc
.
origSubdir
,
0777
)
CheckSuccess
(
err
)
// Link.
mountSubfile
:=
filepath
.
Join
(
me
.
mountSubdir
,
"subfile"
)
err
=
os
.
Link
(
me
.
mountFile
,
mountSubfile
)
mountSubfile
:=
filepath
.
Join
(
tc
.
mountSubdir
,
"subfile"
)
err
=
os
.
Link
(
tc
.
mountFile
,
mountSubfile
)
CheckSuccess
(
err
)
var
subStat
,
stat
syscall
.
Stat_t
err
=
syscall
.
Lstat
(
mountSubfile
,
&
subStat
)
CheckSuccess
(
err
)
err
=
syscall
.
Lstat
(
me
.
mountFile
,
&
stat
)
err
=
syscall
.
Lstat
(
tc
.
mountFile
,
&
stat
)
CheckSuccess
(
err
)
if
stat
.
Nlink
!=
2
{
...
...
@@ -262,7 +262,7 @@ func TestLinkCreate(t *testing.T) {
t
.
Errorf
(
"Content error: got %q want %q"
,
string
(
readback
),
contents
)
}
err
=
os
.
Remove
(
me
.
mountFile
)
err
=
os
.
Remove
(
tc
.
mountFile
)
CheckSuccess
(
err
)
_
,
err
=
ioutil
.
ReadFile
(
mountSubfile
)
...
...
@@ -272,27 +272,27 @@ func TestLinkCreate(t *testing.T) {
// Deal correctly with hard links implied by matching client inode
// numbers.
func
TestLinkExisting
(
t
*
testing
.
T
)
{
me
:=
NewTestCase
(
t
)
defer
me
.
Cleanup
()
tc
:=
NewTestCase
(
t
)
defer
tc
.
Cleanup
()
c
:=
"hello"
err
:=
ioutil
.
WriteFile
(
me
.
orig
+
"/file1"
,
[]
byte
(
c
),
0644
)
err
:=
ioutil
.
WriteFile
(
tc
.
orig
+
"/file1"
,
[]
byte
(
c
),
0644
)
CheckSuccess
(
err
)
err
=
os
.
Link
(
me
.
orig
+
"/file1"
,
me
.
orig
+
"/file2"
)
err
=
os
.
Link
(
tc
.
orig
+
"/file1"
,
tc
.
orig
+
"/file2"
)
CheckSuccess
(
err
)
var
s1
,
s2
syscall
.
Stat_t
err
=
syscall
.
Lstat
(
me
.
mnt
+
"/file1"
,
&
s1
)
err
=
syscall
.
Lstat
(
tc
.
mnt
+
"/file1"
,
&
s1
)
CheckSuccess
(
err
)
err
=
syscall
.
Lstat
(
me
.
mnt
+
"/file2"
,
&
s2
)
err
=
syscall
.
Lstat
(
tc
.
mnt
+
"/file2"
,
&
s2
)
CheckSuccess
(
err
)
if
s1
.
Ino
!=
s2
.
Ino
{
t
.
Errorf
(
"linked files should have identical inodes %v %v"
,
s1
.
Ino
,
s2
.
Ino
)
}
c1
,
err
:=
ioutil
.
ReadFile
(
me
.
mnt
+
"/file1"
)
c1
,
err
:=
ioutil
.
ReadFile
(
tc
.
mnt
+
"/file1"
)
CheckSuccess
(
err
)
if
string
(
c1
)
!=
c
{
t
.
Errorf
(
"Content mismatch relative to original."
)
...
...
@@ -302,23 +302,23 @@ func TestLinkExisting(t *testing.T) {
// Deal correctly with hard links implied by matching client inode
// numbers.
func
TestLinkForget
(
t
*
testing
.
T
)
{
me
:=
NewTestCase
(
t
)
defer
me
.
Cleanup
()
tc
:=
NewTestCase
(
t
)
defer
tc
.
Cleanup
()
c
:=
"hello"
err
:=
ioutil
.
WriteFile
(
me
.
orig
+
"/file1"
,
[]
byte
(
c
),
0644
)
err
:=
ioutil
.
WriteFile
(
tc
.
orig
+
"/file1"
,
[]
byte
(
c
),
0644
)
CheckSuccess
(
err
)
err
=
os
.
Link
(
me
.
orig
+
"/file1"
,
me
.
orig
+
"/file2"
)
err
=
os
.
Link
(
tc
.
orig
+
"/file1"
,
tc
.
orig
+
"/file2"
)
CheckSuccess
(
err
)
var
s1
,
s2
syscall
.
Stat_t
err
=
syscall
.
Lstat
(
me
.
mnt
+
"/file1"
,
&
s1
)
err
=
syscall
.
Lstat
(
tc
.
mnt
+
"/file1"
,
&
s1
)
CheckSuccess
(
err
)
me
.
pathFs
.
ForgetClientInodes
()
tc
.
pathFs
.
ForgetClientInodes
()
err
=
syscall
.
Lstat
(
me
.
mnt
+
"/file2"
,
&
s2
)
err
=
syscall
.
Lstat
(
tc
.
mnt
+
"/file2"
,
&
s2
)
CheckSuccess
(
err
)
if
s1
.
Ino
==
s2
.
Ino
{
t
.
Error
(
"After forget, we should not export links"
)
...
...
@@ -326,20 +326,20 @@ func TestLinkForget(t *testing.T) {
}
func
TestSymlink
(
t
*
testing
.
T
)
{
me
:=
NewTestCase
(
t
)
defer
me
.
Cleanup
()
tc
:=
NewTestCase
(
t
)
defer
tc
.
Cleanup
()
t
.
Log
(
"testing symlink/readlink."
)
err
:=
ioutil
.
WriteFile
(
me
.
origFile
,
[]
byte
(
contents
),
0700
)
err
:=
ioutil
.
WriteFile
(
tc
.
origFile
,
[]
byte
(
contents
),
0700
)
CheckSuccess
(
err
)
linkFile
:=
"symlink-file"
orig
:=
"hello.txt"
err
=
os
.
Symlink
(
orig
,
filepath
.
Join
(
me
.
mnt
,
linkFile
))
err
=
os
.
Symlink
(
orig
,
filepath
.
Join
(
tc
.
mnt
,
linkFile
))
CheckSuccess
(
err
)
origLink
:=
filepath
.
Join
(
me
.
orig
,
linkFile
)
origLink
:=
filepath
.
Join
(
tc
.
orig
,
linkFile
)
fi
,
err
:=
os
.
Lstat
(
origLink
)
CheckSuccess
(
err
)
...
...
@@ -348,7 +348,7 @@ func TestSymlink(t *testing.T) {
return
}
read
,
err
:=
os
.
Readlink
(
filepath
.
Join
(
me
.
mnt
,
linkFile
))
read
,
err
:=
os
.
Readlink
(
filepath
.
Join
(
tc
.
mnt
,
linkFile
))
CheckSuccess
(
err
)
if
read
!=
orig
{
...
...
@@ -357,21 +357,21 @@ func TestSymlink(t *testing.T) {
}
func
TestRename
(
t
*
testing
.
T
)
{
me
:=
NewTestCase
(
t
)
defer
me
.
Cleanup
()
tc
:=
NewTestCase
(
t
)
defer
tc
.
Cleanup
()
t
.
Log
(
"Testing rename."
)
err
:=
ioutil
.
WriteFile
(
me
.
origFile
,
[]
byte
(
contents
),
0700
)
err
:=
ioutil
.
WriteFile
(
tc
.
origFile
,
[]
byte
(
contents
),
0700
)
CheckSuccess
(
err
)
sd
:=
me
.
mnt
+
"/testRename"
sd
:=
tc
.
mnt
+
"/testRename"
err
=
os
.
MkdirAll
(
sd
,
0777
)
subFile
:=
sd
+
"/subfile"
err
=
os
.
Rename
(
me
.
mountFile
,
subFile
)
err
=
os
.
Rename
(
tc
.
mountFile
,
subFile
)
CheckSuccess
(
err
)
f
,
_
:=
os
.
Lstat
(
me
.
origFile
)
f
,
_
:=
os
.
Lstat
(
tc
.
origFile
)
if
f
!=
nil
{
t
.
Errorf
(
"original %v still exists."
,
me
.
origFile
)
t
.
Errorf
(
"original %v still exists."
,
tc
.
origFile
)
}
f
,
_
=
os
.
Lstat
(
subFile
)
if
f
==
nil
{
...
...
@@ -381,12 +381,12 @@ func TestRename(t *testing.T) {
// Flaky test, due to rename race condition.
func
TestDelRename
(
t
*
testing
.
T
)
{
me
:=
NewTestCase
(
t
)
defer
me
.
Cleanup
()
tc
:=
NewTestCase
(
t
)
defer
tc
.
Cleanup
()
t
.
Log
(
"Testing del+rename."
)
sd
:=
me
.
mnt
+
"/testDelRename"
sd
:=
tc
.
mnt
+
"/testDelRename"
err
:=
os
.
MkdirAll
(
sd
,
0755
)
CheckSuccess
(
err
)
...
...
@@ -410,12 +410,12 @@ func TestDelRename(t *testing.T) {
}
func
TestOverwriteRename
(
t
*
testing
.
T
)
{
me
:=
NewTestCase
(
t
)
defer
me
.
Cleanup
()
tc
:=
NewTestCase
(
t
)
defer
tc
.
Cleanup
()
t
.
Log
(
"Testing rename overwrite."
)
sd
:=
me
.
mnt
+
"/testOverwriteRename"
sd
:=
tc
.
mnt
+
"/testOverwriteRename"
err
:=
os
.
MkdirAll
(
sd
,
0755
)
CheckSuccess
(
err
)
...
...
@@ -436,54 +436,54 @@ func TestAccess(t *testing.T) {
t
.
Log
(
"Skipping TestAccess() as root."
)
return
}
me
:=
NewTestCase
(
t
)
defer
me
.
Cleanup
()
tc
:=
NewTestCase
(
t
)
defer
tc
.
Cleanup
()
err
:=
ioutil
.
WriteFile
(
me
.
origFile
,
[]
byte
(
contents
),
0700
)
err
:=
ioutil
.
WriteFile
(
tc
.
origFile
,
[]
byte
(
contents
),
0700
)
CheckSuccess
(
err
)
err
=
os
.
Chmod
(
me
.
origFile
,
0
)
err
=
os
.
Chmod
(
tc
.
origFile
,
0
)
CheckSuccess
(
err
)
// Ugh - copied from unistd.h
const
W_OK
uint32
=
2
errCode
:=
syscall
.
Access
(
me
.
mountFile
,
W_OK
)
errCode
:=
syscall
.
Access
(
tc
.
mountFile
,
W_OK
)
if
errCode
!=
syscall
.
EACCES
{
t
.
Errorf
(
"Expected EACCES for non-writable, %v %v"
,
errCode
,
syscall
.
EACCES
)
}
err
=
os
.
Chmod
(
me
.
origFile
,
0222
)
err
=
os
.
Chmod
(
tc
.
origFile
,
0222
)
CheckSuccess
(
err
)
errCode
=
syscall
.
Access
(
me
.
mountFile
,
W_OK
)
errCode
=
syscall
.
Access
(
tc
.
mountFile
,
W_OK
)
if
errCode
!=
nil
{
t
.
Errorf
(
"Expected no error code for writable. %v"
,
errCode
)
}
}
func
TestMknod
(
t
*
testing
.
T
)
{
me
:=
NewTestCase
(
t
)
defer
me
.
Cleanup
()
tc
:=
NewTestCase
(
t
)
defer
tc
.
Cleanup
()
t
.
Log
(
"Testing mknod."
)
errNo
:=
syscall
.
Mknod
(
me
.
mountFile
,
syscall
.
S_IFIFO
|
0777
,
0
)
errNo
:=
syscall
.
Mknod
(
tc
.
mountFile
,
syscall
.
S_IFIFO
|
0777
,
0
)
if
errNo
!=
nil
{
t
.
Errorf
(
"Mknod %v"
,
errNo
)
}
fi
,
_
:=
os
.
Lstat
(
me
.
origFile
)
fi
,
_
:=
os
.
Lstat
(
tc
.
origFile
)
if
fi
==
nil
||
fi
.
Mode
()
&
os
.
ModeNamedPipe
==
0
{
t
.
Errorf
(
"Expected FIFO filetype."
)
}
}
func
TestReaddir
(
t
*
testing
.
T
)
{
me
:=
NewTestCase
(
t
)
defer
me
.
Cleanup
()
tc
:=
NewTestCase
(
t
)
defer
tc
.
Cleanup
()
t
.
Log
(
"Testing readdir."
)
err
:=
ioutil
.
WriteFile
(
me
.
origFile
,
[]
byte
(
contents
),
0700
)
err
:=
ioutil
.
WriteFile
(
tc
.
origFile
,
[]
byte
(
contents
),
0700
)
CheckSuccess
(
err
)
err
=
os
.
Mkdir
(
me
.
origSubdir
,
0777
)
err
=
os
.
Mkdir
(
tc
.
origSubdir
,
0777
)
CheckSuccess
(
err
)
dir
,
err
:=
os
.
Open
(
me
.
mnt
)
dir
,
err
:=
os
.
Open
(
tc
.
mnt
)
CheckSuccess
(
err
)
infos
,
err
:=
dir
.
Readdir
(
10
)
CheckSuccess
(
err
)
...
...
@@ -507,14 +507,14 @@ func TestReaddir(t *testing.T) {
}
func
TestFSync
(
t
*
testing
.
T
)
{
me
:=
NewTestCase
(
t
)
defer
me
.
Cleanup
()
tc
:=
NewTestCase
(
t
)
defer
tc
.
Cleanup
()
t
.
Log
(
"Testing fsync."
)
err
:=
ioutil
.
WriteFile
(
me
.
origFile
,
[]
byte
(
contents
),
0700
)
err
:=
ioutil
.
WriteFile
(
tc
.
origFile
,
[]
byte
(
contents
),
0700
)
CheckSuccess
(
err
)
f
,
err
:=
os
.
OpenFile
(
me
.
mountFile
,
os
.
O_WRONLY
,
0
)
f
,
err
:=
os
.
OpenFile
(
tc
.
mountFile
,
os
.
O_WRONLY
,
0
)
_
,
err
=
f
.
WriteString
(
"hello there"
)
CheckSuccess
(
err
)
...
...
@@ -527,11 +527,11 @@ func TestFSync(t *testing.T) {
}
func
TestLargeRead
(
t
*
testing
.
T
)
{
me
:=
NewTestCase
(
t
)
defer
me
.
Cleanup
()
tc
:=
NewTestCase
(
t
)
defer
tc
.
Cleanup
()
t
.
Log
(
"Testing large read."
)
name
:=
filepath
.
Join
(
me
.
orig
,
"large"
)
name
:=
filepath
.
Join
(
tc
.
orig
,
"large"
)
f
,
err
:=
os
.
OpenFile
(
name
,
os
.
O_WRONLY
|
os
.
O_CREATE
,
0777
)
CheckSuccess
(
err
)
...
...
@@ -550,7 +550,7 @@ func TestLargeRead(t *testing.T) {
CheckSuccess
(
err
)
// Read in one go.
g
,
err
:=
os
.
Open
(
filepath
.
Join
(
me
.
mnt
,
"large"
))
g
,
err
:=
os
.
Open
(
filepath
.
Join
(
tc
.
mnt
,
"large"
))
CheckSuccess
(
err
)
readSlice
:=
make
([]
byte
,
len
(
slice
))
m
,
err
:=
g
.
Read
(
readSlice
)
...
...
@@ -568,7 +568,7 @@ func TestLargeRead(t *testing.T) {
g
.
Close
()
// Read in chunks
g
,
err
=
os
.
Open
(
filepath
.
Join
(
me
.
mnt
,
"large"
))
g
,
err
=
os
.
Open
(
filepath
.
Join
(
tc
.
mnt
,
"large"
))
CheckSuccess
(
err
)
defer
g
.
Close
()
readSlice
=
make
([]
byte
,
4096
)
...
...
@@ -599,15 +599,15 @@ func randomLengthString(length int) string {
}
func
TestLargeDirRead
(
t
*
testing
.
T
)
{
me
:=
NewTestCase
(
t
)
defer
me
.
Cleanup
()
tc
:=
NewTestCase
(
t
)
defer
tc
.
Cleanup
()
t
.
Log
(
"Testing large readdir."
)
created
:=
100
names
:=
make
([]
string
,
created
)
subdir
:=
filepath
.
Join
(
me
.
orig
,
"readdirSubdir"
)
subdir
:=
filepath
.
Join
(
tc
.
orig
,
"readdirSubdir"
)
os
.
Mkdir
(
subdir
,
0700
)
longname
:=
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
...
...
@@ -628,7 +628,7 @@ func TestLargeDirRead(t *testing.T) {
names
[
i
]
=
name
}
dir
,
err
:=
os
.
Open
(
filepath
.
Join
(
me
.
mnt
,
"readdirSubdir"
))
dir
,
err
:=
os
.
Open
(
filepath
.
Join
(
tc
.
mnt
,
"readdirSubdir"
))
CheckSuccess
(
err
)
defer
dir
.
Close
()
...
...
fuse/memnode.go
View file @
ce603372
...
...
@@ -19,25 +19,25 @@ type MemNodeFs struct {
nextFree
int
}
func
(
me
*
MemNodeFs
)
String
()
string
{
return
fmt
.
Sprintf
(
"MemNodeFs(%s)"
,
me
.
backingStorePrefix
)
func
(
fs
*
MemNodeFs
)
String
()
string
{
return
fmt
.
Sprintf
(
"MemNodeFs(%s)"
,
fs
.
backingStorePrefix
)
}
func
(
me
*
MemNodeFs
)
Root
()
FsNode
{
return
me
.
root
func
(
fs
*
MemNodeFs
)
Root
()
FsNode
{
return
fs
.
root
}
func
(
me
*
MemNodeFs
)
newNode
()
*
memNode
{
me
.
mutex
.
Lock
()
defer
me
.
mutex
.
Unlock
()
func
(
fs
*
MemNodeFs
)
newNode
()
*
memNode
{
fs
.
mutex
.
Lock
()
defer
fs
.
mutex
.
Unlock
()
n
:=
&
memNode
{
fs
:
me
,
id
:
me
.
nextFree
,
fs
:
fs
,
id
:
fs
.
nextFree
,
}
now
:=
time
.
Now
()
.
UnixNano
()
n
.
info
.
SetNs
(
now
,
now
,
now
)
n
.
info
.
Mode
=
S_IFDIR
|
0777
me
.
nextFree
++
fs
.
nextFree
++
return
n
}
...
...
@@ -48,7 +48,7 @@ func NewMemNodeFs(prefix string) *MemNodeFs {
return
me
}
func
(
me
*
MemNodeFs
)
Filename
(
n
*
Inode
)
string
{
func
(
fs
*
MemNodeFs
)
Filename
(
n
*
Inode
)
string
{
mn
:=
n
.
FsNode
()
.
(
*
memNode
)
return
mn
.
filename
()
}
...
...
@@ -62,75 +62,75 @@ type memNode struct {
info
Attr
}
func
(
me
*
memNode
)
newNode
(
isdir
bool
)
*
memNode
{
n
:=
me
.
fs
.
newNode
()
me
.
Inode
()
.
New
(
isdir
,
n
)
return
n
func
(
n
*
memNode
)
newNode
(
isdir
bool
)
*
memNode
{
n
ewNode
:=
n
.
fs
.
newNode
()
n
.
Inode
()
.
New
(
isdir
,
newNode
)
return
n
ewNode
}
func
(
me
*
memNode
)
filename
()
string
{
return
fmt
.
Sprintf
(
"%s%d"
,
me
.
fs
.
backingStorePrefix
,
me
.
id
)
func
(
n
*
memNode
)
filename
()
string
{
return
fmt
.
Sprintf
(
"%s%d"
,
n
.
fs
.
backingStorePrefix
,
n
.
id
)
}
func
(
me
*
memNode
)
Deletable
()
bool
{
func
(
n
*
memNode
)
Deletable
()
bool
{
return
false
}
func
(
me
*
memNode
)
Readlink
(
c
*
Context
)
([]
byte
,
Status
)
{
return
[]
byte
(
me
.
link
),
OK
func
(
n
*
memNode
)
Readlink
(
c
*
Context
)
([]
byte
,
Status
)
{
return
[]
byte
(
n
.
link
),
OK
}
func
(
me
*
memNode
)
Mkdir
(
name
string
,
mode
uint32
,
context
*
Context
)
(
fi
*
Attr
,
newNode
FsNode
,
code
Status
)
{
n
:=
me
.
newNode
(
true
)
n
.
info
.
Mode
=
mode
|
S_IFDIR
me
.
Inode
()
.
AddChild
(
name
,
n
.
Inode
())
return
&
n
.
info
,
n
,
OK
func
(
n
*
memNode
)
Mkdir
(
name
string
,
mode
uint32
,
context
*
Context
)
(
fi
*
Attr
,
newNode
FsNode
,
code
Status
)
{
ch
:=
n
.
newNode
(
true
)
ch
.
info
.
Mode
=
mode
|
S_IFDIR
n
.
Inode
()
.
AddChild
(
name
,
ch
.
Inode
())
return
&
ch
.
info
,
ch
,
OK
}
func
(
me
*
memNode
)
Unlink
(
name
string
,
context
*
Context
)
(
code
Status
)
{
ch
:=
me
.
Inode
()
.
RmChild
(
name
)
func
(
n
*
memNode
)
Unlink
(
name
string
,
context
*
Context
)
(
code
Status
)
{
ch
:=
n
.
Inode
()
.
RmChild
(
name
)
if
ch
==
nil
{
return
ENOENT
}
return
OK
}
func
(
me
*
memNode
)
Rmdir
(
name
string
,
context
*
Context
)
(
code
Status
)
{
return
me
.
Unlink
(
name
,
context
)
func
(
n
*
memNode
)
Rmdir
(
name
string
,
context
*
Context
)
(
code
Status
)
{
return
n
.
Unlink
(
name
,
context
)
}
func
(
me
*
memNode
)
Symlink
(
name
string
,
content
string
,
context
*
Context
)
(
fi
*
Attr
,
newNode
FsNode
,
code
Status
)
{
n
:=
me
.
newNode
(
false
)
n
.
info
.
Mode
=
S_IFLNK
|
0777
n
.
link
=
content
me
.
Inode
()
.
AddChild
(
name
,
n
.
Inode
())
func
(
n
*
memNode
)
Symlink
(
name
string
,
content
string
,
context
*
Context
)
(
fi
*
Attr
,
newNode
FsNode
,
code
Status
)
{
ch
:=
n
.
newNode
(
false
)
ch
.
info
.
Mode
=
S_IFLNK
|
0777
ch
.
link
=
content
n
.
Inode
()
.
AddChild
(
name
,
ch
.
Inode
())
return
&
n
.
info
,
n
,
OK
return
&
ch
.
info
,
ch
,
OK
}
func
(
me
*
memNode
)
Rename
(
oldName
string
,
newParent
FsNode
,
newName
string
,
context
*
Context
)
(
code
Status
)
{
ch
:=
me
.
Inode
()
.
RmChild
(
oldName
)
func
(
n
*
memNode
)
Rename
(
oldName
string
,
newParent
FsNode
,
newName
string
,
context
*
Context
)
(
code
Status
)
{
ch
:=
n
.
Inode
()
.
RmChild
(
oldName
)
newParent
.
Inode
()
.
RmChild
(
newName
)
newParent
.
Inode
()
.
AddChild
(
newName
,
ch
)
return
OK
}
func
(
me
*
memNode
)
Link
(
name
string
,
existing
FsNode
,
context
*
Context
)
(
fi
*
Attr
,
newNode
FsNode
,
code
Status
)
{
me
.
Inode
()
.
AddChild
(
name
,
existing
.
Inode
())
func
(
n
*
memNode
)
Link
(
name
string
,
existing
FsNode
,
context
*
Context
)
(
fi
*
Attr
,
newNode
FsNode
,
code
Status
)
{
n
.
Inode
()
.
AddChild
(
name
,
existing
.
Inode
())
fi
,
code
=
existing
.
GetAttr
(
nil
,
context
)
return
fi
,
existing
,
code
}
func
(
me
*
memNode
)
Create
(
name
string
,
flags
uint32
,
mode
uint32
,
context
*
Context
)
(
file
File
,
fi
*
Attr
,
newNode
FsNode
,
code
Status
)
{
n
:=
me
.
newNode
(
false
)
n
.
info
.
Mode
=
mode
|
S_IFREG
func
(
n
*
memNode
)
Create
(
name
string
,
flags
uint32
,
mode
uint32
,
context
*
Context
)
(
file
File
,
fi
*
Attr
,
newNode
FsNode
,
code
Status
)
{
ch
:=
n
.
newNode
(
false
)
ch
.
info
.
Mode
=
mode
|
S_IFREG
f
,
err
:=
os
.
Create
(
n
.
filename
())
if
err
!=
nil
{
return
nil
,
nil
,
nil
,
ToStatus
(
err
)
}
me
.
Inode
()
.
AddChild
(
name
,
n
.
Inode
())
return
n
.
newFile
(
f
),
&
n
.
info
,
n
,
OK
n
.
Inode
()
.
AddChild
(
name
,
ch
.
Inode
())
return
ch
.
newFile
(
f
),
&
ch
.
info
,
ch
,
OK
}
type
memNodeFile
struct
{
...
...
@@ -138,71 +138,71 @@ type memNodeFile struct {
node
*
memNode
}
func
(
me
*
memNodeFile
)
String
()
string
{
return
fmt
.
Sprintf
(
"memNodeFile(%s)"
,
me
.
LoopbackFile
.
String
())
func
(
n
*
memNodeFile
)
String
()
string
{
return
fmt
.
Sprintf
(
"memNodeFile(%s)"
,
n
.
LoopbackFile
.
String
())
}
func
(
me
*
memNodeFile
)
InnerFile
()
File
{
return
&
me
.
LoopbackFile
func
(
n
*
memNodeFile
)
InnerFile
()
File
{
return
&
n
.
LoopbackFile
}
func
(
me
*
memNodeFile
)
Flush
()
Status
{
code
:=
me
.
LoopbackFile
.
Flush
()
fi
,
_
:=
me
.
LoopbackFile
.
GetAttr
()
me
.
node
.
info
.
Size
=
fi
.
Size
me
.
node
.
info
.
Blocks
=
fi
.
Blocks
func
(
n
*
memNodeFile
)
Flush
()
Status
{
code
:=
n
.
LoopbackFile
.
Flush
()
fi
,
_
:=
n
.
LoopbackFile
.
GetAttr
()
n
.
node
.
info
.
Size
=
fi
.
Size
n
.
node
.
info
.
Blocks
=
fi
.
Blocks
return
code
}
func
(
me
*
memNode
)
newFile
(
f
*
os
.
File
)
File
{
func
(
n
*
memNode
)
newFile
(
f
*
os
.
File
)
File
{
return
&
memNodeFile
{
LoopbackFile
:
LoopbackFile
{
File
:
f
},
node
:
me
,
node
:
n
,
}
}
func
(
me
*
memNode
)
Open
(
flags
uint32
,
context
*
Context
)
(
file
File
,
code
Status
)
{
f
,
err
:=
os
.
OpenFile
(
me
.
filename
(),
int
(
flags
),
0666
)
func
(
n
*
memNode
)
Open
(
flags
uint32
,
context
*
Context
)
(
file
File
,
code
Status
)
{
f
,
err
:=
os
.
OpenFile
(
n
.
filename
(),
int
(
flags
),
0666
)
if
err
!=
nil
{
return
nil
,
ToStatus
(
err
)
}
return
me
.
newFile
(
f
),
OK
return
n
.
newFile
(
f
),
OK
}
func
(
me
*
memNode
)
GetAttr
(
file
File
,
context
*
Context
)
(
fi
*
Attr
,
code
Status
)
{
return
&
me
.
info
,
OK
func
(
n
*
memNode
)
GetAttr
(
file
File
,
context
*
Context
)
(
fi
*
Attr
,
code
Status
)
{
return
&
n
.
info
,
OK
}
func
(
me
*
memNode
)
Truncate
(
file
File
,
size
uint64
,
context
*
Context
)
(
code
Status
)
{
func
(
n
*
memNode
)
Truncate
(
file
File
,
size
uint64
,
context
*
Context
)
(
code
Status
)
{
if
file
!=
nil
{
code
=
file
.
Truncate
(
size
)
}
else
{
err
:=
os
.
Truncate
(
me
.
filename
(),
int64
(
size
))
err
:=
os
.
Truncate
(
n
.
filename
(),
int64
(
size
))
code
=
ToStatus
(
err
)
}
if
code
.
Ok
()
{
me
.
info
.
SetNs
(
-
1
,
-
1
,
time
.
Now
()
.
UnixNano
())
n
.
info
.
SetNs
(
-
1
,
-
1
,
time
.
Now
()
.
UnixNano
())
// TODO - should update mtime too?
me
.
info
.
Size
=
size
n
.
info
.
Size
=
size
}
return
code
}
func
(
me
*
memNode
)
Utimens
(
file
File
,
atime
int64
,
mtime
int64
,
context
*
Context
)
(
code
Status
)
{
me
.
info
.
SetNs
(
int64
(
atime
),
int64
(
mtime
),
time
.
Now
()
.
UnixNano
())
func
(
n
*
memNode
)
Utimens
(
file
File
,
atime
int64
,
mtime
int64
,
context
*
Context
)
(
code
Status
)
{
n
.
info
.
SetNs
(
int64
(
atime
),
int64
(
mtime
),
time
.
Now
()
.
UnixNano
())
return
OK
}
func
(
me
*
memNode
)
Chmod
(
file
File
,
perms
uint32
,
context
*
Context
)
(
code
Status
)
{
me
.
info
.
Mode
=
(
me
.
info
.
Mode
^
07777
)
|
perms
me
.
info
.
SetNs
(
-
1
,
-
1
,
time
.
Now
()
.
UnixNano
())
func
(
n
*
memNode
)
Chmod
(
file
File
,
perms
uint32
,
context
*
Context
)
(
code
Status
)
{
n
.
info
.
Mode
=
(
n
.
info
.
Mode
^
07777
)
|
perms
n
.
info
.
SetNs
(
-
1
,
-
1
,
time
.
Now
()
.
UnixNano
())
return
OK
}
func
(
me
*
memNode
)
Chown
(
file
File
,
uid
uint32
,
gid
uint32
,
context
*
Context
)
(
code
Status
)
{
me
.
info
.
Uid
=
uid
me
.
info
.
Gid
=
gid
me
.
info
.
SetNs
(
-
1
,
-
1
,
time
.
Now
()
.
UnixNano
())
func
(
n
*
memNode
)
Chown
(
file
File
,
uid
uint32
,
gid
uint32
,
context
*
Context
)
(
code
Status
)
{
n
.
info
.
Uid
=
uid
n
.
info
.
Gid
=
gid
n
.
info
.
SetNs
(
-
1
,
-
1
,
time
.
Now
()
.
UnixNano
())
return
OK
}
fuse/mountstate.go
View file @
ce603372
...
...
@@ -37,16 +37,16 @@ type MountState struct {
kernelSettings
raw
.
InitIn
}
func
(
m
e
*
MountState
)
KernelSettings
()
raw
.
InitIn
{
return
m
e
.
kernelSettings
func
(
m
s
*
MountState
)
KernelSettings
()
raw
.
InitIn
{
return
m
s
.
kernelSettings
}
func
(
m
e
*
MountState
)
MountPoint
()
string
{
return
m
e
.
mountPoint
func
(
m
s
*
MountState
)
MountPoint
()
string
{
return
m
s
.
mountPoint
}
// Mount filesystem on mountPoint.
func
(
m
e
*
MountState
)
Mount
(
mountPoint
string
,
opts
*
MountOptions
)
error
{
func
(
m
s
*
MountState
)
Mount
(
mountPoint
string
,
opts
*
MountOptions
)
error
{
if
opts
==
nil
{
opts
=
&
MountOptions
{
MaxBackground
:
_DEFAULT_BACKGROUND_TASKS
,
...
...
@@ -63,7 +63,7 @@ func (me *MountState) Mount(mountPoint string, opts *MountOptions) error {
o
.
MaxWrite
=
MAX_KERNEL_WRITE
}
opts
=
&
o
m
e
.
opts
=
&
o
m
s
.
opts
=
&
o
optStrs
:=
opts
.
Options
if
opts
.
AllowOther
{
...
...
@@ -76,33 +76,33 @@ func (me *MountState) Mount(mountPoint string, opts *MountOptions) error {
}
initParams
:=
RawFsInit
{
InodeNotify
:
func
(
n
*
raw
.
NotifyInvalInodeOut
)
Status
{
return
m
e
.
writeInodeNotify
(
n
)
return
m
s
.
writeInodeNotify
(
n
)
},
EntryNotify
:
func
(
parent
uint64
,
n
string
)
Status
{
return
m
e
.
writeEntryNotify
(
parent
,
n
)
return
m
s
.
writeEntryNotify
(
parent
,
n
)
},
}
m
e
.
fileSystem
.
Init
(
&
initParams
)
m
e
.
mountPoint
=
mp
m
e
.
mountFile
=
file
m
s
.
fileSystem
.
Init
(
&
initParams
)
m
s
.
mountPoint
=
mp
m
s
.
mountFile
=
file
return
nil
}
func
(
m
e
*
MountState
)
SetRecordStatistics
(
record
bool
)
{
func
(
m
s
*
MountState
)
SetRecordStatistics
(
record
bool
)
{
if
record
{
m
e
.
latencies
=
NewLatencyMap
()
m
s
.
latencies
=
NewLatencyMap
()
}
else
{
m
e
.
latencies
=
nil
m
s
.
latencies
=
nil
}
}
func
(
m
e
*
MountState
)
Unmount
()
(
err
error
)
{
if
m
e
.
mountPoint
==
""
{
func
(
m
s
*
MountState
)
Unmount
()
(
err
error
)
{
if
m
s
.
mountPoint
==
""
{
return
nil
}
delay
:=
time
.
Duration
(
0
)
for
try
:=
0
;
try
<
5
;
try
++
{
err
=
unmount
(
m
e
.
mountPoint
)
err
=
unmount
(
m
s
.
mountPoint
)
if
err
==
nil
{
break
}
...
...
@@ -113,50 +113,50 @@ func (me *MountState) Unmount() (err error) {
delay
=
2
*
delay
+
5
*
time
.
Millisecond
time
.
Sleep
(
delay
)
}
m
e
.
mountPoint
=
""
m
s
.
mountPoint
=
""
return
err
}
func
NewMountState
(
fs
RawFileSystem
)
*
MountState
{
m
e
:=
new
(
MountState
)
m
e
.
mountPoint
=
""
m
e
.
fileSystem
=
fs
m
e
.
buffers
=
NewBufferPool
()
return
m
e
m
s
:=
new
(
MountState
)
m
s
.
mountPoint
=
""
m
s
.
fileSystem
=
fs
m
s
.
buffers
=
NewBufferPool
()
return
m
s
}
func
(
m
e
*
MountState
)
Latencies
()
map
[
string
]
float64
{
if
m
e
.
latencies
==
nil
{
func
(
m
s
*
MountState
)
Latencies
()
map
[
string
]
float64
{
if
m
s
.
latencies
==
nil
{
return
nil
}
return
m
e
.
latencies
.
Latencies
(
1e-3
)
return
m
s
.
latencies
.
Latencies
(
1e-3
)
}
func
(
m
e
*
MountState
)
OperationCounts
()
map
[
string
]
int
{
if
m
e
.
latencies
==
nil
{
func
(
m
s
*
MountState
)
OperationCounts
()
map
[
string
]
int
{
if
m
s
.
latencies
==
nil
{
return
nil
}
return
m
e
.
latencies
.
Counts
()
return
m
s
.
latencies
.
Counts
()
}
func
(
m
e
*
MountState
)
BufferPoolStats
()
string
{
return
m
e
.
buffers
.
String
()
func
(
m
s
*
MountState
)
BufferPoolStats
()
string
{
return
m
s
.
buffers
.
String
()
}
func
(
m
e
*
MountState
)
newRequest
()
*
request
{
func
(
m
s
*
MountState
)
newRequest
()
*
request
{
r
:=
&
request
{
pool
:
m
e
.
buffers
,
pool
:
m
s
.
buffers
,
}
return
r
}
func
(
m
e
*
MountState
)
recordStats
(
req
*
request
)
{
if
m
e
.
latencies
!=
nil
{
func
(
m
s
*
MountState
)
recordStats
(
req
*
request
)
{
if
m
s
.
latencies
!=
nil
{
endNs
:=
time
.
Now
()
.
UnixNano
()
dt
:=
endNs
-
req
.
startNs
opname
:=
operationName
(
req
.
inHeader
.
Opcode
)
m
e
.
latencies
.
AddMany
(
m
s
.
latencies
.
AddMany
(
[]
LatencyArg
{
{
opname
,
""
,
dt
},
{
opname
+
"-write"
,
""
,
endNs
-
req
.
preWriteNs
}})
...
...
@@ -168,20 +168,20 @@ func (me *MountState) recordStats(req *request) {
// goroutine.
//
// Each filesystem operation executes in a separate goroutine.
func
(
m
e
*
MountState
)
Loop
()
{
m
e
.
loop
()
m
e
.
mountFile
.
Close
()
m
e
.
mountFile
=
nil
func
(
m
s
*
MountState
)
Loop
()
{
m
s
.
loop
()
m
s
.
mountFile
.
Close
()
m
s
.
mountFile
=
nil
}
func
(
m
e
*
MountState
)
loop
()
{
func
(
m
s
*
MountState
)
loop
()
{
var
dest
[]
byte
for
{
if
dest
==
nil
{
dest
=
m
e
.
buffers
.
AllocBuffer
(
uint32
(
me
.
opts
.
MaxWrite
+
4096
))
dest
=
m
s
.
buffers
.
AllocBuffer
(
uint32
(
ms
.
opts
.
MaxWrite
+
4096
))
}
n
,
err
:=
m
e
.
mountFile
.
Read
(
dest
)
n
,
err
:=
m
s
.
mountFile
.
Read
(
dest
)
if
err
!=
nil
{
errNo
:=
ToStatus
(
err
)
...
...
@@ -199,8 +199,8 @@ func (me *MountState) loop() {
break
}
req
:=
m
e
.
newRequest
()
if
m
e
.
latencies
!=
nil
{
req
:=
m
s
.
newRequest
()
if
m
s
.
latencies
!=
nil
{
req
.
startNs
=
time
.
Now
()
.
UnixNano
()
}
if
req
.
setInput
(
dest
[
:
n
])
{
...
...
@@ -213,21 +213,21 @@ func (me *MountState) loop() {
// which will lock up the FS if the daemon has too
// many blocking calls.
go
func
(
r
*
request
)
{
m
e
.
handleRequest
(
r
)
m
s
.
handleRequest
(
r
)
r
.
Discard
()
}(
req
)
}
}
func
(
m
e
*
MountState
)
handleRequest
(
req
*
request
)
{
defer
m
e
.
recordStats
(
req
)
func
(
m
s
*
MountState
)
handleRequest
(
req
*
request
)
{
defer
m
s
.
recordStats
(
req
)
req
.
parse
()
if
req
.
handler
==
nil
{
req
.
status
=
ENOSYS
}
if
req
.
status
.
Ok
()
&&
m
e
.
Debug
{
if
req
.
status
.
Ok
()
&&
m
s
.
Debug
{
log
.
Println
(
req
.
InputDebug
())
}
...
...
@@ -237,28 +237,28 @@ func (me *MountState) handleRequest(req *request) {
}
if
req
.
status
.
Ok
()
{
req
.
handler
.
Func
(
m
e
,
req
)
req
.
handler
.
Func
(
m
s
,
req
)
}
errNo
:=
m
e
.
write
(
req
)
errNo
:=
m
s
.
write
(
req
)
if
errNo
!=
0
{
log
.
Printf
(
"writer: Write/Writev %v failed, err: %v. opcode: %v"
,
req
.
outHeaderBytes
,
errNo
,
operationName
(
req
.
inHeader
.
Opcode
))
}
}
func
(
m
e
*
MountState
)
write
(
req
*
request
)
Status
{
func
(
m
s
*
MountState
)
write
(
req
*
request
)
Status
{
// Forget does not wait for reply.
if
req
.
inHeader
.
Opcode
==
_OP_FORGET
||
req
.
inHeader
.
Opcode
==
_OP_BATCH_FORGET
{
return
OK
}
req
.
serialize
()
if
m
e
.
Debug
{
if
m
s
.
Debug
{
log
.
Println
(
req
.
OutputDebug
())
}
if
m
e
.
latencies
!=
nil
{
if
m
s
.
latencies
!=
nil
{
req
.
preWriteNs
=
time
.
Now
()
.
UnixNano
()
}
...
...
@@ -268,16 +268,16 @@ func (me *MountState) write(req *request) Status {
var
err
error
if
req
.
flatData
==
nil
{
_
,
err
=
m
e
.
mountFile
.
Write
(
req
.
outHeaderBytes
)
_
,
err
=
m
s
.
mountFile
.
Write
(
req
.
outHeaderBytes
)
}
else
{
_
,
err
=
Writev
(
int
(
m
e
.
mountFile
.
Fd
()),
_
,
err
=
Writev
(
int
(
m
s
.
mountFile
.
Fd
()),
[][]
byte
{
req
.
outHeaderBytes
,
req
.
flatData
})
}
return
ToStatus
(
err
)
}
func
(
m
e
*
MountState
)
writeInodeNotify
(
entry
*
raw
.
NotifyInvalInodeOut
)
Status
{
func
(
m
s
*
MountState
)
writeInodeNotify
(
entry
*
raw
.
NotifyInvalInodeOut
)
Status
{
req
:=
request
{
inHeader
:
&
raw
.
InHeader
{
Opcode
:
_OP_NOTIFY_INODE
,
...
...
@@ -287,15 +287,15 @@ func (me *MountState) writeInodeNotify(entry *raw.NotifyInvalInodeOut) Status {
}
req
.
outData
=
unsafe
.
Pointer
(
entry
)
req
.
serialize
()
result
:=
m
e
.
write
(
&
req
)
result
:=
m
s
.
write
(
&
req
)
if
m
e
.
Debug
{
if
m
s
.
Debug
{
log
.
Println
(
"Response: INODE_NOTIFY"
,
result
)
}
return
result
}
func
(
m
e
*
MountState
)
writeEntryNotify
(
parent
uint64
,
name
string
)
Status
{
func
(
m
s
*
MountState
)
writeEntryNotify
(
parent
uint64
,
name
string
)
Status
{
req
:=
request
{
inHeader
:
&
raw
.
InHeader
{
Opcode
:
_OP_NOTIFY_ENTRY
,
...
...
@@ -314,9 +314,9 @@ func (me *MountState) writeEntryNotify(parent uint64, name string) Status {
req
.
outData
=
unsafe
.
Pointer
(
entry
)
req
.
flatData
=
nameBytes
req
.
serialize
()
result
:=
m
e
.
write
(
&
req
)
result
:=
m
s
.
write
(
&
req
)
if
m
e
.
Debug
{
if
m
s
.
Debug
{
log
.
Printf
(
"Response: ENTRY_NOTIFY: %v"
,
result
)
}
return
result
...
...
fuse/notify_test.go
View file @
ce603372
...
...
@@ -16,12 +16,12 @@ type NotifyFs struct {
exist
bool
}
func
(
me
*
NotifyFs
)
GetAttr
(
name
string
,
context
*
Context
)
(
*
Attr
,
Status
)
{
func
(
fs
*
NotifyFs
)
GetAttr
(
name
string
,
context
*
Context
)
(
*
Attr
,
Status
)
{
if
name
==
""
{
return
&
Attr
{
Mode
:
S_IFDIR
|
0755
},
OK
}
if
name
==
"file"
||
(
name
==
"dir/file"
&&
me
.
exist
)
{
return
&
Attr
{
Mode
:
S_IFREG
|
0644
,
Size
:
me
.
size
},
OK
if
name
==
"file"
||
(
name
==
"dir/file"
&&
fs
.
exist
)
{
return
&
Attr
{
Mode
:
S_IFREG
|
0644
,
Size
:
fs
.
size
},
OK
}
if
name
==
"dir"
{
return
&
Attr
{
Mode
:
S_IFDIR
|
0755
},
OK
...
...
@@ -29,7 +29,7 @@ func (me *NotifyFs) GetAttr(name string, context *Context) (*Attr, Status) {
return
nil
,
ENOENT
}
func
(
me
*
NotifyFs
)
Open
(
name
string
,
f
uint32
,
context
*
Context
)
(
File
,
Status
)
{
func
(
fs
*
NotifyFs
)
Open
(
name
string
,
f
uint32
,
context
*
Context
)
(
File
,
Status
)
{
return
NewDataFile
([]
byte
{
42
}),
OK
}
...
...
@@ -63,10 +63,10 @@ func NewNotifyTest() *NotifyTest {
return
me
}
func
(
me
*
NotifyTest
)
Clean
()
{
err
:=
me
.
state
.
Unmount
()
func
(
t
*
NotifyTest
)
Clean
()
{
err
:=
t
.
state
.
Unmount
()
if
err
==
nil
{
os
.
RemoveAll
(
me
.
dir
)
os
.
RemoveAll
(
t
.
dir
)
}
}
...
...
fuse/owner_test.go
View file @
ce603372
...
...
@@ -13,7 +13,7 @@ type ownerFs struct {
const
_RANDOM_OWNER
=
31415265
func
(
me
*
ownerFs
)
GetAttr
(
name
string
,
context
*
Context
)
(
*
Attr
,
Status
)
{
func
(
fs
*
ownerFs
)
GetAttr
(
name
string
,
context
*
Context
)
(
*
Attr
,
Status
)
{
if
name
==
""
{
return
&
Attr
{
Mode
:
S_IFDIR
|
0755
,
...
...
fuse/pathfs.go
View file @
ce603372
...
...
@@ -40,64 +40,64 @@ type PathNodeFs struct {
options
*
PathNodeFsOptions
}
func
(
me
*
PathNodeFs
)
Mount
(
path
string
,
nodeFs
NodeFileSystem
,
opts
*
FileSystemOptions
)
Status
{
func
(
fs
*
PathNodeFs
)
Mount
(
path
string
,
nodeFs
NodeFileSystem
,
opts
*
FileSystemOptions
)
Status
{
dir
,
name
:=
filepath
.
Split
(
path
)
if
dir
!=
""
{
dir
=
filepath
.
Clean
(
dir
)
}
parent
:=
me
.
LookupNode
(
dir
)
parent
:=
fs
.
LookupNode
(
dir
)
if
parent
==
nil
{
return
ENOENT
}
return
me
.
connector
.
Mount
(
parent
,
name
,
nodeFs
,
opts
)
return
fs
.
connector
.
Mount
(
parent
,
name
,
nodeFs
,
opts
)
}
// Forgets all known information on client inodes.
func
(
me
*
PathNodeFs
)
ForgetClientInodes
()
{
if
!
me
.
options
.
ClientInodes
{
func
(
fs
*
PathNodeFs
)
ForgetClientInodes
()
{
if
!
fs
.
options
.
ClientInodes
{
return
}
me
.
pathLock
.
Lock
()
defer
me
.
pathLock
.
Unlock
()
me
.
clientInodeMap
=
map
[
uint64
][]
*
clientInodePath
{}
me
.
root
.
forgetClientInodes
()
fs
.
pathLock
.
Lock
()
defer
fs
.
pathLock
.
Unlock
()
fs
.
clientInodeMap
=
map
[
uint64
][]
*
clientInodePath
{}
fs
.
root
.
forgetClientInodes
()
}
// Rereads all inode numbers for all known files.
func
(
me
*
PathNodeFs
)
RereadClientInodes
()
{
if
!
me
.
options
.
ClientInodes
{
func
(
fs
*
PathNodeFs
)
RereadClientInodes
()
{
if
!
fs
.
options
.
ClientInodes
{
return
}
me
.
ForgetClientInodes
()
me
.
root
.
updateClientInodes
()
fs
.
ForgetClientInodes
()
fs
.
root
.
updateClientInodes
()
}
func
(
me
*
PathNodeFs
)
UnmountNode
(
node
*
Inode
)
Status
{
return
me
.
connector
.
Unmount
(
node
)
func
(
fs
*
PathNodeFs
)
UnmountNode
(
node
*
Inode
)
Status
{
return
fs
.
connector
.
Unmount
(
node
)
}
func
(
me
*
PathNodeFs
)
Unmount
(
path
string
)
Status
{
node
:=
me
.
Node
(
path
)
func
(
fs
*
PathNodeFs
)
Unmount
(
path
string
)
Status
{
node
:=
fs
.
Node
(
path
)
if
node
==
nil
{
return
ENOENT
}
return
me
.
connector
.
Unmount
(
node
)
return
fs
.
connector
.
Unmount
(
node
)
}
func
(
me
*
PathNodeFs
)
OnUnmount
()
{
func
(
fs
*
PathNodeFs
)
OnUnmount
()
{
}
func
(
me
*
PathNodeFs
)
String
()
string
{
return
fmt
.
Sprintf
(
"PathNodeFs(%v)"
,
me
.
fs
)
func
(
fs
*
PathNodeFs
)
String
()
string
{
return
fmt
.
Sprintf
(
"PathNodeFs(%v)"
,
fs
.
fs
)
}
func
(
me
*
PathNodeFs
)
OnMount
(
conn
*
FileSystemConnector
)
{
me
.
connector
=
conn
me
.
fs
.
OnMount
(
me
)
func
(
fs
*
PathNodeFs
)
OnMount
(
conn
*
FileSystemConnector
)
{
fs
.
connector
=
conn
fs
.
fs
.
OnMount
(
fs
)
}
func
(
me
*
PathNodeFs
)
Node
(
name
string
)
*
Inode
{
n
,
rest
:=
me
.
LastNode
(
name
)
func
(
fs
*
PathNodeFs
)
Node
(
name
string
)
*
Inode
{
n
,
rest
:=
fs
.
LastNode
(
name
)
if
len
(
rest
)
>
0
{
return
nil
}
...
...
@@ -105,45 +105,45 @@ func (me *PathNodeFs) Node(name string) *Inode {
}
// Like node, but use Lookup to discover inodes we may not have yet.
func
(
me
*
PathNodeFs
)
LookupNode
(
name
string
)
*
Inode
{
return
me
.
connector
.
LookupNode
(
me
.
Root
()
.
Inode
(),
name
)
func
(
fs
*
PathNodeFs
)
LookupNode
(
name
string
)
*
Inode
{
return
fs
.
connector
.
LookupNode
(
fs
.
Root
()
.
Inode
(),
name
)
}
func
(
me
*
PathNodeFs
)
Path
(
node
*
Inode
)
string
{
func
(
fs
*
PathNodeFs
)
Path
(
node
*
Inode
)
string
{
pNode
:=
node
.
FsNode
()
.
(
*
pathInode
)
return
pNode
.
GetPath
()
}
func
(
me
*
PathNodeFs
)
LastNode
(
name
string
)
(
*
Inode
,
[]
string
)
{
return
me
.
connector
.
Node
(
me
.
Root
()
.
Inode
(),
name
)
func
(
fs
*
PathNodeFs
)
LastNode
(
name
string
)
(
*
Inode
,
[]
string
)
{
return
fs
.
connector
.
Node
(
fs
.
Root
()
.
Inode
(),
name
)
}
func
(
me
*
PathNodeFs
)
FileNotify
(
path
string
,
off
int64
,
length
int64
)
Status
{
node
,
r
:=
me
.
connector
.
Node
(
me
.
root
.
Inode
(),
path
)
func
(
fs
*
PathNodeFs
)
FileNotify
(
path
string
,
off
int64
,
length
int64
)
Status
{
node
,
r
:=
fs
.
connector
.
Node
(
fs
.
root
.
Inode
(),
path
)
if
len
(
r
)
>
0
{
return
ENOENT
}
return
me
.
connector
.
FileNotify
(
node
,
off
,
length
)
return
fs
.
connector
.
FileNotify
(
node
,
off
,
length
)
}
func
(
me
*
PathNodeFs
)
EntryNotify
(
dir
string
,
name
string
)
Status
{
node
,
rest
:=
me
.
connector
.
Node
(
me
.
root
.
Inode
(),
dir
)
func
(
fs
*
PathNodeFs
)
EntryNotify
(
dir
string
,
name
string
)
Status
{
node
,
rest
:=
fs
.
connector
.
Node
(
fs
.
root
.
Inode
(),
dir
)
if
len
(
rest
)
>
0
{
return
ENOENT
}
return
me
.
connector
.
EntryNotify
(
node
,
name
)
return
fs
.
connector
.
EntryNotify
(
node
,
name
)
}
func
(
me
*
PathNodeFs
)
Notify
(
path
string
)
Status
{
node
,
rest
:=
me
.
connector
.
Node
(
me
.
root
.
Inode
(),
path
)
func
(
fs
*
PathNodeFs
)
Notify
(
path
string
)
Status
{
node
,
rest
:=
fs
.
connector
.
Node
(
fs
.
root
.
Inode
(),
path
)
if
len
(
rest
)
>
0
{
return
me
.
connector
.
EntryNotify
(
node
,
rest
[
0
])
return
fs
.
connector
.
EntryNotify
(
node
,
rest
[
0
])
}
return
me
.
connector
.
FileNotify
(
node
,
0
,
0
)
return
fs
.
connector
.
FileNotify
(
node
,
0
,
0
)
}
func
(
me
*
PathNodeFs
)
AllFiles
(
name
string
,
mask
uint32
)
[]
WithFlags
{
n
:=
me
.
Node
(
name
)
func
(
fs
*
PathNodeFs
)
AllFiles
(
name
string
,
mask
uint32
)
[]
WithFlags
{
n
:=
fs
.
Node
(
name
)
if
n
==
nil
{
return
nil
}
...
...
@@ -158,18 +158,18 @@ func NewPathNodeFs(fs FileSystem, opts *PathNodeFsOptions) *PathNodeFs {
opts
=
&
PathNodeFsOptions
{}
}
me
:=
&
PathNodeFs
{
pfs
:=
&
PathNodeFs
{
fs
:
fs
,
root
:
root
,
clientInodeMap
:
map
[
uint64
][]
*
clientInodePath
{},
options
:
opts
,
}
root
.
pathFs
=
me
return
me
root
.
pathFs
=
pfs
return
pfs
}
func
(
me
*
PathNodeFs
)
Root
()
FsNode
{
return
me
.
root
func
(
fs
*
PathNodeFs
)
Root
()
FsNode
{
return
fs
.
root
}
// This is a combination of dentry (entry in the file/directory and
...
...
@@ -191,33 +191,33 @@ type pathInode struct {
}
// Drop all known client inodes. Must have the treeLock.
func
(
me
*
pathInode
)
forgetClientInodes
()
{
me
.
clientInode
=
0
for
_
,
ch
:=
range
me
.
Inode
()
.
FsChildren
()
{
func
(
n
*
pathInode
)
forgetClientInodes
()
{
n
.
clientInode
=
0
for
_
,
ch
:=
range
n
.
Inode
()
.
FsChildren
()
{
ch
.
FsNode
()
.
(
*
pathInode
)
.
forgetClientInodes
()
}
}
// Reread all client nodes below this node. Must run outside the treeLock.
func
(
me
*
pathInode
)
updateClientInodes
()
{
me
.
GetAttr
(
nil
,
nil
)
for
_
,
ch
:=
range
me
.
Inode
()
.
FsChildren
()
{
func
(
n
*
pathInode
)
updateClientInodes
()
{
n
.
GetAttr
(
nil
,
nil
)
for
_
,
ch
:=
range
n
.
Inode
()
.
FsChildren
()
{
ch
.
FsNode
()
.
(
*
pathInode
)
.
updateClientInodes
()
}
}
func
(
me
*
pathInode
)
LockTree
()
func
()
{
me
.
pathFs
.
pathLock
.
Lock
()
return
func
()
{
me
.
pathFs
.
pathLock
.
Unlock
()
}
func
(
n
*
pathInode
)
LockTree
()
func
()
{
n
.
pathFs
.
pathLock
.
Lock
()
return
func
()
{
n
.
pathFs
.
pathLock
.
Unlock
()
}
}
func
(
me
*
pathInode
)
RLockTree
()
func
()
{
me
.
pathFs
.
pathLock
.
RLock
()
return
func
()
{
me
.
pathFs
.
pathLock
.
RUnlock
()
}
func
(
n
*
pathInode
)
RLockTree
()
func
()
{
n
.
pathFs
.
pathLock
.
RLock
()
return
func
()
{
n
.
pathFs
.
pathLock
.
RUnlock
()
}
}
func
(
me
*
pathInode
)
fillNewChildAttr
(
path
string
,
child
*
pathInode
,
c
*
Context
)
(
fi
*
Attr
,
code
Status
)
{
fi
,
_
=
me
.
fs
.
GetAttr
(
path
,
c
)
func
(
n
*
pathInode
)
fillNewChildAttr
(
path
string
,
child
*
pathInode
,
c
*
Context
)
(
fi
*
Attr
,
code
Status
)
{
fi
,
_
=
n
.
fs
.
GetAttr
(
path
,
c
)
if
fi
!=
nil
&&
fi
.
Ino
>
0
{
child
.
clientInode
=
fi
.
Ino
}
...
...
@@ -232,55 +232,55 @@ func (me *pathInode) fillNewChildAttr(path string, child *pathInode, c *Context)
// GetPath returns the path relative to the mount governing this
// inode. It returns nil for mount if the file was deleted or the
// filesystem unmounted.
func
(
me
*
pathInode
)
GetPath
()
(
path
string
)
{
defer
me
.
RLockTree
()()
func
(
n
*
pathInode
)
GetPath
()
(
path
string
)
{
defer
n
.
RLockTree
()()
rev_components
:=
make
([]
string
,
0
,
10
)
n
:=
me
for
;
n
.
Parent
!=
nil
;
n
=
n
.
Parent
{
rev_components
=
append
(
rev_components
,
n
.
Name
)
p
:=
n
for
;
p
.
Parent
!=
nil
;
p
=
p
.
Parent
{
rev_components
=
append
(
rev_components
,
p
.
Name
)
}
if
n
!=
me
.
pathFs
.
root
{
if
p
!=
p
.
pathFs
.
root
{
return
".deleted"
}
p
:
=
ReverseJoin
(
rev_components
,
"/"
)
if
me
.
pathFs
.
Debug
{
log
.
Printf
(
"Inode %d = %q (%s)"
,
me
.
Inode
()
.
nodeId
,
p
,
me
.
fs
.
String
())
p
ath
=
ReverseJoin
(
rev_components
,
"/"
)
if
n
.
pathFs
.
Debug
{
log
.
Printf
(
"Inode %d = %q (%s)"
,
n
.
Inode
()
.
nodeId
,
path
,
n
.
fs
.
String
())
}
return
p
return
p
ath
}
func
(
me
*
pathInode
)
addChild
(
name
string
,
child
*
pathInode
)
{
me
.
Inode
()
.
AddChild
(
name
,
child
.
Inode
())
child
.
Parent
=
me
func
(
n
*
pathInode
)
addChild
(
name
string
,
child
*
pathInode
)
{
n
.
Inode
()
.
AddChild
(
name
,
child
.
Inode
())
child
.
Parent
=
n
child
.
Name
=
name
if
child
.
clientInode
>
0
&&
me
.
pathFs
.
options
.
ClientInodes
{
defer
me
.
LockTree
()()
m
:=
me
.
pathFs
.
clientInodeMap
[
child
.
clientInode
]
if
child
.
clientInode
>
0
&&
n
.
pathFs
.
options
.
ClientInodes
{
defer
n
.
LockTree
()()
m
:=
n
.
pathFs
.
clientInodeMap
[
child
.
clientInode
]
e
:=
&
clientInodePath
{
me
,
name
,
child
,
n
,
name
,
child
,
}
m
=
append
(
m
,
e
)
me
.
pathFs
.
clientInodeMap
[
child
.
clientInode
]
=
m
n
.
pathFs
.
clientInodeMap
[
child
.
clientInode
]
=
m
}
}
func
(
me
*
pathInode
)
rmChild
(
name
string
)
*
pathInode
{
childInode
:=
me
.
Inode
()
.
RmChild
(
name
)
func
(
n
*
pathInode
)
rmChild
(
name
string
)
*
pathInode
{
childInode
:=
n
.
Inode
()
.
RmChild
(
name
)
if
childInode
==
nil
{
return
nil
}
ch
:=
childInode
.
FsNode
()
.
(
*
pathInode
)
if
ch
.
clientInode
>
0
&&
me
.
pathFs
.
options
.
ClientInodes
{
defer
me
.
LockTree
()()
m
:=
me
.
pathFs
.
clientInodeMap
[
ch
.
clientInode
]
if
ch
.
clientInode
>
0
&&
n
.
pathFs
.
options
.
ClientInodes
{
defer
n
.
LockTree
()()
m
:=
n
.
pathFs
.
clientInodeMap
[
ch
.
clientInode
]
idx
:=
-
1
for
i
,
v
:=
range
m
{
if
v
.
parent
==
me
&&
v
.
name
==
name
{
if
v
.
parent
==
n
&&
v
.
name
==
name
{
idx
=
i
break
}
...
...
@@ -294,7 +294,7 @@ func (me *pathInode) rmChild(name string) *pathInode {
ch
.
Name
=
m
[
0
]
.
name
return
ch
}
else
{
delete
(
me
.
pathFs
.
clientInodeMap
,
ch
.
clientInode
)
delete
(
n
.
pathFs
.
clientInodeMap
,
ch
.
clientInode
)
}
}
...
...
@@ -306,214 +306,214 @@ func (me *pathInode) rmChild(name string) *pathInode {
// Handle a change in clientInode number for an other wise unchanged
// pathInode.
func
(
me
*
pathInode
)
setClientInode
(
ino
uint64
)
{
if
ino
==
me
.
clientInode
||
!
me
.
pathFs
.
options
.
ClientInodes
{
func
(
n
*
pathInode
)
setClientInode
(
ino
uint64
)
{
if
ino
==
n
.
clientInode
||
!
n
.
pathFs
.
options
.
ClientInodes
{
return
}
defer
me
.
LockTree
()()
if
me
.
clientInode
!=
0
{
delete
(
me
.
pathFs
.
clientInodeMap
,
me
.
clientInode
)
defer
n
.
LockTree
()()
if
n
.
clientInode
!=
0
{
delete
(
n
.
pathFs
.
clientInodeMap
,
n
.
clientInode
)
}
me
.
clientInode
=
ino
if
me
.
Parent
!=
nil
{
n
.
clientInode
=
ino
if
n
.
Parent
!=
nil
{
e
:=
&
clientInodePath
{
me
.
Parent
,
me
.
Name
,
me
,
n
.
Parent
,
n
.
Name
,
n
,
}
me
.
pathFs
.
clientInodeMap
[
ino
]
=
append
(
me
.
pathFs
.
clientInodeMap
[
ino
],
e
)
n
.
pathFs
.
clientInodeMap
[
ino
]
=
append
(
n
.
pathFs
.
clientInodeMap
[
ino
],
e
)
}
}
func
(
me
*
pathInode
)
OnForget
()
{
if
me
.
clientInode
==
0
||
!
me
.
pathFs
.
options
.
ClientInodes
{
func
(
n
*
pathInode
)
OnForget
()
{
if
n
.
clientInode
==
0
||
!
n
.
pathFs
.
options
.
ClientInodes
{
return
}
defer
me
.
LockTree
()()
delete
(
me
.
pathFs
.
clientInodeMap
,
me
.
clientInode
)
defer
n
.
LockTree
()()
delete
(
n
.
pathFs
.
clientInodeMap
,
n
.
clientInode
)
}
////////////////////////////////////////////////////////////////
// FS operations
func
(
me
*
pathInode
)
StatFs
()
*
StatfsOut
{
return
me
.
fs
.
StatFs
(
me
.
GetPath
())
func
(
n
*
pathInode
)
StatFs
()
*
StatfsOut
{
return
n
.
fs
.
StatFs
(
n
.
GetPath
())
}
func
(
me
*
pathInode
)
Readlink
(
c
*
Context
)
([]
byte
,
Status
)
{
path
:=
me
.
GetPath
()
func
(
n
*
pathInode
)
Readlink
(
c
*
Context
)
([]
byte
,
Status
)
{
path
:=
n
.
GetPath
()
val
,
err
:=
me
.
fs
.
Readlink
(
path
,
c
)
val
,
err
:=
n
.
fs
.
Readlink
(
path
,
c
)
return
[]
byte
(
val
),
err
}
func
(
me
*
pathInode
)
Access
(
mode
uint32
,
context
*
Context
)
(
code
Status
)
{
p
:=
me
.
GetPath
()
return
me
.
fs
.
Access
(
p
,
mode
,
context
)
func
(
n
*
pathInode
)
Access
(
mode
uint32
,
context
*
Context
)
(
code
Status
)
{
p
:=
n
.
GetPath
()
return
n
.
fs
.
Access
(
p
,
mode
,
context
)
}
func
(
me
*
pathInode
)
GetXAttr
(
attribute
string
,
context
*
Context
)
(
data
[]
byte
,
code
Status
)
{
return
me
.
fs
.
GetXAttr
(
me
.
GetPath
(),
attribute
,
context
)
func
(
n
*
pathInode
)
GetXAttr
(
attribute
string
,
context
*
Context
)
(
data
[]
byte
,
code
Status
)
{
return
n
.
fs
.
GetXAttr
(
n
.
GetPath
(),
attribute
,
context
)
}
func
(
me
*
pathInode
)
RemoveXAttr
(
attr
string
,
context
*
Context
)
Status
{
p
:=
me
.
GetPath
()
return
me
.
fs
.
RemoveXAttr
(
p
,
attr
,
context
)
func
(
n
*
pathInode
)
RemoveXAttr
(
attr
string
,
context
*
Context
)
Status
{
p
:=
n
.
GetPath
()
return
n
.
fs
.
RemoveXAttr
(
p
,
attr
,
context
)
}
func
(
me
*
pathInode
)
SetXAttr
(
attr
string
,
data
[]
byte
,
flags
int
,
context
*
Context
)
Status
{
return
me
.
fs
.
SetXAttr
(
me
.
GetPath
(),
attr
,
data
,
flags
,
context
)
func
(
n
*
pathInode
)
SetXAttr
(
attr
string
,
data
[]
byte
,
flags
int
,
context
*
Context
)
Status
{
return
n
.
fs
.
SetXAttr
(
n
.
GetPath
(),
attr
,
data
,
flags
,
context
)
}
func
(
me
*
pathInode
)
ListXAttr
(
context
*
Context
)
(
attrs
[]
string
,
code
Status
)
{
return
me
.
fs
.
ListXAttr
(
me
.
GetPath
(),
context
)
func
(
n
*
pathInode
)
ListXAttr
(
context
*
Context
)
(
attrs
[]
string
,
code
Status
)
{
return
n
.
fs
.
ListXAttr
(
n
.
GetPath
(),
context
)
}
func
(
me
*
pathInode
)
Flush
(
file
File
,
openFlags
uint32
,
context
*
Context
)
(
code
Status
)
{
func
(
n
*
pathInode
)
Flush
(
file
File
,
openFlags
uint32
,
context
*
Context
)
(
code
Status
)
{
return
file
.
Flush
()
}
func
(
me
*
pathInode
)
OpenDir
(
context
*
Context
)
(
chan
DirEntry
,
Status
)
{
return
me
.
fs
.
OpenDir
(
me
.
GetPath
(),
context
)
func
(
n
*
pathInode
)
OpenDir
(
context
*
Context
)
(
chan
DirEntry
,
Status
)
{
return
n
.
fs
.
OpenDir
(
n
.
GetPath
(),
context
)
}
func
(
me
*
pathInode
)
Mknod
(
name
string
,
mode
uint32
,
dev
uint32
,
context
*
Context
)
(
fi
*
Attr
,
newNode
FsNode
,
code
Status
)
{
fullPath
:=
filepath
.
Join
(
me
.
GetPath
(),
name
)
code
=
me
.
fs
.
Mknod
(
fullPath
,
mode
,
dev
,
context
)
func
(
n
*
pathInode
)
Mknod
(
name
string
,
mode
uint32
,
dev
uint32
,
context
*
Context
)
(
fi
*
Attr
,
newNode
FsNode
,
code
Status
)
{
fullPath
:=
filepath
.
Join
(
n
.
GetPath
(),
name
)
code
=
n
.
fs
.
Mknod
(
fullPath
,
mode
,
dev
,
context
)
if
code
.
Ok
()
{
pNode
:=
me
.
createChild
(
false
)
pNode
:=
n
.
createChild
(
false
)
newNode
=
pNode
fi
,
code
=
me
.
fillNewChildAttr
(
fullPath
,
pNode
,
context
)
me
.
addChild
(
name
,
pNode
)
fi
,
code
=
n
.
fillNewChildAttr
(
fullPath
,
pNode
,
context
)
n
.
addChild
(
name
,
pNode
)
}
return
}
func
(
me
*
pathInode
)
Mkdir
(
name
string
,
mode
uint32
,
context
*
Context
)
(
fi
*
Attr
,
newNode
FsNode
,
code
Status
)
{
fullPath
:=
filepath
.
Join
(
me
.
GetPath
(),
name
)
code
=
me
.
fs
.
Mkdir
(
fullPath
,
mode
,
context
)
func
(
n
*
pathInode
)
Mkdir
(
name
string
,
mode
uint32
,
context
*
Context
)
(
fi
*
Attr
,
newNode
FsNode
,
code
Status
)
{
fullPath
:=
filepath
.
Join
(
n
.
GetPath
(),
name
)
code
=
n
.
fs
.
Mkdir
(
fullPath
,
mode
,
context
)
if
code
.
Ok
()
{
pNode
:=
me
.
createChild
(
true
)
pNode
:=
n
.
createChild
(
true
)
newNode
=
pNode
fi
,
code
=
me
.
fillNewChildAttr
(
fullPath
,
pNode
,
context
)
me
.
addChild
(
name
,
pNode
)
fi
,
code
=
n
.
fillNewChildAttr
(
fullPath
,
pNode
,
context
)
n
.
addChild
(
name
,
pNode
)
}
return
}
func
(
me
*
pathInode
)
Unlink
(
name
string
,
context
*
Context
)
(
code
Status
)
{
code
=
me
.
fs
.
Unlink
(
filepath
.
Join
(
me
.
GetPath
(),
name
),
context
)
func
(
n
*
pathInode
)
Unlink
(
name
string
,
context
*
Context
)
(
code
Status
)
{
code
=
n
.
fs
.
Unlink
(
filepath
.
Join
(
n
.
GetPath
(),
name
),
context
)
if
code
.
Ok
()
{
me
.
rmChild
(
name
)
n
.
rmChild
(
name
)
}
return
code
}
func
(
me
*
pathInode
)
Rmdir
(
name
string
,
context
*
Context
)
(
code
Status
)
{
code
=
me
.
fs
.
Rmdir
(
filepath
.
Join
(
me
.
GetPath
(),
name
),
context
)
func
(
n
*
pathInode
)
Rmdir
(
name
string
,
context
*
Context
)
(
code
Status
)
{
code
=
n
.
fs
.
Rmdir
(
filepath
.
Join
(
n
.
GetPath
(),
name
),
context
)
if
code
.
Ok
()
{
me
.
rmChild
(
name
)
n
.
rmChild
(
name
)
}
return
code
}
func
(
me
*
pathInode
)
Symlink
(
name
string
,
content
string
,
context
*
Context
)
(
fi
*
Attr
,
newNode
FsNode
,
code
Status
)
{
fullPath
:=
filepath
.
Join
(
me
.
GetPath
(),
name
)
code
=
me
.
fs
.
Symlink
(
content
,
fullPath
,
context
)
func
(
n
*
pathInode
)
Symlink
(
name
string
,
content
string
,
context
*
Context
)
(
fi
*
Attr
,
newNode
FsNode
,
code
Status
)
{
fullPath
:=
filepath
.
Join
(
n
.
GetPath
(),
name
)
code
=
n
.
fs
.
Symlink
(
content
,
fullPath
,
context
)
if
code
.
Ok
()
{
pNode
:=
me
.
createChild
(
false
)
pNode
:=
n
.
createChild
(
false
)
newNode
=
pNode
fi
,
code
=
me
.
fillNewChildAttr
(
fullPath
,
pNode
,
context
)
me
.
addChild
(
name
,
pNode
)
fi
,
code
=
n
.
fillNewChildAttr
(
fullPath
,
pNode
,
context
)
n
.
addChild
(
name
,
pNode
)
}
return
}
func
(
me
*
pathInode
)
Rename
(
oldName
string
,
newParent
FsNode
,
newName
string
,
context
*
Context
)
(
code
Status
)
{
func
(
n
*
pathInode
)
Rename
(
oldName
string
,
newParent
FsNode
,
newName
string
,
context
*
Context
)
(
code
Status
)
{
p
:=
newParent
.
(
*
pathInode
)
oldPath
:=
filepath
.
Join
(
me
.
GetPath
(),
oldName
)
oldPath
:=
filepath
.
Join
(
n
.
GetPath
(),
oldName
)
newPath
:=
filepath
.
Join
(
p
.
GetPath
(),
newName
)
code
=
me
.
fs
.
Rename
(
oldPath
,
newPath
,
context
)
code
=
n
.
fs
.
Rename
(
oldPath
,
newPath
,
context
)
if
code
.
Ok
()
{
ch
:=
me
.
rmChild
(
oldName
)
ch
:=
n
.
rmChild
(
oldName
)
p
.
rmChild
(
newName
)
p
.
addChild
(
newName
,
ch
)
}
return
code
}
func
(
me
*
pathInode
)
Link
(
name
string
,
existingFsnode
FsNode
,
context
*
Context
)
(
fi
*
Attr
,
newNode
FsNode
,
code
Status
)
{
if
!
me
.
pathFs
.
options
.
ClientInodes
{
func
(
n
*
pathInode
)
Link
(
name
string
,
existingFsnode
FsNode
,
context
*
Context
)
(
fi
*
Attr
,
newNode
FsNode
,
code
Status
)
{
if
!
n
.
pathFs
.
options
.
ClientInodes
{
return
nil
,
nil
,
ENOSYS
}
newPath
:=
filepath
.
Join
(
me
.
GetPath
(),
name
)
newPath
:=
filepath
.
Join
(
n
.
GetPath
(),
name
)
existing
:=
existingFsnode
.
(
*
pathInode
)
oldPath
:=
existing
.
GetPath
()
code
=
me
.
fs
.
Link
(
oldPath
,
newPath
,
context
)
code
=
n
.
fs
.
Link
(
oldPath
,
newPath
,
context
)
if
code
.
Ok
()
{
fi
,
code
=
me
.
fs
.
GetAttr
(
newPath
,
context
)
fi
,
code
=
n
.
fs
.
GetAttr
(
newPath
,
context
)
}
if
code
.
Ok
()
{
if
existing
.
clientInode
!=
0
&&
existing
.
clientInode
==
fi
.
Ino
{
newNode
=
existing
me
.
addChild
(
name
,
existing
)
n
.
addChild
(
name
,
existing
)
}
else
{
pNode
:=
me
.
createChild
(
false
)
pNode
:=
n
.
createChild
(
false
)
newNode
=
pNode
pNode
.
clientInode
=
fi
.
Ino
me
.
addChild
(
name
,
pNode
)
n
.
addChild
(
name
,
pNode
)
}
}
return
}
func
(
me
*
pathInode
)
Create
(
name
string
,
flags
uint32
,
mode
uint32
,
context
*
Context
)
(
file
File
,
fi
*
Attr
,
newNode
FsNode
,
code
Status
)
{
fullPath
:=
filepath
.
Join
(
me
.
GetPath
(),
name
)
file
,
code
=
me
.
fs
.
Create
(
fullPath
,
flags
,
mode
,
context
)
func
(
n
*
pathInode
)
Create
(
name
string
,
flags
uint32
,
mode
uint32
,
context
*
Context
)
(
file
File
,
fi
*
Attr
,
newNode
FsNode
,
code
Status
)
{
fullPath
:=
filepath
.
Join
(
n
.
GetPath
(),
name
)
file
,
code
=
n
.
fs
.
Create
(
fullPath
,
flags
,
mode
,
context
)
if
code
.
Ok
()
{
pNode
:=
me
.
createChild
(
false
)
pNode
:=
n
.
createChild
(
false
)
newNode
=
pNode
fi
,
code
=
me
.
fillNewChildAttr
(
fullPath
,
pNode
,
context
)
me
.
addChild
(
name
,
pNode
)
fi
,
code
=
n
.
fillNewChildAttr
(
fullPath
,
pNode
,
context
)
n
.
addChild
(
name
,
pNode
)
}
return
}
func
(
me
*
pathInode
)
createChild
(
isDir
bool
)
*
pathInode
{
func
(
n
*
pathInode
)
createChild
(
isDir
bool
)
*
pathInode
{
i
:=
new
(
pathInode
)
i
.
fs
=
me
.
fs
i
.
pathFs
=
me
.
pathFs
i
.
fs
=
n
.
fs
i
.
pathFs
=
n
.
pathFs
me
.
Inode
()
.
New
(
isDir
,
i
)
n
.
Inode
()
.
New
(
isDir
,
i
)
return
i
}
func
(
me
*
pathInode
)
Open
(
flags
uint32
,
context
*
Context
)
(
file
File
,
code
Status
)
{
file
,
code
=
me
.
fs
.
Open
(
me
.
GetPath
(),
flags
,
context
)
if
me
.
pathFs
.
Debug
{
func
(
n
*
pathInode
)
Open
(
flags
uint32
,
context
*
Context
)
(
file
File
,
code
Status
)
{
file
,
code
=
n
.
fs
.
Open
(
n
.
GetPath
(),
flags
,
context
)
if
n
.
pathFs
.
Debug
{
file
=
&
WithFlags
{
File
:
file
,
Description
:
me
.
GetPath
(),
Description
:
n
.
GetPath
(),
}
}
return
}
func
(
me
*
pathInode
)
Lookup
(
name
string
,
context
*
Context
)
(
fi
*
Attr
,
node
FsNode
,
code
Status
)
{
fullPath
:=
filepath
.
Join
(
me
.
GetPath
(),
name
)
fi
,
code
=
me
.
fs
.
GetAttr
(
fullPath
,
context
)
func
(
n
*
pathInode
)
Lookup
(
name
string
,
context
*
Context
)
(
fi
*
Attr
,
node
FsNode
,
code
Status
)
{
fullPath
:=
filepath
.
Join
(
n
.
GetPath
(),
name
)
fi
,
code
=
n
.
fs
.
GetAttr
(
fullPath
,
context
)
if
code
.
Ok
()
{
node
=
me
.
findChild
(
fi
,
name
,
fullPath
)
node
=
n
.
findChild
(
fi
,
name
,
fullPath
)
}
return
}
func
(
me
*
pathInode
)
findChild
(
fi
*
Attr
,
name
string
,
fullPath
string
)
(
out
*
pathInode
)
{
func
(
n
*
pathInode
)
findChild
(
fi
*
Attr
,
name
string
,
fullPath
string
)
(
out
*
pathInode
)
{
if
fi
.
Ino
>
0
{
unlock
:=
me
.
RLockTree
()
v
:=
me
.
pathFs
.
clientInodeMap
[
fi
.
Ino
]
unlock
:=
n
.
RLockTree
()
v
:=
n
.
pathFs
.
clientInodeMap
[
fi
.
Ino
]
if
len
(
v
)
>
0
{
out
=
v
[
0
]
.
node
...
...
@@ -525,18 +525,18 @@ func (me *pathInode) findChild(fi *Attr, name string, fullPath string) (out *pat
}
if
out
==
nil
{
out
=
me
.
createChild
(
fi
.
IsDir
())
out
=
n
.
createChild
(
fi
.
IsDir
())
out
.
clientInode
=
fi
.
Ino
me
.
addChild
(
name
,
out
)
n
.
addChild
(
name
,
out
)
}
return
out
}
func
(
me
*
pathInode
)
GetAttr
(
file
File
,
context
*
Context
)
(
fi
*
Attr
,
code
Status
)
{
func
(
n
*
pathInode
)
GetAttr
(
file
File
,
context
*
Context
)
(
fi
*
Attr
,
code
Status
)
{
if
file
==
nil
{
// called on a deleted files.
file
=
me
.
inode
.
AnyFile
()
file
=
n
.
inode
.
AnyFile
()
}
if
file
!=
nil
{
...
...
@@ -544,11 +544,11 @@ func (me *pathInode) GetAttr(file File, context *Context) (fi *Attr, code Status
}
if
file
==
nil
||
code
==
ENOSYS
||
code
==
EBADF
{
fi
,
code
=
me
.
fs
.
GetAttr
(
me
.
GetPath
(),
context
)
fi
,
code
=
n
.
fs
.
GetAttr
(
n
.
GetPath
(),
context
)
}
if
fi
!=
nil
{
me
.
setClientInode
(
fi
.
Ino
)
n
.
setClientInode
(
fi
.
Ino
)
}
if
fi
!=
nil
&&
!
fi
.
IsDir
()
&&
fi
.
Nlink
==
0
{
...
...
@@ -557,8 +557,8 @@ func (me *pathInode) GetAttr(file File, context *Context) (fi *Attr, code Status
return
fi
,
code
}
func
(
me
*
pathInode
)
Chmod
(
file
File
,
perms
uint32
,
context
*
Context
)
(
code
Status
)
{
files
:=
me
.
inode
.
Files
(
O_ANYWRITE
)
func
(
n
*
pathInode
)
Chmod
(
file
File
,
perms
uint32
,
context
*
Context
)
(
code
Status
)
{
files
:=
n
.
inode
.
Files
(
O_ANYWRITE
)
for
_
,
f
:=
range
files
{
// TODO - pass context
code
=
f
.
Chmod
(
perms
)
...
...
@@ -568,13 +568,13 @@ func (me *pathInode) Chmod(file File, perms uint32, context *Context) (code Stat
}
if
len
(
files
)
==
0
||
code
==
ENOSYS
||
code
==
EBADF
{
code
=
me
.
fs
.
Chmod
(
me
.
GetPath
(),
perms
,
context
)
code
=
n
.
fs
.
Chmod
(
n
.
GetPath
(),
perms
,
context
)
}
return
code
}
func
(
me
*
pathInode
)
Chown
(
file
File
,
uid
uint32
,
gid
uint32
,
context
*
Context
)
(
code
Status
)
{
files
:=
me
.
inode
.
Files
(
O_ANYWRITE
)
func
(
n
*
pathInode
)
Chown
(
file
File
,
uid
uint32
,
gid
uint32
,
context
*
Context
)
(
code
Status
)
{
files
:=
n
.
inode
.
Files
(
O_ANYWRITE
)
for
_
,
f
:=
range
files
{
// TODO - pass context
code
=
f
.
Chown
(
uid
,
gid
)
...
...
@@ -584,13 +584,13 @@ func (me *pathInode) Chown(file File, uid uint32, gid uint32, context *Context)
}
if
len
(
files
)
==
0
||
code
==
ENOSYS
||
code
==
EBADF
{
// TODO - can we get just FATTR_GID but not FATTR_UID ?
code
=
me
.
fs
.
Chown
(
me
.
GetPath
(),
uid
,
gid
,
context
)
code
=
n
.
fs
.
Chown
(
n
.
GetPath
(),
uid
,
gid
,
context
)
}
return
code
}
func
(
me
*
pathInode
)
Truncate
(
file
File
,
size
uint64
,
context
*
Context
)
(
code
Status
)
{
files
:=
me
.
inode
.
Files
(
O_ANYWRITE
)
func
(
n
*
pathInode
)
Truncate
(
file
File
,
size
uint64
,
context
*
Context
)
(
code
Status
)
{
files
:=
n
.
inode
.
Files
(
O_ANYWRITE
)
for
_
,
f
:=
range
files
{
// TODO - pass context
code
=
f
.
Truncate
(
size
)
...
...
@@ -599,13 +599,13 @@ func (me *pathInode) Truncate(file File, size uint64, context *Context) (code St
}
}
if
len
(
files
)
==
0
||
code
==
ENOSYS
||
code
==
EBADF
{
code
=
me
.
fs
.
Truncate
(
me
.
GetPath
(),
size
,
context
)
code
=
n
.
fs
.
Truncate
(
n
.
GetPath
(),
size
,
context
)
}
return
code
}
func
(
me
*
pathInode
)
Utimens
(
file
File
,
atime
int64
,
mtime
int64
,
context
*
Context
)
(
code
Status
)
{
files
:=
me
.
inode
.
Files
(
O_ANYWRITE
)
func
(
n
*
pathInode
)
Utimens
(
file
File
,
atime
int64
,
mtime
int64
,
context
*
Context
)
(
code
Status
)
{
files
:=
n
.
inode
.
Files
(
O_ANYWRITE
)
for
_
,
f
:=
range
files
{
// TODO - pass context
code
=
f
.
Utimens
(
atime
,
mtime
)
...
...
@@ -614,7 +614,7 @@ func (me *pathInode) Utimens(file File, atime int64, mtime int64, context *Conte
}
}
if
len
(
files
)
==
0
||
code
==
ENOSYS
||
code
==
EBADF
{
code
=
me
.
fs
.
Utimens
(
me
.
GetPath
(),
atime
,
mtime
,
context
)
code
=
n
.
fs
.
Utimens
(
n
.
GetPath
(),
atime
,
mtime
,
context
)
}
return
code
}
fuse/prefixfs.go
View file @
ce603372
...
...
@@ -11,102 +11,102 @@ type PrefixFileSystem struct {
Prefix
string
}
func
(
me
*
PrefixFileSystem
)
prefixed
(
n
string
)
string
{
return
filepath
.
Join
(
me
.
Prefix
,
n
)
func
(
fs
*
PrefixFileSystem
)
prefixed
(
n
string
)
string
{
return
filepath
.
Join
(
fs
.
Prefix
,
n
)
}
func
(
me
*
PrefixFileSystem
)
GetAttr
(
name
string
,
context
*
Context
)
(
*
Attr
,
Status
)
{
return
me
.
FileSystem
.
GetAttr
(
me
.
prefixed
(
name
),
context
)
func
(
fs
*
PrefixFileSystem
)
GetAttr
(
name
string
,
context
*
Context
)
(
*
Attr
,
Status
)
{
return
fs
.
FileSystem
.
GetAttr
(
fs
.
prefixed
(
name
),
context
)
}
func
(
me
*
PrefixFileSystem
)
Readlink
(
name
string
,
context
*
Context
)
(
string
,
Status
)
{
return
me
.
FileSystem
.
Readlink
(
me
.
prefixed
(
name
),
context
)
func
(
fs
*
PrefixFileSystem
)
Readlink
(
name
string
,
context
*
Context
)
(
string
,
Status
)
{
return
fs
.
FileSystem
.
Readlink
(
fs
.
prefixed
(
name
),
context
)
}
func
(
me
*
PrefixFileSystem
)
Mknod
(
name
string
,
mode
uint32
,
dev
uint32
,
context
*
Context
)
Status
{
return
me
.
FileSystem
.
Mknod
(
me
.
prefixed
(
name
),
mode
,
dev
,
context
)
func
(
fs
*
PrefixFileSystem
)
Mknod
(
name
string
,
mode
uint32
,
dev
uint32
,
context
*
Context
)
Status
{
return
fs
.
FileSystem
.
Mknod
(
fs
.
prefixed
(
name
),
mode
,
dev
,
context
)
}
func
(
me
*
PrefixFileSystem
)
Mkdir
(
name
string
,
mode
uint32
,
context
*
Context
)
Status
{
return
me
.
FileSystem
.
Mkdir
(
me
.
prefixed
(
name
),
mode
,
context
)
func
(
fs
*
PrefixFileSystem
)
Mkdir
(
name
string
,
mode
uint32
,
context
*
Context
)
Status
{
return
fs
.
FileSystem
.
Mkdir
(
fs
.
prefixed
(
name
),
mode
,
context
)
}
func
(
me
*
PrefixFileSystem
)
Unlink
(
name
string
,
context
*
Context
)
(
code
Status
)
{
return
me
.
FileSystem
.
Unlink
(
me
.
prefixed
(
name
),
context
)
func
(
fs
*
PrefixFileSystem
)
Unlink
(
name
string
,
context
*
Context
)
(
code
Status
)
{
return
fs
.
FileSystem
.
Unlink
(
fs
.
prefixed
(
name
),
context
)
}
func
(
me
*
PrefixFileSystem
)
Rmdir
(
name
string
,
context
*
Context
)
(
code
Status
)
{
return
me
.
FileSystem
.
Rmdir
(
me
.
prefixed
(
name
),
context
)
func
(
fs
*
PrefixFileSystem
)
Rmdir
(
name
string
,
context
*
Context
)
(
code
Status
)
{
return
fs
.
FileSystem
.
Rmdir
(
fs
.
prefixed
(
name
),
context
)
}
func
(
me
*
PrefixFileSystem
)
Symlink
(
value
string
,
linkName
string
,
context
*
Context
)
(
code
Status
)
{
return
me
.
FileSystem
.
Symlink
(
value
,
me
.
prefixed
(
linkName
),
context
)
func
(
fs
*
PrefixFileSystem
)
Symlink
(
value
string
,
linkName
string
,
context
*
Context
)
(
code
Status
)
{
return
fs
.
FileSystem
.
Symlink
(
value
,
fs
.
prefixed
(
linkName
),
context
)
}
func
(
me
*
PrefixFileSystem
)
Rename
(
oldName
string
,
newName
string
,
context
*
Context
)
(
code
Status
)
{
return
me
.
FileSystem
.
Rename
(
me
.
prefixed
(
oldName
),
me
.
prefixed
(
newName
),
context
)
func
(
fs
*
PrefixFileSystem
)
Rename
(
oldName
string
,
newName
string
,
context
*
Context
)
(
code
Status
)
{
return
fs
.
FileSystem
.
Rename
(
fs
.
prefixed
(
oldName
),
fs
.
prefixed
(
newName
),
context
)
}
func
(
me
*
PrefixFileSystem
)
Link
(
oldName
string
,
newName
string
,
context
*
Context
)
(
code
Status
)
{
return
me
.
FileSystem
.
Link
(
me
.
prefixed
(
oldName
),
me
.
prefixed
(
newName
),
context
)
func
(
fs
*
PrefixFileSystem
)
Link
(
oldName
string
,
newName
string
,
context
*
Context
)
(
code
Status
)
{
return
fs
.
FileSystem
.
Link
(
fs
.
prefixed
(
oldName
),
fs
.
prefixed
(
newName
),
context
)
}
func
(
me
*
PrefixFileSystem
)
Chmod
(
name
string
,
mode
uint32
,
context
*
Context
)
(
code
Status
)
{
return
me
.
FileSystem
.
Chmod
(
me
.
prefixed
(
name
),
mode
,
context
)
func
(
fs
*
PrefixFileSystem
)
Chmod
(
name
string
,
mode
uint32
,
context
*
Context
)
(
code
Status
)
{
return
fs
.
FileSystem
.
Chmod
(
fs
.
prefixed
(
name
),
mode
,
context
)
}
func
(
me
*
PrefixFileSystem
)
Chown
(
name
string
,
uid
uint32
,
gid
uint32
,
context
*
Context
)
(
code
Status
)
{
return
me
.
FileSystem
.
Chown
(
me
.
prefixed
(
name
),
uid
,
gid
,
context
)
func
(
fs
*
PrefixFileSystem
)
Chown
(
name
string
,
uid
uint32
,
gid
uint32
,
context
*
Context
)
(
code
Status
)
{
return
fs
.
FileSystem
.
Chown
(
fs
.
prefixed
(
name
),
uid
,
gid
,
context
)
}
func
(
me
*
PrefixFileSystem
)
Truncate
(
name
string
,
offset
uint64
,
context
*
Context
)
(
code
Status
)
{
return
me
.
FileSystem
.
Truncate
(
me
.
prefixed
(
name
),
offset
,
context
)
func
(
fs
*
PrefixFileSystem
)
Truncate
(
name
string
,
offset
uint64
,
context
*
Context
)
(
code
Status
)
{
return
fs
.
FileSystem
.
Truncate
(
fs
.
prefixed
(
name
),
offset
,
context
)
}
func
(
me
*
PrefixFileSystem
)
Open
(
name
string
,
flags
uint32
,
context
*
Context
)
(
file
File
,
code
Status
)
{
return
me
.
FileSystem
.
Open
(
me
.
prefixed
(
name
),
flags
,
context
)
func
(
fs
*
PrefixFileSystem
)
Open
(
name
string
,
flags
uint32
,
context
*
Context
)
(
file
File
,
code
Status
)
{
return
fs
.
FileSystem
.
Open
(
fs
.
prefixed
(
name
),
flags
,
context
)
}
func
(
me
*
PrefixFileSystem
)
OpenDir
(
name
string
,
context
*
Context
)
(
stream
chan
DirEntry
,
status
Status
)
{
return
me
.
FileSystem
.
OpenDir
(
me
.
prefixed
(
name
),
context
)
func
(
fs
*
PrefixFileSystem
)
OpenDir
(
name
string
,
context
*
Context
)
(
stream
chan
DirEntry
,
status
Status
)
{
return
fs
.
FileSystem
.
OpenDir
(
fs
.
prefixed
(
name
),
context
)
}
func
(
me
*
PrefixFileSystem
)
OnMount
(
nodeFs
*
PathNodeFs
)
{
me
.
FileSystem
.
OnMount
(
nodeFs
)
func
(
fs
*
PrefixFileSystem
)
OnMount
(
nodeFs
*
PathNodeFs
)
{
fs
.
FileSystem
.
OnMount
(
nodeFs
)
}
func
(
me
*
PrefixFileSystem
)
OnUnmount
()
{
me
.
FileSystem
.
OnUnmount
()
func
(
fs
*
PrefixFileSystem
)
OnUnmount
()
{
fs
.
FileSystem
.
OnUnmount
()
}
func
(
me
*
PrefixFileSystem
)
Access
(
name
string
,
mode
uint32
,
context
*
Context
)
(
code
Status
)
{
return
me
.
FileSystem
.
Access
(
me
.
prefixed
(
name
),
mode
,
context
)
func
(
fs
*
PrefixFileSystem
)
Access
(
name
string
,
mode
uint32
,
context
*
Context
)
(
code
Status
)
{
return
fs
.
FileSystem
.
Access
(
fs
.
prefixed
(
name
),
mode
,
context
)
}
func
(
me
*
PrefixFileSystem
)
Create
(
name
string
,
flags
uint32
,
mode
uint32
,
context
*
Context
)
(
file
File
,
code
Status
)
{
return
me
.
FileSystem
.
Create
(
me
.
prefixed
(
name
),
flags
,
mode
,
context
)
func
(
fs
*
PrefixFileSystem
)
Create
(
name
string
,
flags
uint32
,
mode
uint32
,
context
*
Context
)
(
file
File
,
code
Status
)
{
return
fs
.
FileSystem
.
Create
(
fs
.
prefixed
(
name
),
flags
,
mode
,
context
)
}
func
(
me
*
PrefixFileSystem
)
Utimens
(
name
string
,
AtimeNs
int64
,
CtimeNs
int64
,
context
*
Context
)
(
code
Status
)
{
return
me
.
FileSystem
.
Utimens
(
me
.
prefixed
(
name
),
AtimeNs
,
CtimeNs
,
context
)
func
(
fs
*
PrefixFileSystem
)
Utimens
(
name
string
,
AtimeNs
int64
,
CtimeNs
int64
,
context
*
Context
)
(
code
Status
)
{
return
fs
.
FileSystem
.
Utimens
(
fs
.
prefixed
(
name
),
AtimeNs
,
CtimeNs
,
context
)
}
func
(
me
*
PrefixFileSystem
)
GetXAttr
(
name
string
,
attr
string
,
context
*
Context
)
([]
byte
,
Status
)
{
return
me
.
FileSystem
.
GetXAttr
(
me
.
prefixed
(
name
),
attr
,
context
)
func
(
fs
*
PrefixFileSystem
)
GetXAttr
(
name
string
,
attr
string
,
context
*
Context
)
([]
byte
,
Status
)
{
return
fs
.
FileSystem
.
GetXAttr
(
fs
.
prefixed
(
name
),
attr
,
context
)
}
func
(
me
*
PrefixFileSystem
)
SetXAttr
(
name
string
,
attr
string
,
data
[]
byte
,
flags
int
,
context
*
Context
)
Status
{
return
me
.
FileSystem
.
SetXAttr
(
me
.
prefixed
(
name
),
attr
,
data
,
flags
,
context
)
func
(
fs
*
PrefixFileSystem
)
SetXAttr
(
name
string
,
attr
string
,
data
[]
byte
,
flags
int
,
context
*
Context
)
Status
{
return
fs
.
FileSystem
.
SetXAttr
(
fs
.
prefixed
(
name
),
attr
,
data
,
flags
,
context
)
}
func
(
me
*
PrefixFileSystem
)
ListXAttr
(
name
string
,
context
*
Context
)
([]
string
,
Status
)
{
return
me
.
FileSystem
.
ListXAttr
(
me
.
prefixed
(
name
),
context
)
func
(
fs
*
PrefixFileSystem
)
ListXAttr
(
name
string
,
context
*
Context
)
([]
string
,
Status
)
{
return
fs
.
FileSystem
.
ListXAttr
(
fs
.
prefixed
(
name
),
context
)
}
func
(
me
*
PrefixFileSystem
)
RemoveXAttr
(
name
string
,
attr
string
,
context
*
Context
)
Status
{
return
me
.
FileSystem
.
RemoveXAttr
(
me
.
prefixed
(
name
),
attr
,
context
)
func
(
fs
*
PrefixFileSystem
)
RemoveXAttr
(
name
string
,
attr
string
,
context
*
Context
)
Status
{
return
fs
.
FileSystem
.
RemoveXAttr
(
fs
.
prefixed
(
name
),
attr
,
context
)
}
func
(
me
*
PrefixFileSystem
)
String
()
string
{
return
fmt
.
Sprintf
(
"PrefixFileSystem(%s,%s)"
,
me
.
FileSystem
.
String
(),
me
.
Prefix
)
func
(
fs
*
PrefixFileSystem
)
String
()
string
{
return
fmt
.
Sprintf
(
"PrefixFileSystem(%s,%s)"
,
fs
.
FileSystem
.
String
(),
fs
.
Prefix
)
}
fuse/readonlyfs.go
View file @
ce603372
...
...
@@ -9,102 +9,102 @@ type ReadonlyFileSystem struct {
FileSystem
}
func
(
me
*
ReadonlyFileSystem
)
GetAttr
(
name
string
,
context
*
Context
)
(
*
Attr
,
Status
)
{
return
me
.
FileSystem
.
GetAttr
(
name
,
context
)
func
(
fs
*
ReadonlyFileSystem
)
GetAttr
(
name
string
,
context
*
Context
)
(
*
Attr
,
Status
)
{
return
fs
.
FileSystem
.
GetAttr
(
name
,
context
)
}
func
(
me
*
ReadonlyFileSystem
)
Readlink
(
name
string
,
context
*
Context
)
(
string
,
Status
)
{
return
me
.
FileSystem
.
Readlink
(
name
,
context
)
func
(
fs
*
ReadonlyFileSystem
)
Readlink
(
name
string
,
context
*
Context
)
(
string
,
Status
)
{
return
fs
.
FileSystem
.
Readlink
(
name
,
context
)
}
func
(
me
*
ReadonlyFileSystem
)
Mknod
(
name
string
,
mode
uint32
,
dev
uint32
,
context
*
Context
)
Status
{
func
(
fs
*
ReadonlyFileSystem
)
Mknod
(
name
string
,
mode
uint32
,
dev
uint32
,
context
*
Context
)
Status
{
return
EPERM
}
func
(
me
*
ReadonlyFileSystem
)
Mkdir
(
name
string
,
mode
uint32
,
context
*
Context
)
Status
{
func
(
fs
*
ReadonlyFileSystem
)
Mkdir
(
name
string
,
mode
uint32
,
context
*
Context
)
Status
{
return
EPERM
}
func
(
me
*
ReadonlyFileSystem
)
Unlink
(
name
string
,
context
*
Context
)
(
code
Status
)
{
func
(
fs
*
ReadonlyFileSystem
)
Unlink
(
name
string
,
context
*
Context
)
(
code
Status
)
{
return
EPERM
}
func
(
me
*
ReadonlyFileSystem
)
Rmdir
(
name
string
,
context
*
Context
)
(
code
Status
)
{
func
(
fs
*
ReadonlyFileSystem
)
Rmdir
(
name
string
,
context
*
Context
)
(
code
Status
)
{
return
EPERM
}
func
(
me
*
ReadonlyFileSystem
)
Symlink
(
value
string
,
linkName
string
,
context
*
Context
)
(
code
Status
)
{
func
(
fs
*
ReadonlyFileSystem
)
Symlink
(
value
string
,
linkName
string
,
context
*
Context
)
(
code
Status
)
{
return
EPERM
}
func
(
me
*
ReadonlyFileSystem
)
Rename
(
oldName
string
,
newName
string
,
context
*
Context
)
(
code
Status
)
{
func
(
fs
*
ReadonlyFileSystem
)
Rename
(
oldName
string
,
newName
string
,
context
*
Context
)
(
code
Status
)
{
return
EPERM
}
func
(
me
*
ReadonlyFileSystem
)
Link
(
oldName
string
,
newName
string
,
context
*
Context
)
(
code
Status
)
{
func
(
fs
*
ReadonlyFileSystem
)
Link
(
oldName
string
,
newName
string
,
context
*
Context
)
(
code
Status
)
{
return
EPERM
}
func
(
me
*
ReadonlyFileSystem
)
Chmod
(
name
string
,
mode
uint32
,
context
*
Context
)
(
code
Status
)
{
func
(
fs
*
ReadonlyFileSystem
)
Chmod
(
name
string
,
mode
uint32
,
context
*
Context
)
(
code
Status
)
{
return
EPERM
}
func
(
me
*
ReadonlyFileSystem
)
Chown
(
name
string
,
uid
uint32
,
gid
uint32
,
context
*
Context
)
(
code
Status
)
{
func
(
fs
*
ReadonlyFileSystem
)
Chown
(
name
string
,
uid
uint32
,
gid
uint32
,
context
*
Context
)
(
code
Status
)
{
return
EPERM
}
func
(
me
*
ReadonlyFileSystem
)
Truncate
(
name
string
,
offset
uint64
,
context
*
Context
)
(
code
Status
)
{
func
(
fs
*
ReadonlyFileSystem
)
Truncate
(
name
string
,
offset
uint64
,
context
*
Context
)
(
code
Status
)
{
return
EPERM
}
func
(
me
*
ReadonlyFileSystem
)
Open
(
name
string
,
flags
uint32
,
context
*
Context
)
(
file
File
,
code
Status
)
{
func
(
fs
*
ReadonlyFileSystem
)
Open
(
name
string
,
flags
uint32
,
context
*
Context
)
(
file
File
,
code
Status
)
{
if
flags
&
O_ANYWRITE
!=
0
{
return
nil
,
EPERM
}
file
,
code
=
me
.
FileSystem
.
Open
(
name
,
flags
,
context
)
file
,
code
=
fs
.
FileSystem
.
Open
(
name
,
flags
,
context
)
return
&
ReadOnlyFile
{
file
},
code
}
func
(
me
*
ReadonlyFileSystem
)
OpenDir
(
name
string
,
context
*
Context
)
(
stream
chan
DirEntry
,
status
Status
)
{
return
me
.
FileSystem
.
OpenDir
(
name
,
context
)
func
(
fs
*
ReadonlyFileSystem
)
OpenDir
(
name
string
,
context
*
Context
)
(
stream
chan
DirEntry
,
status
Status
)
{
return
fs
.
FileSystem
.
OpenDir
(
name
,
context
)
}
func
(
me
*
ReadonlyFileSystem
)
OnMount
(
nodeFs
*
PathNodeFs
)
{
me
.
FileSystem
.
OnMount
(
nodeFs
)
func
(
fs
*
ReadonlyFileSystem
)
OnMount
(
nodeFs
*
PathNodeFs
)
{
fs
.
FileSystem
.
OnMount
(
nodeFs
)
}
func
(
me
*
ReadonlyFileSystem
)
OnUnmount
()
{
me
.
FileSystem
.
OnUnmount
()
func
(
fs
*
ReadonlyFileSystem
)
OnUnmount
()
{
fs
.
FileSystem
.
OnUnmount
()
}
func
(
me
*
ReadonlyFileSystem
)
String
()
string
{
return
fmt
.
Sprintf
(
"ReadonlyFileSystem(%v)"
,
me
.
FileSystem
)
func
(
fs
*
ReadonlyFileSystem
)
String
()
string
{
return
fmt
.
Sprintf
(
"ReadonlyFileSystem(%v)"
,
fs
.
FileSystem
)
}
func
(
me
*
ReadonlyFileSystem
)
Access
(
name
string
,
mode
uint32
,
context
*
Context
)
(
code
Status
)
{
return
me
.
FileSystem
.
Access
(
name
,
mode
,
context
)
func
(
fs
*
ReadonlyFileSystem
)
Access
(
name
string
,
mode
uint32
,
context
*
Context
)
(
code
Status
)
{
return
fs
.
FileSystem
.
Access
(
name
,
mode
,
context
)
}
func
(
me
*
ReadonlyFileSystem
)
Create
(
name
string
,
flags
uint32
,
mode
uint32
,
context
*
Context
)
(
file
File
,
code
Status
)
{
func
(
fs
*
ReadonlyFileSystem
)
Create
(
name
string
,
flags
uint32
,
mode
uint32
,
context
*
Context
)
(
file
File
,
code
Status
)
{
return
nil
,
EPERM
}
func
(
me
*
ReadonlyFileSystem
)
Utimens
(
name
string
,
AtimeNs
int64
,
CtimeNs
int64
,
context
*
Context
)
(
code
Status
)
{
func
(
fs
*
ReadonlyFileSystem
)
Utimens
(
name
string
,
AtimeNs
int64
,
CtimeNs
int64
,
context
*
Context
)
(
code
Status
)
{
return
EPERM
}
func
(
me
*
ReadonlyFileSystem
)
GetXAttr
(
name
string
,
attr
string
,
context
*
Context
)
([]
byte
,
Status
)
{
return
me
.
FileSystem
.
GetXAttr
(
name
,
attr
,
context
)
func
(
fs
*
ReadonlyFileSystem
)
GetXAttr
(
name
string
,
attr
string
,
context
*
Context
)
([]
byte
,
Status
)
{
return
fs
.
FileSystem
.
GetXAttr
(
name
,
attr
,
context
)
}
func
(
me
*
ReadonlyFileSystem
)
SetXAttr
(
name
string
,
attr
string
,
data
[]
byte
,
flags
int
,
context
*
Context
)
Status
{
func
(
fs
*
ReadonlyFileSystem
)
SetXAttr
(
name
string
,
attr
string
,
data
[]
byte
,
flags
int
,
context
*
Context
)
Status
{
return
EPERM
}
func
(
me
*
ReadonlyFileSystem
)
ListXAttr
(
name
string
,
context
*
Context
)
([]
string
,
Status
)
{
return
me
.
FileSystem
.
ListXAttr
(
name
,
context
)
func
(
fs
*
ReadonlyFileSystem
)
ListXAttr
(
name
string
,
context
*
Context
)
([]
string
,
Status
)
{
return
fs
.
FileSystem
.
ListXAttr
(
name
,
context
)
}
func
(
me
*
ReadonlyFileSystem
)
RemoveXAttr
(
name
string
,
attr
string
,
context
*
Context
)
Status
{
func
(
fs
*
ReadonlyFileSystem
)
RemoveXAttr
(
name
string
,
attr
string
,
context
*
Context
)
Status
{
return
EPERM
}
fuse/request.go
View file @
ce603372
...
...
@@ -52,29 +52,29 @@ type request struct {
handler
*
operationHandler
}
func
(
me
*
request
)
InputDebug
()
string
{
func
(
r
*
request
)
InputDebug
()
string
{
val
:=
" "
if
me
.
handler
.
DecodeIn
!=
nil
{
val
=
fmt
.
Sprintf
(
" data: %v "
,
me
.
handler
.
DecodeIn
(
me
.
inData
))
if
r
.
handler
.
DecodeIn
!=
nil
{
val
=
fmt
.
Sprintf
(
" data: %v "
,
r
.
handler
.
DecodeIn
(
r
.
inData
))
}
names
:=
""
if
me
.
filenames
!=
nil
{
names
=
fmt
.
Sprintf
(
"names: %v"
,
me
.
filenames
)
if
r
.
filenames
!=
nil
{
names
=
fmt
.
Sprintf
(
"names: %v"
,
r
.
filenames
)
}
if
len
(
me
.
arg
)
>
0
{
names
+=
fmt
.
Sprintf
(
" %d bytes"
,
len
(
me
.
arg
))
if
len
(
r
.
arg
)
>
0
{
names
+=
fmt
.
Sprintf
(
" %d bytes"
,
len
(
r
.
arg
))
}
return
fmt
.
Sprintf
(
"Dispatch: %s, NodeId: %v.%v%v"
,
operationName
(
me
.
inHeader
.
Opcode
),
me
.
inHeader
.
NodeId
,
val
,
names
)
operationName
(
r
.
inHeader
.
Opcode
),
r
.
inHeader
.
NodeId
,
val
,
names
)
}
func
(
me
*
request
)
OutputDebug
()
string
{
func
(
r
*
request
)
OutputDebug
()
string
{
var
val
interface
{}
if
me
.
handler
.
DecodeOut
!=
nil
&&
me
.
outData
!=
nil
{
val
=
me
.
handler
.
DecodeOut
(
me
.
outData
)
if
r
.
handler
.
DecodeOut
!=
nil
&&
r
.
outData
!=
nil
{
val
=
r
.
handler
.
DecodeOut
(
r
.
outData
)
}
dataStr
:=
""
...
...
@@ -84,96 +84,96 @@ func (me *request) OutputDebug() string {
max
:=
1024
if
len
(
dataStr
)
>
max
{
dataStr
=
dataStr
[
:
max
]
+
fmt
.
Sprintf
(
" ...trimmed (response size %d)"
,
len
(
me
.
outHeaderBytes
))
dataStr
=
dataStr
[
:
max
]
+
fmt
.
Sprintf
(
" ...trimmed (response size %d)"
,
len
(
r
.
outHeaderBytes
))
}
flatStr
:=
""
if
len
(
me
.
flatData
)
>
0
{
if
me
.
handler
.
FileNameOut
{
s
:=
strings
.
TrimRight
(
string
(
me
.
flatData
),
"
\x00
"
)
if
len
(
r
.
flatData
)
>
0
{
if
r
.
handler
.
FileNameOut
{
s
:=
strings
.
TrimRight
(
string
(
r
.
flatData
),
"
\x00
"
)
flatStr
=
fmt
.
Sprintf
(
" %q"
,
s
)
}
else
{
flatStr
=
fmt
.
Sprintf
(
" %d bytes data
\n
"
,
len
(
me
.
flatData
))
flatStr
=
fmt
.
Sprintf
(
" %d bytes data
\n
"
,
len
(
r
.
flatData
))
}
}
return
fmt
.
Sprintf
(
"Serialize: %s code: %v value: %v%v"
,
operationName
(
me
.
inHeader
.
Opcode
),
me
.
status
,
dataStr
,
flatStr
)
operationName
(
r
.
inHeader
.
Opcode
),
r
.
status
,
dataStr
,
flatStr
)
}
// setInput returns true if it takes ownership of the argument, false if not.
func
(
me
*
request
)
setInput
(
input
[]
byte
)
bool
{
if
len
(
input
)
<
len
(
me
.
smallInputBuf
)
{
copy
(
me
.
smallInputBuf
[
:
],
input
)
me
.
inputBuf
=
me
.
smallInputBuf
[
:
len
(
input
)]
func
(
r
*
request
)
setInput
(
input
[]
byte
)
bool
{
if
len
(
input
)
<
len
(
r
.
smallInputBuf
)
{
copy
(
r
.
smallInputBuf
[
:
],
input
)
r
.
inputBuf
=
r
.
smallInputBuf
[
:
len
(
input
)]
return
false
}
me
.
inputBuf
=
input
me
.
bufferPoolInputBuf
=
input
r
.
inputBuf
=
input
r
.
bufferPoolInputBuf
=
input
return
true
}
func
(
me
*
request
)
parse
()
{
func
(
r
*
request
)
parse
()
{
inHSize
:=
int
(
unsafe
.
Sizeof
(
raw
.
InHeader
{}))
if
len
(
me
.
inputBuf
)
<
inHSize
{
log
.
Printf
(
"Short read for input header: %v"
,
me
.
inputBuf
)
if
len
(
r
.
inputBuf
)
<
inHSize
{
log
.
Printf
(
"Short read for input header: %v"
,
r
.
inputBuf
)
return
}
me
.
inHeader
=
(
*
raw
.
InHeader
)(
unsafe
.
Pointer
(
&
me
.
inputBuf
[
0
]))
me
.
arg
=
me
.
inputBuf
[
inHSize
:
]
r
.
inHeader
=
(
*
raw
.
InHeader
)(
unsafe
.
Pointer
(
&
r
.
inputBuf
[
0
]))
r
.
arg
=
r
.
inputBuf
[
inHSize
:
]
me
.
handler
=
getHandler
(
me
.
inHeader
.
Opcode
)
if
me
.
handler
==
nil
{
log
.
Printf
(
"Unknown opcode %d"
,
me
.
inHeader
.
Opcode
)
me
.
status
=
ENOSYS
r
.
handler
=
getHandler
(
r
.
inHeader
.
Opcode
)
if
r
.
handler
==
nil
{
log
.
Printf
(
"Unknown opcode %d"
,
r
.
inHeader
.
Opcode
)
r
.
status
=
ENOSYS
return
}
if
len
(
me
.
arg
)
<
int
(
me
.
handler
.
InputSize
)
{
log
.
Printf
(
"Short read for %v: %v"
,
operationName
(
me
.
inHeader
.
Opcode
),
me
.
arg
)
me
.
status
=
EIO
if
len
(
r
.
arg
)
<
int
(
r
.
handler
.
InputSize
)
{
log
.
Printf
(
"Short read for %v: %v"
,
operationName
(
r
.
inHeader
.
Opcode
),
r
.
arg
)
r
.
status
=
EIO
return
}
if
me
.
handler
.
InputSize
>
0
{
me
.
inData
=
unsafe
.
Pointer
(
&
me
.
arg
[
0
])
me
.
arg
=
me
.
arg
[
me
.
handler
.
InputSize
:
]
if
r
.
handler
.
InputSize
>
0
{
r
.
inData
=
unsafe
.
Pointer
(
&
r
.
arg
[
0
])
r
.
arg
=
r
.
arg
[
r
.
handler
.
InputSize
:
]
}
count
:=
me
.
handler
.
FileNames
count
:=
r
.
handler
.
FileNames
if
count
>
0
{
if
count
==
1
{
me
.
filenames
=
[]
string
{
string
(
me
.
arg
[
:
len
(
me
.
arg
)
-
1
])}
r
.
filenames
=
[]
string
{
string
(
r
.
arg
[
:
len
(
r
.
arg
)
-
1
])}
}
else
{
names
:=
bytes
.
SplitN
(
me
.
arg
[
:
len
(
me
.
arg
)
-
1
],
[]
byte
{
0
},
count
)
me
.
filenames
=
make
([]
string
,
len
(
names
))
names
:=
bytes
.
SplitN
(
r
.
arg
[
:
len
(
r
.
arg
)
-
1
],
[]
byte
{
0
},
count
)
r
.
filenames
=
make
([]
string
,
len
(
names
))
for
i
,
n
:=
range
names
{
me
.
filenames
[
i
]
=
string
(
n
)
r
.
filenames
[
i
]
=
string
(
n
)
}
if
len
(
names
)
!=
count
{
log
.
Println
(
"filename argument mismatch"
,
names
,
count
)
me
.
status
=
EIO
r
.
status
=
EIO
}
}
}
}
func
(
me
*
request
)
serialize
()
{
dataLength
:=
me
.
handler
.
OutputSize
if
me
.
outData
==
nil
||
me
.
status
>
OK
{
func
(
r
*
request
)
serialize
()
{
dataLength
:=
r
.
handler
.
OutputSize
if
r
.
outData
==
nil
||
r
.
status
>
OK
{
dataLength
=
0
}
sizeOfOutHeader
:=
unsafe
.
Sizeof
(
raw
.
OutHeader
{})
me
.
outHeaderBytes
=
make
([]
byte
,
sizeOfOutHeader
+
dataLength
)
outHeader
:=
(
*
raw
.
OutHeader
)(
unsafe
.
Pointer
(
&
me
.
outHeaderBytes
[
0
]))
outHeader
.
Unique
=
me
.
inHeader
.
Unique
outHeader
.
Status
=
int32
(
-
me
.
status
)
r
.
outHeaderBytes
=
make
([]
byte
,
sizeOfOutHeader
+
dataLength
)
outHeader
:=
(
*
raw
.
OutHeader
)(
unsafe
.
Pointer
(
&
r
.
outHeaderBytes
[
0
]))
outHeader
.
Unique
=
r
.
inHeader
.
Unique
outHeader
.
Status
=
int32
(
-
r
.
status
)
outHeader
.
Length
=
uint32
(
int
(
sizeOfOutHeader
)
+
int
(
dataLength
)
+
int
(
len
(
me
.
flatData
)))
int
(
sizeOfOutHeader
)
+
int
(
dataLength
)
+
int
(
len
(
r
.
flatData
)))
copy
(
me
.
outHeaderBytes
[
sizeOfOutHeader
:
],
asSlice
(
me
.
outData
,
dataLength
))
copy
(
r
.
outHeaderBytes
[
sizeOfOutHeader
:
],
asSlice
(
r
.
outData
,
dataLength
))
}
fuse/typeprint.go
View file @
ce603372
...
...
@@ -18,7 +18,7 @@ func init() {
}
}
func
(
me
*
Attr
)
String
()
string
{
func
(
a
*
Attr
)
String
()
string
{
return
fmt
.
Sprintf
(
"{M0%o S=%d L=%d "
+
"%d:%d "
+
...
...
@@ -26,11 +26,11 @@ func (me *Attr) String() string {
"A %d.%09d "
+
"M %d.%09d "
+
"C %d.%09d}"
,
me
.
Mode
,
me
.
Size
,
me
.
Nlink
,
me
.
Uid
,
me
.
Gid
,
me
.
Blocks
,
me
.
Blksize
,
me
.
Rdev
,
me
.
Ino
,
me
.
Atime
,
me
.
Atimensec
,
me
.
Mtime
,
me
.
Mtimensec
,
me
.
Ctime
,
me
.
Ctimensec
)
a
.
Mode
,
a
.
Size
,
a
.
Nlink
,
a
.
Uid
,
a
.
Gid
,
a
.
Blocks
,
a
.
Blksize
,
a
.
Rdev
,
a
.
Ino
,
a
.
Atime
,
a
.
Atimensec
,
a
.
Mtime
,
a
.
Mtimensec
,
a
.
Ctime
,
a
.
Ctimensec
)
}
func
(
me
*
ReadIn
)
String
()
string
{
...
...
fuse/xattr_test.go
View file @
ce603372
...
...
@@ -27,63 +27,63 @@ func NewXAttrFs(nm string, m map[string][]byte) *XAttrTestFs {
return
x
}
func
(
me
*
XAttrTestFs
)
GetAttr
(
name
string
,
context
*
Context
)
(
*
Attr
,
Status
)
{
func
(
fs
*
XAttrTestFs
)
GetAttr
(
name
string
,
context
*
Context
)
(
*
Attr
,
Status
)
{
a
:=
&
Attr
{}
if
name
==
""
||
name
==
"/"
{
a
.
Mode
=
S_IFDIR
|
0700
return
a
,
OK
}
if
name
==
me
.
filename
{
if
name
==
fs
.
filename
{
a
.
Mode
=
S_IFREG
|
0600
return
a
,
OK
}
return
nil
,
ENOENT
}
func
(
me
*
XAttrTestFs
)
SetXAttr
(
name
string
,
attr
string
,
data
[]
byte
,
flags
int
,
context
*
Context
)
Status
{
me
.
tester
.
Log
(
"SetXAttr"
,
name
,
attr
,
string
(
data
),
flags
)
if
name
!=
me
.
filename
{
func
(
fs
*
XAttrTestFs
)
SetXAttr
(
name
string
,
attr
string
,
data
[]
byte
,
flags
int
,
context
*
Context
)
Status
{
fs
.
tester
.
Log
(
"SetXAttr"
,
name
,
attr
,
string
(
data
),
flags
)
if
name
!=
fs
.
filename
{
return
ENOENT
}
dest
:=
make
([]
byte
,
len
(
data
))
copy
(
dest
,
data
)
me
.
attrs
[
attr
]
=
dest
fs
.
attrs
[
attr
]
=
dest
return
OK
}
func
(
me
*
XAttrTestFs
)
GetXAttr
(
name
string
,
attr
string
,
context
*
Context
)
([]
byte
,
Status
)
{
if
name
!=
me
.
filename
{
func
(
fs
*
XAttrTestFs
)
GetXAttr
(
name
string
,
attr
string
,
context
*
Context
)
([]
byte
,
Status
)
{
if
name
!=
fs
.
filename
{
return
nil
,
ENOENT
}
v
,
ok
:=
me
.
attrs
[
attr
]
v
,
ok
:=
fs
.
attrs
[
attr
]
if
!
ok
{
return
nil
,
ENODATA
}
me
.
tester
.
Log
(
"GetXAttr"
,
string
(
v
))
fs
.
tester
.
Log
(
"GetXAttr"
,
string
(
v
))
return
v
,
OK
}
func
(
me
*
XAttrTestFs
)
ListXAttr
(
name
string
,
context
*
Context
)
(
data
[]
string
,
code
Status
)
{
if
name
!=
me
.
filename
{
func
(
fs
*
XAttrTestFs
)
ListXAttr
(
name
string
,
context
*
Context
)
(
data
[]
string
,
code
Status
)
{
if
name
!=
fs
.
filename
{
return
nil
,
ENOENT
}
for
k
:=
range
me
.
attrs
{
for
k
:=
range
fs
.
attrs
{
data
=
append
(
data
,
k
)
}
return
data
,
OK
}
func
(
me
*
XAttrTestFs
)
RemoveXAttr
(
name
string
,
attr
string
,
context
*
Context
)
Status
{
if
name
!=
me
.
filename
{
func
(
fs
*
XAttrTestFs
)
RemoveXAttr
(
name
string
,
attr
string
,
context
*
Context
)
Status
{
if
name
!=
fs
.
filename
{
return
ENOENT
}
_
,
ok
:=
me
.
attrs
[
attr
]
me
.
tester
.
Log
(
"RemoveXAttr"
,
name
,
attr
,
ok
)
_
,
ok
:=
fs
.
attrs
[
attr
]
fs
.
tester
.
Log
(
"RemoveXAttr"
,
name
,
attr
,
ok
)
if
!
ok
{
return
ENODATA
}
delete
(
me
.
attrs
,
attr
)
delete
(
fs
.
attrs
,
attr
)
return
OK
}
...
...
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