Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
go-fuse
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Levin Zimmermann
go-fuse
Commits
3ad26b23
Commit
3ad26b23
authored
May 15, 2011
by
Han-Wen Nienhuys
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add fuse.MountFileSystem() to encapsulate some main() boilerplate.
parent
6d31d546
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
55 additions
and
295 deletions
+55
-295
example/autounionfs/main.go
example/autounionfs/main.go
+7
-11
example/multizip/multizip.go
example/multizip/multizip.go
+8
-7
example/unionfs/main.go
example/unionfs/main.go
+3
-7
example/zipfs/main.go
example/zipfs/main.go
+5
-6
fuse/Makefile
fuse/Makefile
+1
-0
fuse/fsetattr_test.go
fuse/fsetattr_test.go
+3
-5
fuse/fuse.go
fuse/fuse.go
+9
-235
fuse/xattr_test.go
fuse/xattr_test.go
+3
-5
unionfs/autounion_test.go
unionfs/autounion_test.go
+3
-4
unionfs/unionfs_test.go
unionfs/unionfs_test.go
+2
-3
zipfs/multizip.go
zipfs/multizip.go
+5
-1
zipfs/multizip_test.go
zipfs/multizip_test.go
+6
-11
No files found.
example/autounionfs/main.go
View file @
3ad26b23
...
...
@@ -10,7 +10,7 @@ import (
func
main
()
{
debug
:=
flag
.
Bool
(
"debug"
,
false
,
"debug on"
)
threaded
:=
flag
.
Bool
(
"threaded"
,
true
,
"
debu
g on"
)
threaded
:=
flag
.
Bool
(
"threaded"
,
true
,
"
threadin
g on"
)
delcache_ttl
:=
flag
.
Float64
(
"deletion_cache_ttl"
,
5.0
,
"Deletion cache TTL in seconds."
)
branchcache_ttl
:=
flag
.
Float64
(
"branchcache_ttl"
,
5.0
,
"Branch cache TTL in seconds."
)
deldirname
:=
flag
.
String
(
...
...
@@ -21,8 +21,6 @@ func main() {
fmt
.
Println
(
"Usage:
\n
main MOUNTPOINT BASEDIR"
)
os
.
Exit
(
2
)
}
mountpoint
:=
flag
.
Arg
(
0
)
ufsOptions
:=
unionfs
.
UnionFsOptions
{
DeletionCacheTTLSecs
:
*
delcache_ttl
,
BranchCacheTTLSecs
:
*
branchcache_ttl
,
...
...
@@ -39,16 +37,14 @@ func main() {
}
gofs
:=
unionfs
.
NewAutoUnionFs
(
flag
.
Arg
(
1
),
options
)
conn
:=
fuse
.
NewFileSystemConnector
(
gofs
,
nil
)
conn
.
Debug
=
*
debug
mountState
:=
fuse
.
NewMountState
(
conn
)
mountState
.
Debug
=
*
debug
fmt
.
Printf
(
"Go-FUSE %v Mounting AutoUnionFs...
\n
"
,
fuse
.
Version
())
err
:=
mountState
.
Mount
(
mountpoint
)
state
,
conn
,
err
:=
fuse
.
MountFileSystem
(
flag
.
Arg
(
0
),
gofs
,
nil
)
if
err
!=
nil
{
fmt
.
Printf
(
"Mount fail: %v
\n
"
,
err
)
os
.
Exit
(
1
)
}
fmt
.
Printf
(
"Mounted!
\n
"
)
mountState
.
Loop
(
*
threaded
)
conn
.
Debug
=
*
debug
state
.
Debug
=
*
debug
state
.
Loop
(
*
threaded
)
}
example/multizip/multizip.go
View file @
3ad26b23
...
...
@@ -13,6 +13,7 @@ var _ = log.Printf
func
main
()
{
// Scans the arg list and sets up flags
debug
:=
flag
.
Bool
(
"debug"
,
false
,
"debug on"
)
flag
.
Parse
()
if
flag
.
NArg
()
<
1
{
// TODO - where to get program name?
...
...
@@ -21,12 +22,12 @@ func main() {
}
fs
:=
zipfs
.
NewMultiZipFs
()
state
:=
fuse
.
NewMountState
(
fs
.
Connector
)
mountPoint
:=
flag
.
Arg
(
0
)
state
.
Debug
=
true
state
.
Mount
(
mountPoint
)
fmt
.
Printf
(
"Mounted %s
\n
"
,
mountPoint
)
state
,
_
,
err
:=
fuse
.
MountFileSystem
(
flag
.
Arg
(
0
),
fs
,
nil
)
if
err
!=
nil
{
fmt
.
Printf
(
"Mount fail: %v
\n
"
,
err
)
os
.
Exit
(
1
)
}
state
.
Debug
=
*
debug
state
.
Loop
(
true
)
}
example/unionfs/main.go
View file @
3ad26b23
...
...
@@ -21,7 +21,6 @@ func main() {
fmt
.
Println
(
"Usage:
\n
main MOUNTPOINT RW-DIRECTORY RO-DIRECTORY ..."
)
os
.
Exit
(
2
)
}
mountpoint
:=
flag
.
Arg
(
0
)
ufsOptions
:=
unionfs
.
UnionFsOptions
{
DeletionCacheTTLSecs
:
*
delcache_ttl
,
...
...
@@ -35,15 +34,12 @@ func main() {
}
ufs
:=
unionfs
.
NewUnionFs
(
"unionfs"
,
fses
,
ufsOptions
)
conn
:=
fuse
.
NewFileSystemConnector
(
ufs
,
nil
)
mountState
:=
fuse
.
NewMountState
(
conn
)
mountState
.
Debug
=
*
debug
fmt
.
Printf
(
"Go-FUSE Version %v.
\n
Mounting UnionFs...
\n
"
,
fuse
.
Version
())
err
:=
mountState
.
Mount
(
mountpoint
)
mountState
,
_
,
err
:=
fuse
.
MountFileSystem
(
flag
.
Arg
(
0
),
ufs
,
nil
)
if
err
!=
nil
{
fmt
.
Printf
(
"Mount fail: %v
\n
"
,
err
)
os
.
Exit
(
1
)
}
fmt
.
Printf
(
"Mounted!
\n
"
)
mountState
.
Debug
=
*
debug
mountState
.
Loop
(
*
threaded
)
}
example/zipfs/main.go
View file @
3ad26b23
...
...
@@ -35,19 +35,18 @@ func main() {
fs
=
debugFs
}
conn
:=
fuse
.
NewFileSystemConnector
(
fs
,
nil
)
state
:=
fuse
.
NewMountState
(
conn
)
state
,
conn
,
err
:=
fuse
.
MountFileSystem
(
flag
.
Arg
(
0
),
fs
,
nil
)
if
err
!=
nil
{
fmt
.
Printf
(
"Mount fail: %v
\n
"
,
err
)
os
.
Exit
(
1
)
}
if
*
latencies
{
debugFs
.
AddFileSystemConnector
(
conn
)
debugFs
.
AddMountState
(
state
)
}
mountPoint
:=
flag
.
Arg
(
0
)
state
.
SetRecordStatistics
(
*
latencies
)
state
.
Debug
=
*
debug
state
.
Mount
(
mountPoint
)
fmt
.
Printf
(
"Mounted %s - PID %s
\n
"
,
mountPoint
,
fuse
.
MyPID
())
state
.
Loop
(
true
)
}
fuse/Makefile
View file @
3ad26b23
...
...
@@ -17,6 +17,7 @@ GOFILES=\
loopback.go
\
misc.go
\
mount.go
\
mountstate.go
\
opcode.go
\
pathdebug.go
\
pathfilesystem.go
\
...
...
fuse/fsetattr_test.go
View file @
3ad26b23
...
...
@@ -124,14 +124,12 @@ func NewFile() *MutableDataFile {
func
TestFSetAttr
(
t
*
testing
.
T
)
{
fs
:=
&
FSetAttrFs
{}
c
:=
NewFileSystemConnector
(
fs
,
nil
)
state
:=
NewMountState
(
c
)
dir
:=
MakeTempDir
()
state
.
Mount
(
dir
)
defer
os
.
RemoveAll
(
dir
)
state
,
_
,
err
:=
MountFileSystem
(
dir
,
fs
,
nil
)
CheckSuccess
(
err
)
state
.
Debug
=
true
defer
state
.
Unmount
()
defer
os
.
RemoveAll
(
dir
)
go
state
.
Loop
(
false
)
...
...
fuse/fuse.go
View file @
3ad26b23
package
fuse
import
(
"log"
"os"
"syscall"
"time"
)
const
(
// bufSize should be a power of two to minimize lossage in
// BufferPool. The minimum is 8k, but it doesn't cost anything to
// use a much larger buffer.
bufSize
=
(
1
<<
16
)
maxRead
=
bufSize
-
PAGESIZE
"fmt"
)
// MountState contains the logic for reading from the FUSE device and
// translating it to RawFileSystem interface calls.
type
MountState
struct
{
// Empty if unmounted.
mountPoint
string
fileSystem
RawFileSystem
// I/O with kernel and daemon.
mountFile
*
os
.
File
// Dump debug info onto stdout.
Debug
bool
// For efficient reads and writes.
buffers
*
BufferPoolImpl
*
LatencyMap
kernelSettings
InitIn
}
func
(
me
*
MountState
)
KernelSettings
()
InitIn
{
return
me
.
kernelSettings
}
func
(
me
*
MountState
)
MountPoint
()
string
{
return
me
.
mountPoint
}
// Mount filesystem on mountPoint.
func
(
me
*
MountState
)
Mount
(
mountPoint
string
)
os
.
Error
{
file
,
mp
,
err
:=
mount
(
mountPoint
)
if
err
!=
nil
{
return
err
}
me
.
mountPoint
=
mp
me
.
mountFile
=
file
return
nil
}
func
(
me
*
MountState
)
SetRecordStatistics
(
record
bool
)
{
if
record
{
me
.
LatencyMap
=
NewLatencyMap
()
}
else
{
me
.
LatencyMap
=
nil
}
}
func
(
me
*
MountState
)
Unmount
()
os
.
Error
{
// Todo: flush/release all files/dirs?
result
:=
unmount
(
me
.
mountPoint
)
if
result
==
nil
{
me
.
mountPoint
=
""
}
return
result
}
func
NewMountState
(
fs
RawFileSystem
)
*
MountState
{
me
:=
new
(
MountState
)
me
.
mountPoint
=
""
me
.
fileSystem
=
fs
me
.
buffers
=
NewBufferPool
()
return
me
}
func
(
me
*
MountState
)
Latencies
()
map
[
string
]
float64
{
return
me
.
LatencyMap
.
Latencies
(
1e-3
)
}
func
(
me
*
MountState
)
OperationCounts
()
map
[
string
]
int
{
return
me
.
LatencyMap
.
Counts
()
}
func
(
me
*
MountState
)
BufferPoolStats
()
string
{
return
me
.
buffers
.
String
()
}
func
(
me
*
MountState
)
newRequest
(
oldReq
*
request
)
*
request
{
if
oldReq
!=
nil
{
me
.
buffers
.
FreeBuffer
(
oldReq
.
flatData
)
*
oldReq
=
request
{
status
:
OK
,
inputBuf
:
oldReq
.
inputBuf
[
0
:
bufSize
],
}
return
oldReq
}
return
&
request
{
status
:
OK
,
inputBuf
:
me
.
buffers
.
AllocBuffer
(
bufSize
),
}
}
func
(
me
*
MountState
)
readRequest
(
req
*
request
)
os
.
Error
{
n
,
err
:=
me
.
mountFile
.
Read
(
req
.
inputBuf
)
// If we start timing before the read, we may take into
// account waiting for input into the timing.
if
me
.
LatencyMap
!=
nil
{
req
.
startNs
=
time
.
Nanoseconds
()
}
req
.
inputBuf
=
req
.
inputBuf
[
0
:
n
]
return
err
}
func
(
me
*
MountState
)
recordStats
(
req
*
request
)
{
if
me
.
LatencyMap
!=
nil
{
endNs
:=
time
.
Nanoseconds
()
dt
:=
endNs
-
req
.
startNs
opname
:=
operationName
(
req
.
inHeader
.
opcode
)
me
.
LatencyMap
.
AddMany
(
[]
LatencyArg
{
{
opname
,
""
,
dt
},
{
opname
+
"-write"
,
""
,
endNs
-
req
.
preWriteNs
}})
}
}
// Loop initiates the FUSE loop. Normally, callers should run Loop()
// and wait for it to exit, but tests will want to run this in a
// goroutine.
//
// If threaded is given, each filesystem operation executes in a
// separate goroutine.
func
(
me
*
MountState
)
Loop
(
threaded
bool
)
{
// To limit scheduling overhead, we spawn multiple read loops.
// This means that the request once read does not need to be
// assigned to another thread, so it avoids a context switch.
if
threaded
{
for
i
:=
0
;
i
<
_BACKGROUND_TASKS
;
i
++
{
go
me
.
loop
()
}
}
me
.
loop
()
me
.
mountFile
.
Close
()
}
func
(
me
*
MountState
)
loop
()
{
var
lastReq
*
request
for
{
req
:=
me
.
newRequest
(
lastReq
)
lastReq
=
req
err
:=
me
.
readRequest
(
req
)
if
err
!=
nil
{
errNo
:=
OsErrorToErrno
(
err
)
// Retry.
if
errNo
==
syscall
.
ENOENT
{
continue
}
// According to fuse_chan_receive()
if
errNo
==
syscall
.
ENODEV
{
break
}
// What I see on linux-x86 2.6.35.10.
if
errNo
==
syscall
.
ENOSYS
{
break
}
log
.
Printf
(
"Failed to read from fuse conn: %v"
,
err
)
break
}
me
.
handleRequest
(
req
)
}
}
func
(
me
*
MountState
)
handleRequest
(
req
*
request
)
{
defer
me
.
recordStats
(
req
)
req
.
parse
()
if
req
.
handler
==
nil
{
req
.
status
=
ENOSYS
}
if
req
.
status
.
Ok
()
&&
me
.
Debug
{
log
.
Println
(
req
.
InputDebug
())
}
if
req
.
status
.
Ok
()
&&
req
.
handler
.
Func
==
nil
{
log
.
Printf
(
"Unimplemented opcode %v"
,
req
.
inHeader
.
opcode
)
req
.
status
=
ENOSYS
}
if
req
.
status
.
Ok
()
{
req
.
handler
.
Func
(
me
,
req
)
}
me
.
write
(
req
)
}
func
(
me
*
MountState
)
write
(
req
*
request
)
{
// If we try to write OK, nil, we will get
// error: writer: Writev [[16 0 0 0 0 0 0 0 17 0 0 0 0 0 0 0]]
// failed, err: writev: no such file or directory
if
req
.
inHeader
.
opcode
==
_OP_FORGET
{
return
}
req
.
serialize
()
if
me
.
Debug
{
log
.
Println
(
req
.
OutputDebug
())
}
if
me
.
LatencyMap
!=
nil
{
req
.
preWriteNs
=
time
.
Nanoseconds
()
}
if
req
.
outHeaderBytes
==
nil
{
return
}
var
err
os
.
Error
if
req
.
flatData
==
nil
{
_
,
err
=
me
.
mountFile
.
Write
(
req
.
outHeaderBytes
)
}
else
{
_
,
err
=
Writev
(
me
.
mountFile
.
Fd
(),
[][]
byte
{
req
.
outHeaderBytes
,
req
.
flatData
})
}
func
MountFileSystem
(
mountpoint
string
,
fs
FileSystem
,
opts
*
MountOptions
)
(
*
MountState
,
*
FileSystemConnector
,
os
.
Error
)
{
conn
:=
NewFileSystemConnector
(
fs
,
opts
)
mountState
:=
NewMountState
(
conn
)
fmt
.
Printf
(
"Go-FUSE Version %v.
\n
Mounting...
\n
"
,
Version
())
err
:=
mountState
.
Mount
(
mountpoint
)
if
err
!=
nil
{
log
.
Printf
(
"writer: Write/Writev %v failed, err: %v. opcode: %v"
,
req
.
outHeaderBytes
,
err
,
operationName
(
req
.
inHeader
.
opcode
))
return
nil
,
nil
,
err
}
fmt
.
Println
(
"Mounted!"
)
return
mountState
,
conn
,
nil
}
fuse/xattr_test.go
View file @
3ad26b23
...
...
@@ -92,20 +92,18 @@ func TestXAttrRead(t *testing.T) {
"user.attr1"
:
[]
byte
(
"val1"
),
"user.attr2"
:
[]
byte
(
"val2"
)}
xfs
:=
NewXAttrFs
(
nm
,
golden
)
connector
:=
NewFileSystemConnector
(
xfs
,
nil
)
mountPoint
:=
MakeTempDir
()
defer
os
.
RemoveAll
(
mountPoint
)
state
:=
NewMountState
(
connector
)
state
.
Mount
(
mountPoint
)
state
,
_
,
err
:=
MountFileSystem
(
mountPoint
,
xfs
,
nil
)
CheckSuccess
(
err
)
state
.
Debug
=
true
defer
state
.
Unmount
()
go
state
.
Loop
(
false
)
mounted
:=
filepath
.
Join
(
mountPoint
,
nm
)
_
,
err
:
=
os
.
Lstat
(
mounted
)
_
,
err
=
os
.
Lstat
(
mounted
)
if
err
!=
nil
{
t
.
Error
(
"Unexpected stat error"
,
err
)
}
...
...
unionfs/autounion_test.go
View file @
3ad26b23
...
...
@@ -44,9 +44,8 @@ func setup(t *testing.T) (workdir string, cleanup func()) {
WriteFile
(
wd
+
"/ro/file2"
,
"file2"
)
fs
:=
NewAutoUnionFs
(
wd
+
"/store"
,
testAOpts
)
connector
:=
fuse
.
NewFileSystemConnector
(
fs
,
&
testAOpts
.
MountOptions
)
state
:=
fuse
.
NewMountState
(
connector
)
state
.
Mount
(
wd
+
"/mount"
)
state
,
_
,
err
:=
fuse
.
MountFileSystem
(
wd
+
"/mount"
,
fs
,
&
testAOpts
.
MountOptions
)
CheckSuccess
(
err
)
state
.
Debug
=
true
go
state
.
Loop
(
false
)
...
...
@@ -76,7 +75,7 @@ func TestAutoFsSymlink(t *testing.T) {
// Need time for the unmount to be noticed.
log
.
Println
(
"sleeping..."
)
time
.
Sleep
(
entryTtl
*
2
e9
)
time
.
Sleep
(
2
*
entryTtl
*
1
e9
)
fi
,
_
=
os
.
Lstat
(
wd
+
"/mount/manual1"
)
if
fi
!=
nil
{
...
...
unionfs/unionfs_test.go
View file @
3ad26b23
...
...
@@ -48,9 +48,8 @@ func setupUfs(t *testing.T) (workdir string, cleanup func()) {
NegativeTimeout
:
entryTtl
,
}
connector
:=
fuse
.
NewFileSystemConnector
(
ufs
,
opts
)
state
:=
fuse
.
NewMountState
(
connector
)
state
.
Mount
(
wd
+
"/mount"
)
state
,
_
,
err
:=
fuse
.
MountFileSystem
(
wd
+
"/mount"
,
ufs
,
opts
)
CheckSuccess
(
err
)
state
.
Debug
=
true
go
state
.
Loop
(
false
)
...
...
zipfs/multizip.go
View file @
3ad26b23
...
...
@@ -87,10 +87,14 @@ func NewMultiZipFs() *MultiZipFs {
m
.
zips
=
make
(
map
[
string
]
*
MemTreeFileSystem
)
m
.
pendingZips
=
make
(
map
[
string
]
bool
)
m
.
dirZipFileMap
=
make
(
map
[
string
]
string
)
m
.
Connector
=
fuse
.
NewFileSystemConnector
(
m
,
nil
)
return
m
}
func
(
me
*
MultiZipFs
)
Mount
(
connector
*
fuse
.
FileSystemConnector
)
fuse
.
Status
{
me
.
Connector
=
connector
return
fuse
.
OK
}
func
(
me
*
MultiZipFs
)
OpenDir
(
name
string
)
(
stream
chan
fuse
.
DirEntry
,
code
fuse
.
Status
)
{
me
.
lock
.
RLock
()
defer
me
.
lock
.
RUnlock
()
...
...
zipfs/multizip_test.go
View file @
3ad26b23
...
...
@@ -8,12 +8,8 @@ import (
"time"
)
func
CheckSuccess
(
err
os
.
Error
)
{
if
err
!=
nil
{
log
.
Println
(
err
)
panic
(
"error"
)
}
}
var
_
=
log
.
Printf
var
CheckSuccess
=
fuse
.
CheckSuccess
func
TestMultiZipFs
(
t
*
testing
.
T
)
{
var
err
os
.
Error
...
...
@@ -22,14 +18,13 @@ func TestMultiZipFs(t *testing.T) {
zipFile
:=
wd
+
"/test.zip"
fs
:=
NewMultiZipFs
()
state
:=
fuse
.
NewMountState
(
fs
.
Connector
)
mountPoint
:=
fuse
.
MakeTempDir
()
state
,
_
,
err
:=
fuse
.
MountFileSystem
(
mountPoint
,
fs
,
nil
)
defer
os
.
RemoveAll
(
mountPoint
)
state
.
Debug
=
true
err
=
state
.
Mount
(
mountPoint
)
defer
state
.
Unmount
()
CheckSuccess
(
err
)
defer
state
.
Unmount
()
state
.
Debug
=
true
go
state
.
Loop
(
true
)
...
...
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