Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
J
jacobsa-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
jacobsa-fuse
Commits
ae5da07e
Commit
ae5da07e
authored
Jan 28, 2020
by
Michael Stapelberg
Committed by
GitHub
Jan 28, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
remove naked returns across the code base (#75)
fixes #73
parent
4898d792
Changes
39
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
39 changed files
with
678 additions
and
929 deletions
+678
-929
connection.go
connection.go
+30
-40
conversions.go
conversions.go
+48
-92
freelists.go
freelists.go
+6
-6
fsutil/fsutil.go
fsutil/fsutil.go
+6
-9
fusetesting/parallel.go
fusetesting/parallel.go
+41
-68
fusetesting/readdir.go
fusetesting/readdir.go
+4
-7
fusetesting/stat_darwin.go
fusetesting/stat_darwin.go
+4
-10
fusetesting/stat_linux.go
fusetesting/stat_linux.go
+4
-8
fuseutil/dirent.go
fuseutil/dirent.go
+2
-2
fuseutil/not_implemented_file_system.go
fuseutil/not_implemented_file_system.go
+56
-84
internal/buffer/in_message.go
internal/buffer/in_message.go
+15
-19
internal/buffer/out_message.go
internal/buffer/out_message.go
+7
-7
internal/buffer/out_message_test.go
internal/buffer/out_message_test.go
+7
-7
internal/freelist/freelist.go
internal/freelist/freelist.go
+4
-4
mount.go
mount.go
+10
-16
mount_config.go
mount_config.go
+2
-2
mount_darwin.go
mount_darwin.go
+13
-21
mount_test.go
mount_test.go
+2
-2
samples/cachingfs/caching_fs.go
samples/cachingfs/caching_fs.go
+19
-23
samples/cachingfs/caching_fs_test.go
samples/cachingfs/caching_fs_test.go
+3
-3
samples/dynamicfs/dynamic_fs.go
samples/dynamicfs/dynamic_fs.go
+32
-42
samples/errorfs/error_fs.go
samples/errorfs/error_fs.go
+35
-37
samples/flushfs/flush_fs.go
samples/flushfs/flush_fs.go
+40
-55
samples/flushfs/flush_fs_test.go
samples/flushfs/flush_fs_test.go
+20
-29
samples/forgetfs/forget_fs.go
samples/forgetfs/forget_fs.go
+22
-25
samples/hellofs/hello_fs.go
samples/hellofs/hello_fs.go
+27
-34
samples/in_process.go
samples/in_process.go
+13
-19
samples/interruptfs/interrupt_fs.go
samples/interruptfs/interrupt_fs.go
+19
-24
samples/memfs/inode.go
samples/memfs/inode.go
+29
-34
samples/memfs/memfs.go
samples/memfs/memfs.go
+78
-86
samples/memfs/posix_test.go
samples/memfs/posix_test.go
+1
-2
samples/mount_sample/mount.go
samples/mount_sample/mount.go
+13
-23
samples/statfs/statfs.go
samples/statfs/statfs.go
+16
-19
samples/statfs/statfs_darwin_test.go
samples/statfs/statfs_darwin_test.go
+2
-3
samples/statfs/statfs_test.go
samples/statfs/statfs_test.go
+7
-9
samples/subprocess.go
samples/subprocess.go
+29
-42
samples/unmount.go
samples/unmount.go
+4
-5
unmount_linux.go
unmount_linux.go
+4
-5
unmount_std.go
unmount_std.go
+4
-6
No files found.
connection.go
View file @
ae5da07e
...
@@ -95,8 +95,8 @@ func newConnection(
...
@@ -95,8 +95,8 @@ func newConnection(
cfg
MountConfig
,
cfg
MountConfig
,
debugLogger
*
log
.
Logger
,
debugLogger
*
log
.
Logger
,
errorLogger
*
log
.
Logger
,
errorLogger
*
log
.
Logger
,
dev
*
os
.
File
)
(
c
*
Connection
,
err
error
)
{
dev
*
os
.
File
)
(
*
Connection
,
error
)
{
c
=
&
Connection
{
c
:
=
&
Connection
{
cfg
:
cfg
,
cfg
:
cfg
,
debugLogger
:
debugLogger
,
debugLogger
:
debugLogger
,
errorLogger
:
errorLogger
,
errorLogger
:
errorLogger
,
...
@@ -105,30 +105,26 @@ func newConnection(
...
@@ -105,30 +105,26 @@ func newConnection(
}
}
// Initialize.
// Initialize.
err
=
c
.
Init
()
if
err
:=
c
.
Init
();
err
!=
nil
{
if
err
!=
nil
{
c
.
close
()
c
.
close
()
err
=
fmt
.
Errorf
(
"Init: %v"
,
err
)
return
nil
,
fmt
.
Errorf
(
"Init: %v"
,
err
)
return
}
}
return
return
c
,
nil
}
}
// Init performs the work necessary to cause the mount process to complete.
// Init performs the work necessary to cause the mount process to complete.
func
(
c
*
Connection
)
Init
()
(
err
error
)
{
func
(
c
*
Connection
)
Init
()
error
{
// Read the init op.
// Read the init op.
ctx
,
op
,
err
:=
c
.
ReadOp
()
ctx
,
op
,
err
:=
c
.
ReadOp
()
if
err
!=
nil
{
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"Reading init op: %v"
,
err
)
return
fmt
.
Errorf
(
"Reading init op: %v"
,
err
)
return
}
}
initOp
,
ok
:=
op
.
(
*
initOp
)
initOp
,
ok
:=
op
.
(
*
initOp
)
if
!
ok
{
if
!
ok
{
c
.
Reply
(
ctx
,
syscall
.
EPROTO
)
c
.
Reply
(
ctx
,
syscall
.
EPROTO
)
err
=
fmt
.
Errorf
(
"Expected *initOp, got %T"
,
op
)
return
fmt
.
Errorf
(
"Expected *initOp, got %T"
,
op
)
return
}
}
// Make sure the protocol version spoken by the kernel is new enough.
// Make sure the protocol version spoken by the kernel is new enough.
...
@@ -139,8 +135,7 @@ func (c *Connection) Init() (err error) {
...
@@ -139,8 +135,7 @@ func (c *Connection) Init() (err error) {
if
initOp
.
Kernel
.
LT
(
min
)
{
if
initOp
.
Kernel
.
LT
(
min
)
{
c
.
Reply
(
ctx
,
syscall
.
EPROTO
)
c
.
Reply
(
ctx
,
syscall
.
EPROTO
)
err
=
fmt
.
Errorf
(
"Version too old: %v"
,
initOp
.
Kernel
)
return
fmt
.
Errorf
(
"Version too old: %v"
,
initOp
.
Kernel
)
return
}
}
// Downgrade our protocol if necessary.
// Downgrade our protocol if necessary.
...
@@ -169,7 +164,7 @@ func (c *Connection) Init() (err error) {
...
@@ -169,7 +164,7 @@ func (c *Connection) Init() (err error) {
}
}
c
.
Reply
(
ctx
,
nil
)
c
.
Reply
(
ctx
,
nil
)
return
return
nil
}
}
// Log information for an operation with the given ID. calldepth is the depth
// Log information for an operation with the given ID. calldepth is the depth
...
@@ -228,9 +223,9 @@ func (c *Connection) recordCancelFunc(
...
@@ -228,9 +223,9 @@ func (c *Connection) recordCancelFunc(
// LOCKS_EXCLUDED(c.mu)
// LOCKS_EXCLUDED(c.mu)
func
(
c
*
Connection
)
beginOp
(
func
(
c
*
Connection
)
beginOp
(
opCode
uint32
,
opCode
uint32
,
fuseID
uint64
)
(
ctx
context
.
Context
)
{
fuseID
uint64
)
context
.
Context
{
// Start with the parent context.
// Start with the parent context.
ctx
=
c
.
cfg
.
OpContext
ctx
:
=
c
.
cfg
.
OpContext
// Set up a cancellation function.
// Set up a cancellation function.
//
//
...
@@ -246,7 +241,7 @@ func (c *Connection) beginOp(
...
@@ -246,7 +241,7 @@ func (c *Connection) beginOp(
c
.
recordCancelFunc
(
fuseID
,
cancel
)
c
.
recordCancelFunc
(
fuseID
,
cancel
)
}
}
return
return
ctx
}
}
// Clean up all state associated with an op to which the user has responded,
// Clean up all state associated with an op to which the user has responded,
...
@@ -307,14 +302,14 @@ func (c *Connection) handleInterrupt(fuseID uint64) {
...
@@ -307,14 +302,14 @@ func (c *Connection) handleInterrupt(fuseID uint64) {
// Read the next message from the kernel. The message must later be destroyed
// Read the next message from the kernel. The message must later be destroyed
// using destroyInMessage.
// using destroyInMessage.
func
(
c
*
Connection
)
readMessage
()
(
m
*
buffer
.
InMessage
,
err
error
)
{
func
(
c
*
Connection
)
readMessage
()
(
*
buffer
.
InMessage
,
error
)
{
// Allocate a message.
// Allocate a message.
m
=
c
.
getInMessage
()
m
:
=
c
.
getInMessage
()
// Loop past transient errors.
// Loop past transient errors.
for
{
for
{
// Attempt a reaed.
// Attempt a reaed.
err
=
m
.
Init
(
c
.
dev
)
err
:
=
m
.
Init
(
c
.
dev
)
// Special cases:
// Special cases:
//
//
...
@@ -336,28 +331,26 @@ func (c *Connection) readMessage() (m *buffer.InMessage, err error) {
...
@@ -336,28 +331,26 @@ func (c *Connection) readMessage() (m *buffer.InMessage, err error) {
if
err
!=
nil
{
if
err
!=
nil
{
c
.
putInMessage
(
m
)
c
.
putInMessage
(
m
)
m
=
nil
return
nil
,
err
return
}
}
return
return
m
,
nil
}
}
}
}
// Write the supplied message to the kernel.
// Write the supplied message to the kernel.
func
(
c
*
Connection
)
writeMessage
(
msg
[]
byte
)
(
err
error
)
{
func
(
c
*
Connection
)
writeMessage
(
msg
[]
byte
)
error
{
// Avoid the retry loop in os.File.Write.
// Avoid the retry loop in os.File.Write.
n
,
err
:=
syscall
.
Write
(
int
(
c
.
dev
.
Fd
()),
msg
)
n
,
err
:=
syscall
.
Write
(
int
(
c
.
dev
.
Fd
()),
msg
)
if
err
!=
nil
{
if
err
!=
nil
{
return
return
err
}
}
if
n
!=
len
(
msg
)
{
if
n
!=
len
(
msg
)
{
err
=
fmt
.
Errorf
(
"Wrote %d bytes; expected %d"
,
n
,
len
(
msg
))
return
fmt
.
Errorf
(
"Wrote %d bytes; expected %d"
,
n
,
len
(
msg
))
return
}
}
return
return
nil
}
}
// ReadOp consumes the next op from the kernel process, returning the op and a
// ReadOp consumes the next op from the kernel process, returning the op and a
...
@@ -371,14 +364,13 @@ func (c *Connection) writeMessage(msg []byte) (err error) {
...
@@ -371,14 +364,13 @@ func (c *Connection) writeMessage(msg []byte) (err error) {
// /dev/fuse. It must not be called multiple times concurrently.
// /dev/fuse. It must not be called multiple times concurrently.
//
//
// LOCKS_EXCLUDED(c.mu)
// LOCKS_EXCLUDED(c.mu)
func
(
c
*
Connection
)
ReadOp
()
(
ctx
context
.
Context
,
op
interface
{},
err
error
)
{
func
(
c
*
Connection
)
ReadOp
()
(
_
context
.
Context
,
op
interface
{},
_
error
)
{
// Keep going until we find a request we know how to convert.
// Keep going until we find a request we know how to convert.
for
{
for
{
// Read the next message from the kernel.
// Read the next message from the kernel.
var
inMsg
*
buffer
.
InMessage
inMsg
,
err
:=
c
.
readMessage
()
inMsg
,
err
=
c
.
readMessage
()
if
err
!=
nil
{
if
err
!=
nil
{
return
return
nil
,
nil
,
err
}
}
// Convert the message to an op.
// Convert the message to an op.
...
@@ -386,8 +378,7 @@ func (c *Connection) ReadOp() (ctx context.Context, op interface{}, err error) {
...
@@ -386,8 +378,7 @@ func (c *Connection) ReadOp() (ctx context.Context, op interface{}, err error) {
op
,
err
=
convertInMessage
(
inMsg
,
outMsg
,
c
.
protocol
)
op
,
err
=
convertInMessage
(
inMsg
,
outMsg
,
c
.
protocol
)
if
err
!=
nil
{
if
err
!=
nil
{
c
.
putOutMessage
(
outMsg
)
c
.
putOutMessage
(
outMsg
)
err
=
fmt
.
Errorf
(
"convertInMessage: %v"
,
err
)
return
nil
,
nil
,
fmt
.
Errorf
(
"convertInMessage: %v"
,
err
)
return
}
}
// Choose an ID for this operation for the purposes of logging, and log it.
// Choose an ID for this operation for the purposes of logging, and log it.
...
@@ -402,11 +393,11 @@ func (c *Connection) ReadOp() (ctx context.Context, op interface{}, err error) {
...
@@ -402,11 +393,11 @@ func (c *Connection) ReadOp() (ctx context.Context, op interface{}, err error) {
}
}
// Set up a context that remembers information about this op.
// Set up a context that remembers information about this op.
ctx
=
c
.
beginOp
(
inMsg
.
Header
()
.
Opcode
,
inMsg
.
Header
()
.
Unique
)
ctx
:
=
c
.
beginOp
(
inMsg
.
Header
()
.
Opcode
,
inMsg
.
Header
()
.
Unique
)
ctx
=
context
.
WithValue
(
ctx
,
contextKey
,
opState
{
inMsg
,
outMsg
,
op
})
ctx
=
context
.
WithValue
(
ctx
,
contextKey
,
opState
{
inMsg
,
outMsg
,
op
})
// Return the op to the user.
// Return the op to the user.
return
return
ctx
,
op
,
nil
}
}
}
}
...
@@ -499,10 +490,9 @@ func (c *Connection) Reply(ctx context.Context, opErr error) {
...
@@ -499,10 +490,9 @@ func (c *Connection) Reply(ctx context.Context, opErr error) {
// Close the connection. Must not be called until operations that were read
// Close the connection. Must not be called until operations that were read
// from the connection have been responded to.
// from the connection have been responded to.
func
(
c
*
Connection
)
close
()
(
err
error
)
{
func
(
c
*
Connection
)
close
()
error
{
// Posix doesn't say that close can be called concurrently with read or
// Posix doesn't say that close can be called concurrently with read or
// write, but luckily we exclude the possibility of a race by requiring the
// write, but luckily we exclude the possibility of a race by requiring the
// user to respond to all ops first.
// user to respond to all ops first.
err
=
c
.
dev
.
Close
()
return
c
.
dev
.
Close
()
return
}
}
conversions.go
View file @
ae5da07e
This diff is collapsed.
Click to expand it.
freelists.go
View file @
ae5da07e
...
@@ -25,16 +25,16 @@ import (
...
@@ -25,16 +25,16 @@ import (
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// LOCKS_EXCLUDED(c.mu)
// LOCKS_EXCLUDED(c.mu)
func
(
c
*
Connection
)
getInMessage
()
(
x
*
buffer
.
InMessage
)
{
func
(
c
*
Connection
)
getInMessage
()
*
buffer
.
InMessage
{
c
.
mu
.
Lock
()
c
.
mu
.
Lock
()
x
=
(
*
buffer
.
InMessage
)(
c
.
inMessages
.
Get
())
x
:
=
(
*
buffer
.
InMessage
)(
c
.
inMessages
.
Get
())
c
.
mu
.
Unlock
()
c
.
mu
.
Unlock
()
if
x
==
nil
{
if
x
==
nil
{
x
=
new
(
buffer
.
InMessage
)
x
=
new
(
buffer
.
InMessage
)
}
}
return
return
x
}
}
// LOCKS_EXCLUDED(c.mu)
// LOCKS_EXCLUDED(c.mu)
...
@@ -49,9 +49,9 @@ func (c *Connection) putInMessage(x *buffer.InMessage) {
...
@@ -49,9 +49,9 @@ func (c *Connection) putInMessage(x *buffer.InMessage) {
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// LOCKS_EXCLUDED(c.mu)
// LOCKS_EXCLUDED(c.mu)
func
(
c
*
Connection
)
getOutMessage
()
(
x
*
buffer
.
OutMessage
)
{
func
(
c
*
Connection
)
getOutMessage
()
*
buffer
.
OutMessage
{
c
.
mu
.
Lock
()
c
.
mu
.
Lock
()
x
=
(
*
buffer
.
OutMessage
)(
c
.
outMessages
.
Get
())
x
:
=
(
*
buffer
.
OutMessage
)(
c
.
outMessages
.
Get
())
c
.
mu
.
Unlock
()
c
.
mu
.
Unlock
()
if
x
==
nil
{
if
x
==
nil
{
...
@@ -59,7 +59,7 @@ func (c *Connection) getOutMessage() (x *buffer.OutMessage) {
...
@@ -59,7 +59,7 @@ func (c *Connection) getOutMessage() (x *buffer.OutMessage) {
}
}
x
.
Reset
()
x
.
Reset
()
return
return
x
}
}
// LOCKS_EXCLUDED(c.mu)
// LOCKS_EXCLUDED(c.mu)
...
...
fsutil/fsutil.go
View file @
ae5da07e
...
@@ -28,25 +28,22 @@ import (
...
@@ -28,25 +28,22 @@ import (
// Warning: this is not production-quality code, and should only be used for
// Warning: this is not production-quality code, and should only be used for
// testing purposes. In particular, there is a race between creating and
// testing purposes. In particular, there is a race between creating and
// unlinking by name.
// unlinking by name.
func
AnonymousFile
(
dir
string
)
(
f
*
os
.
File
,
err
error
)
{
func
AnonymousFile
(
dir
string
)
(
*
os
.
File
,
error
)
{
// Choose a prefix based on the binary name.
// Choose a prefix based on the binary name.
prefix
:=
path
.
Base
(
os
.
Args
[
0
])
prefix
:=
path
.
Base
(
os
.
Args
[
0
])
// Create the file.
// Create the file.
f
,
err
=
ioutil
.
TempFile
(
dir
,
prefix
)
f
,
err
:
=
ioutil
.
TempFile
(
dir
,
prefix
)
if
err
!=
nil
{
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"TempFile: %v"
,
err
)
return
nil
,
fmt
.
Errorf
(
"TempFile: %v"
,
err
)
return
}
}
// Unlink it.
// Unlink it.
err
=
os
.
Remove
(
f
.
Name
())
if
err
:=
os
.
Remove
(
f
.
Name
());
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"Remove: %v"
,
err
)
err
=
fmt
.
Errorf
(
"Remove: %v"
,
err
)
return
}
}
return
return
f
,
nil
}
}
// Call fdatasync on the supplied file.
// Call fdatasync on the supplied file.
...
...
fusetesting/parallel.go
View file @
ae5da07e
...
@@ -44,22 +44,18 @@ func RunCreateInParallelTest_NoTruncate(
...
@@ -44,22 +44,18 @@ func RunCreateInParallelTest_NoTruncate(
// Set up a function that opens the file with O_CREATE and then appends a
// Set up a function that opens the file with O_CREATE and then appends a
// byte to it.
// byte to it.
worker
:=
func
(
id
byte
)
(
err
error
)
{
worker
:=
func
(
id
byte
)
error
{
f
,
err
:=
os
.
OpenFile
(
filename
,
os
.
O_CREATE
|
os
.
O_WRONLY
|
os
.
O_APPEND
,
0600
)
f
,
err
:=
os
.
OpenFile
(
filename
,
os
.
O_CREATE
|
os
.
O_WRONLY
|
os
.
O_APPEND
,
0600
)
if
err
!=
nil
{
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"Worker %d: Open: %v"
,
id
,
err
)
return
fmt
.
Errorf
(
"Worker %d: Open: %v"
,
id
,
err
)
return
}
}
defer
f
.
Close
()
defer
f
.
Close
()
_
,
err
=
f
.
Write
([]
byte
{
id
})
if
_
,
err
:=
f
.
Write
([]
byte
{
id
});
err
!=
nil
{
if
err
!=
nil
{
return
fmt
.
Errorf
(
"Worker %d: Write: %v"
,
id
,
err
)
err
=
fmt
.
Errorf
(
"Worker %d: Write: %v"
,
id
,
err
)
return
}
}
return
return
nil
}
}
// Run several workers in parallel.
// Run several workers in parallel.
...
@@ -67,9 +63,8 @@ func RunCreateInParallelTest_NoTruncate(
...
@@ -67,9 +63,8 @@ func RunCreateInParallelTest_NoTruncate(
b
:=
syncutil
.
NewBundle
(
ctx
)
b
:=
syncutil
.
NewBundle
(
ctx
)
for
i
:=
0
;
i
<
numWorkers
;
i
++
{
for
i
:=
0
;
i
<
numWorkers
;
i
++
{
id
:=
byte
(
i
)
id
:=
byte
(
i
)
b
.
Add
(
func
(
ctx
context
.
Context
)
(
err
error
)
{
b
.
Add
(
func
(
ctx
context
.
Context
)
error
{
err
=
worker
(
id
)
return
worker
(
id
)
return
})
})
}
}
...
@@ -121,21 +116,16 @@ func RunCreateInParallelTest_Truncate(
...
@@ -121,21 +116,16 @@ func RunCreateInParallelTest_Truncate(
filename
,
filename
,
os
.
O_CREATE
|
os
.
O_WRONLY
|
os
.
O_APPEND
|
os
.
O_TRUNC
,
os
.
O_CREATE
|
os
.
O_WRONLY
|
os
.
O_APPEND
|
os
.
O_TRUNC
,
0600
)
0600
)
if
err
!=
nil
{
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"Worker %d: Open: %v"
,
id
,
err
)
return
fmt
.
Errorf
(
"Worker %d: Open: %v"
,
id
,
err
)
return
}
}
defer
f
.
Close
()
defer
f
.
Close
()
_
,
err
=
f
.
Write
([]
byte
{
id
})
if
_
,
err
:=
f
.
Write
([]
byte
{
id
});
err
!=
nil
{
if
err
!=
nil
{
return
fmt
.
Errorf
(
"Worker %d: Write: %v"
,
id
,
err
)
err
=
fmt
.
Errorf
(
"Worker %d: Write: %v"
,
id
,
err
)
return
}
}
return
return
nil
}
}
// Run several workers in parallel.
// Run several workers in parallel.
...
@@ -143,9 +133,8 @@ func RunCreateInParallelTest_Truncate(
...
@@ -143,9 +133,8 @@ func RunCreateInParallelTest_Truncate(
b
:=
syncutil
.
NewBundle
(
ctx
)
b
:=
syncutil
.
NewBundle
(
ctx
)
for
i
:=
0
;
i
<
numWorkers
;
i
++
{
for
i
:=
0
;
i
<
numWorkers
;
i
++
{
id
:=
byte
(
i
)
id
:=
byte
(
i
)
b
.
Add
(
func
(
ctx
context
.
Context
)
(
err
error
)
{
b
.
Add
(
func
(
ctx
context
.
Context
)
error
{
err
=
worker
(
id
)
return
worker
(
id
)
return
})
})
}
}
...
@@ -203,26 +192,22 @@ func RunCreateInParallelTest_Exclusive(
...
@@ -203,26 +192,22 @@ func RunCreateInParallelTest_Exclusive(
// If we failed to open due to the file already existing, just leave.
// If we failed to open due to the file already existing, just leave.
if
os
.
IsExist
(
err
)
{
if
os
.
IsExist
(
err
)
{
err
=
nil
return
nil
return
}
}
// Propgate other errors.
// Propgate other errors.
if
err
!=
nil
{
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"Worker %d: Open: %v"
,
id
,
err
)
return
fmt
.
Errorf
(
"Worker %d: Open: %v"
,
id
,
err
)
return
}
}
atomic
.
AddUint64
(
&
openCount
,
1
)
atomic
.
AddUint64
(
&
openCount
,
1
)
defer
f
.
Close
()
defer
f
.
Close
()
_
,
err
=
f
.
Write
([]
byte
{
id
})
if
_
,
err
:=
f
.
Write
([]
byte
{
id
});
err
!=
nil
{
if
err
!=
nil
{
return
fmt
.
Errorf
(
"Worker %d: Write: %v"
,
id
,
err
)
err
=
fmt
.
Errorf
(
"Worker %d: Write: %v"
,
id
,
err
)
return
}
}
return
return
nil
}
}
// Run several workers in parallel.
// Run several workers in parallel.
...
@@ -230,9 +215,8 @@ func RunCreateInParallelTest_Exclusive(
...
@@ -230,9 +215,8 @@ func RunCreateInParallelTest_Exclusive(
b
:=
syncutil
.
NewBundle
(
ctx
)
b
:=
syncutil
.
NewBundle
(
ctx
)
for
i
:=
0
;
i
<
numWorkers
;
i
++
{
for
i
:=
0
;
i
<
numWorkers
;
i
++
{
id
:=
byte
(
i
)
id
:=
byte
(
i
)
b
.
Add
(
func
(
ctx
context
.
Context
)
(
err
error
)
{
b
.
Add
(
func
(
ctx
context
.
Context
)
error
{
err
=
worker
(
id
)
return
worker
(
id
)
return
})
})
}
}
...
@@ -269,19 +253,16 @@ func RunMkdirInParallelTest(
...
@@ -269,19 +253,16 @@ func RunMkdirInParallelTest(
filename
:=
path
.
Join
(
dir
,
"foo"
)
filename
:=
path
.
Join
(
dir
,
"foo"
)
// Set up a function that creates the directory, ignoring EEXIST errors.
// Set up a function that creates the directory, ignoring EEXIST errors.
worker
:=
func
(
id
byte
)
(
err
error
)
{
worker
:=
func
(
id
byte
)
error
{
err
=
os
.
Mkdir
(
filename
,
0700
)
err
:=
os
.
Mkdir
(
filename
,
0700
)
if
os
.
IsExist
(
err
)
{
if
os
.
IsExist
(
err
)
{
err
=
nil
return
nil
}
}
if
err
!=
nil
{
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"Worker %d: Mkdir: %v"
,
id
,
err
)
return
fmt
.
Errorf
(
"Worker %d: Mkdir: %v"
,
id
,
err
)
return
}
}
return
return
nil
}
}
// Run several workers in parallel.
// Run several workers in parallel.
...
@@ -289,9 +270,8 @@ func RunMkdirInParallelTest(
...
@@ -289,9 +270,8 @@ func RunMkdirInParallelTest(
b
:=
syncutil
.
NewBundle
(
ctx
)
b
:=
syncutil
.
NewBundle
(
ctx
)
for
i
:=
0
;
i
<
numWorkers
;
i
++
{
for
i
:=
0
;
i
<
numWorkers
;
i
++
{
id
:=
byte
(
i
)
id
:=
byte
(
i
)
b
.
Add
(
func
(
ctx
context
.
Context
)
(
err
error
)
{
b
.
Add
(
func
(
ctx
context
.
Context
)
error
{
err
=
worker
(
id
)
return
worker
(
id
)
return
})
})
}
}
...
@@ -325,19 +305,17 @@ func RunSymlinkInParallelTest(
...
@@ -325,19 +305,17 @@ func RunSymlinkInParallelTest(
filename
:=
path
.
Join
(
dir
,
"foo"
)
filename
:=
path
.
Join
(
dir
,
"foo"
)
// Set up a function that creates the symlink, ignoring EEXIST errors.
// Set up a function that creates the symlink, ignoring EEXIST errors.
worker
:=
func
(
id
byte
)
(
err
error
)
{
worker
:=
func
(
id
byte
)
error
{
err
=
os
.
Symlink
(
"blah"
,
filename
)
err
:=
os
.
Symlink
(
"blah"
,
filename
)
if
os
.
IsExist
(
err
)
{
if
os
.
IsExist
(
err
)
{
err
=
nil
return
nil
}
}
if
err
!=
nil
{
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"Worker %d: Symlink: %v"
,
id
,
err
)
return
fmt
.
Errorf
(
"Worker %d: Symlink: %v"
,
id
,
err
)
return
}
}
return
return
nil
}
}
// Run several workers in parallel.
// Run several workers in parallel.
...
@@ -345,9 +323,8 @@ func RunSymlinkInParallelTest(
...
@@ -345,9 +323,8 @@ func RunSymlinkInParallelTest(
b
:=
syncutil
.
NewBundle
(
ctx
)
b
:=
syncutil
.
NewBundle
(
ctx
)
for
i
:=
0
;
i
<
numWorkers
;
i
++
{
for
i
:=
0
;
i
<
numWorkers
;
i
++
{
id
:=
byte
(
i
)
id
:=
byte
(
i
)
b
.
Add
(
func
(
ctx
context
.
Context
)
(
err
error
)
{
b
.
Add
(
func
(
ctx
context
.
Context
)
error
{
err
=
worker
(
id
)
return
worker
(
id
)
return
})
})
}
}
...
@@ -388,19 +365,16 @@ func RunHardlinkInParallelTest(
...
@@ -388,19 +365,16 @@ func RunHardlinkInParallelTest(
filename
:=
path
.
Join
(
dir
,
"foo"
)
filename
:=
path
.
Join
(
dir
,
"foo"
)
// Set up a function that creates the symlink, ignoring EEXIST errors.
// Set up a function that creates the symlink, ignoring EEXIST errors.
worker
:=
func
(
id
byte
)
(
err
error
)
{
worker
:=
func
(
id
byte
)
error
{
err
=
os
.
Link
(
originalFile
,
filename
)
err
:=
os
.
Link
(
originalFile
,
filename
)
if
os
.
IsExist
(
err
)
{
if
os
.
IsExist
(
err
)
{
err
=
nil
return
nil
}
}
if
err
!=
nil
{
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"Worker %d: Link: %v"
,
id
,
err
)
return
fmt
.
Errorf
(
"Worker %d: Link: %v"
,
id
,
err
)
return
}
}
return
return
nil
}
}
// Run several workers in parallel.
// Run several workers in parallel.
...
@@ -408,9 +382,8 @@ func RunHardlinkInParallelTest(
...
@@ -408,9 +382,8 @@ func RunHardlinkInParallelTest(
b
:=
syncutil
.
NewBundle
(
ctx
)
b
:=
syncutil
.
NewBundle
(
ctx
)
for
i
:=
0
;
i
<
numWorkers
;
i
++
{
for
i
:=
0
;
i
<
numWorkers
;
i
++
{
id
:=
byte
(
i
)
id
:=
byte
(
i
)
b
.
Add
(
func
(
ctx
context
.
Context
)
(
err
error
)
{
b
.
Add
(
func
(
ctx
context
.
Context
)
error
{
err
=
worker
(
id
)
return
worker
(
id
)
return
})
})
}
}
...
...
fusetesting/readdir.go
View file @
ae5da07e
...
@@ -37,8 +37,7 @@ func ReadDirPicky(dirname string) (entries []os.FileInfo, err error) {
...
@@ -37,8 +37,7 @@ func ReadDirPicky(dirname string) (entries []os.FileInfo, err error) {
// Open the directory.
// Open the directory.
f
,
err
:=
os
.
Open
(
dirname
)
f
,
err
:=
os
.
Open
(
dirname
)
if
err
!=
nil
{
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"Open: %v"
,
err
)
return
nil
,
fmt
.
Errorf
(
"Open: %v"
,
err
)
return
}
}
// Don't forget to close it later.
// Don't forget to close it later.
...
@@ -52,8 +51,7 @@ func ReadDirPicky(dirname string) (entries []os.FileInfo, err error) {
...
@@ -52,8 +51,7 @@ func ReadDirPicky(dirname string) (entries []os.FileInfo, err error) {
// Read all of the names from the directory.
// Read all of the names from the directory.
names
,
err
:=
f
.
Readdirnames
(
-
1
)
names
,
err
:=
f
.
Readdirnames
(
-
1
)
if
err
!=
nil
{
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"Readdirnames: %v"
,
err
)
return
nil
,
fmt
.
Errorf
(
"Readdirnames: %v"
,
err
)
return
}
}
// Stat each one.
// Stat each one.
...
@@ -62,8 +60,7 @@ func ReadDirPicky(dirname string) (entries []os.FileInfo, err error) {
...
@@ -62,8 +60,7 @@ func ReadDirPicky(dirname string) (entries []os.FileInfo, err error) {
fi
,
err
=
os
.
Lstat
(
path
.
Join
(
dirname
,
name
))
fi
,
err
=
os
.
Lstat
(
path
.
Join
(
dirname
,
name
))
if
err
!=
nil
{
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"Lstat(%s): %v"
,
name
,
err
)
return
nil
,
fmt
.
Errorf
(
"Lstat(%s): %v"
,
name
,
err
)
return
}
}
entries
=
append
(
entries
,
fi
)
entries
=
append
(
entries
,
fi
)
...
@@ -72,5 +69,5 @@ func ReadDirPicky(dirname string) (entries []os.FileInfo, err error) {
...
@@ -72,5 +69,5 @@ func ReadDirPicky(dirname string) (entries []os.FileInfo, err error) {
// Sort the entries by name.
// Sort the entries by name.
sort
.
Sort
(
sortedEntries
(
entries
))
sort
.
Sort
(
sortedEntries
(
entries
))
return
return
entries
,
nil
}
}
fusetesting/stat_darwin.go
View file @
ae5da07e
...
@@ -20,26 +20,20 @@ import (
...
@@ -20,26 +20,20 @@ import (
)
)
func
extractMtime
(
sys
interface
{})
(
mtime
time
.
Time
,
ok
bool
)
{
func
extractMtime
(
sys
interface
{})
(
mtime
time
.
Time
,
ok
bool
)
{
mtime
=
time
.
Unix
(
sys
.
(
*
syscall
.
Stat_t
)
.
Mtimespec
.
Unix
())
return
time
.
Unix
(
sys
.
(
*
syscall
.
Stat_t
)
.
Mtimespec
.
Unix
()),
true
ok
=
true
return
}
}
func
extractBirthtime
(
sys
interface
{})
(
birthtime
time
.
Time
,
ok
bool
)
{
func
extractBirthtime
(
sys
interface
{})
(
birthtime
time
.
Time
,
ok
bool
)
{
birthtime
=
time
.
Unix
(
sys
.
(
*
syscall
.
Stat_t
)
.
Birthtimespec
.
Unix
())
return
time
.
Unix
(
sys
.
(
*
syscall
.
Stat_t
)
.
Birthtimespec
.
Unix
()),
true
ok
=
true
return
}
}
func
extractNlink
(
sys
interface
{})
(
nlink
uint64
,
ok
bool
)
{
func
extractNlink
(
sys
interface
{})
(
nlink
uint64
,
ok
bool
)
{
nlink
=
uint64
(
sys
.
(
*
syscall
.
Stat_t
)
.
Nlink
)
return
uint64
(
sys
.
(
*
syscall
.
Stat_t
)
.
Nlink
),
true
ok
=
true
return
}
}
func
getTimes
(
stat
*
syscall
.
Stat_t
)
(
atime
,
ctime
,
mtime
time
.
Time
)
{
func
getTimes
(
stat
*
syscall
.
Stat_t
)
(
atime
,
ctime
,
mtime
time
.
Time
)
{
atime
=
time
.
Unix
(
stat
.
Atimespec
.
Unix
())
atime
=
time
.
Unix
(
stat
.
Atimespec
.
Unix
())
ctime
=
time
.
Unix
(
stat
.
Ctimespec
.
Unix
())
ctime
=
time
.
Unix
(
stat
.
Ctimespec
.
Unix
())
mtime
=
time
.
Unix
(
stat
.
Mtimespec
.
Unix
())
mtime
=
time
.
Unix
(
stat
.
Mtimespec
.
Unix
())
return
return
atime
,
ctime
,
mtime
}
}
fusetesting/stat_linux.go
View file @
ae5da07e
...
@@ -20,24 +20,20 @@ import (
...
@@ -20,24 +20,20 @@ import (
)
)
func
extractMtime
(
sys
interface
{})
(
mtime
time
.
Time
,
ok
bool
)
{
func
extractMtime
(
sys
interface
{})
(
mtime
time
.
Time
,
ok
bool
)
{
mtime
=
time
.
Unix
(
sys
.
(
*
syscall
.
Stat_t
)
.
Mtim
.
Unix
())
return
time
.
Unix
(
sys
.
(
*
syscall
.
Stat_t
)
.
Mtim
.
Unix
()),
true
ok
=
true
return
}
}
func
extractBirthtime
(
sys
interface
{})
(
birthtime
time
.
Time
,
ok
bool
)
{
func
extractBirthtime
(
sys
interface
{})
(
birthtime
time
.
Time
,
ok
bool
)
{
return
return
time
.
Time
{},
false
}
}
func
extractNlink
(
sys
interface
{})
(
nlink
uint64
,
ok
bool
)
{
func
extractNlink
(
sys
interface
{})
(
nlink
uint64
,
ok
bool
)
{
nlink
=
sys
.
(
*
syscall
.
Stat_t
)
.
Nlink
return
sys
.
(
*
syscall
.
Stat_t
)
.
Nlink
,
true
ok
=
true
return
}
}
func
getTimes
(
stat
*
syscall
.
Stat_t
)
(
atime
,
ctime
,
mtime
time
.
Time
)
{
func
getTimes
(
stat
*
syscall
.
Stat_t
)
(
atime
,
ctime
,
mtime
time
.
Time
)
{
atime
=
time
.
Unix
(
stat
.
Atim
.
Unix
())
atime
=
time
.
Unix
(
stat
.
Atim
.
Unix
())
ctime
=
time
.
Unix
(
stat
.
Ctim
.
Unix
())
ctime
=
time
.
Unix
(
stat
.
Ctim
.
Unix
())
mtime
=
time
.
Unix
(
stat
.
Mtim
.
Unix
())
mtime
=
time
.
Unix
(
stat
.
Mtim
.
Unix
())
return
return
atime
,
ctime
,
mtime
}
}
fuseutil/dirent.go
View file @
ae5da07e
...
@@ -79,7 +79,7 @@ func WriteDirent(buf []byte, d Dirent) (n int) {
...
@@ -79,7 +79,7 @@ func WriteDirent(buf []byte, d Dirent) (n int) {
// Do we have enough room?
// Do we have enough room?
totalLen
:=
direntSize
+
len
(
d
.
Name
)
+
padLen
totalLen
:=
direntSize
+
len
(
d
.
Name
)
+
padLen
if
totalLen
>
len
(
buf
)
{
if
totalLen
>
len
(
buf
)
{
return
return
n
}
}
// Write the header.
// Write the header.
...
@@ -101,5 +101,5 @@ func WriteDirent(buf []byte, d Dirent) (n int) {
...
@@ -101,5 +101,5 @@ func WriteDirent(buf []byte, d Dirent) (n int) {
n
+=
copy
(
buf
[
n
:
],
padding
[
:
padLen
])
n
+=
copy
(
buf
[
n
:
],
padding
[
:
padLen
])
}
}
return
return
n
}
}
fuseutil/not_implemented_file_system.go
View file @
ae5da07e
...
@@ -32,198 +32,170 @@ var _ FileSystem = &NotImplementedFileSystem{}
...
@@ -32,198 +32,170 @@ var _ FileSystem = &NotImplementedFileSystem{}
func
(
fs
*
NotImplementedFileSystem
)
StatFS
(
func
(
fs
*
NotImplementedFileSystem
)
StatFS
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
StatFSOp
)
(
err
error
)
{
op
*
fuseops
.
StatFSOp
)
error
{
err
=
fuse
.
ENOSYS
return
fuse
.
ENOSYS
return
}
}
func
(
fs
*
NotImplementedFileSystem
)
LookUpInode
(
func
(
fs
*
NotImplementedFileSystem
)
LookUpInode
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
LookUpInodeOp
)
(
err
error
)
{
op
*
fuseops
.
LookUpInodeOp
)
error
{
err
=
fuse
.
ENOSYS
return
fuse
.
ENOSYS
return
}
}
func
(
fs
*
NotImplementedFileSystem
)
GetInodeAttributes
(
func
(
fs
*
NotImplementedFileSystem
)
GetInodeAttributes
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
GetInodeAttributesOp
)
(
err
error
)
{
op
*
fuseops
.
GetInodeAttributesOp
)
error
{
err
=
fuse
.
ENOSYS
return
fuse
.
ENOSYS
return
}
}
func
(
fs
*
NotImplementedFileSystem
)
SetInodeAttributes
(
func
(
fs
*
NotImplementedFileSystem
)
SetInodeAttributes
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
SetInodeAttributesOp
)
(
err
error
)
{
op
*
fuseops
.
SetInodeAttributesOp
)
error
{
err
=
fuse
.
ENOSYS
return
fuse
.
ENOSYS
return
}
}
func
(
fs
*
NotImplementedFileSystem
)
ForgetInode
(
func
(
fs
*
NotImplementedFileSystem
)
ForgetInode
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
ForgetInodeOp
)
(
err
error
)
{
op
*
fuseops
.
ForgetInodeOp
)
error
{
err
=
fuse
.
ENOSYS
return
fuse
.
ENOSYS
return
}
}
func
(
fs
*
NotImplementedFileSystem
)
MkDir
(
func
(
fs
*
NotImplementedFileSystem
)
MkDir
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
MkDirOp
)
(
err
error
)
{
op
*
fuseops
.
MkDirOp
)
error
{
err
=
fuse
.
ENOSYS
return
fuse
.
ENOSYS
return
}
}
func
(
fs
*
NotImplementedFileSystem
)
MkNode
(
func
(
fs
*
NotImplementedFileSystem
)
MkNode
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
MkNodeOp
)
(
err
error
)
{
op
*
fuseops
.
MkNodeOp
)
error
{
err
=
fuse
.
ENOSYS
return
fuse
.
ENOSYS
return
}
}
func
(
fs
*
NotImplementedFileSystem
)
CreateFile
(
func
(
fs
*
NotImplementedFileSystem
)
CreateFile
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
CreateFileOp
)
(
err
error
)
{
op
*
fuseops
.
CreateFileOp
)
error
{
err
=
fuse
.
ENOSYS
return
fuse
.
ENOSYS
return
}
}
func
(
fs
*
NotImplementedFileSystem
)
CreateSymlink
(
func
(
fs
*
NotImplementedFileSystem
)
CreateSymlink
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
CreateSymlinkOp
)
(
err
error
)
{
op
*
fuseops
.
CreateSymlinkOp
)
error
{
err
=
fuse
.
ENOSYS
return
fuse
.
ENOSYS
return
}
}
func
(
fs
*
NotImplementedFileSystem
)
CreateLink
(
func
(
fs
*
NotImplementedFileSystem
)
CreateLink
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
CreateLinkOp
)
(
err
error
)
{
op
*
fuseops
.
CreateLinkOp
)
error
{
err
=
fuse
.
ENOSYS
return
fuse
.
ENOSYS
return
}
}
func
(
fs
*
NotImplementedFileSystem
)
Rename
(
func
(
fs
*
NotImplementedFileSystem
)
Rename
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
RenameOp
)
(
err
error
)
{
op
*
fuseops
.
RenameOp
)
error
{
err
=
fuse
.
ENOSYS
return
fuse
.
ENOSYS
return
}
}
func
(
fs
*
NotImplementedFileSystem
)
RmDir
(
func
(
fs
*
NotImplementedFileSystem
)
RmDir
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
RmDirOp
)
(
err
error
)
{
op
*
fuseops
.
RmDirOp
)
error
{
err
=
fuse
.
ENOSYS
return
fuse
.
ENOSYS
return
}
}
func
(
fs
*
NotImplementedFileSystem
)
Unlink
(
func
(
fs
*
NotImplementedFileSystem
)
Unlink
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
UnlinkOp
)
(
err
error
)
{
op
*
fuseops
.
UnlinkOp
)
error
{
err
=
fuse
.
ENOSYS
return
fuse
.
ENOSYS
return
}
}
func
(
fs
*
NotImplementedFileSystem
)
OpenDir
(
func
(
fs
*
NotImplementedFileSystem
)
OpenDir
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
OpenDirOp
)
(
err
error
)
{
op
*
fuseops
.
OpenDirOp
)
error
{
err
=
fuse
.
ENOSYS
return
fuse
.
ENOSYS
return
}
}
func
(
fs
*
NotImplementedFileSystem
)
ReadDir
(
func
(
fs
*
NotImplementedFileSystem
)
ReadDir
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
ReadDirOp
)
(
err
error
)
{
op
*
fuseops
.
ReadDirOp
)
error
{
err
=
fuse
.
ENOSYS
return
fuse
.
ENOSYS
return
}
}
func
(
fs
*
NotImplementedFileSystem
)
ReleaseDirHandle
(
func
(
fs
*
NotImplementedFileSystem
)
ReleaseDirHandle
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
ReleaseDirHandleOp
)
(
err
error
)
{
op
*
fuseops
.
ReleaseDirHandleOp
)
error
{
err
=
fuse
.
ENOSYS
return
fuse
.
ENOSYS
return
}
}
func
(
fs
*
NotImplementedFileSystem
)
OpenFile
(
func
(
fs
*
NotImplementedFileSystem
)
OpenFile
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
OpenFileOp
)
(
err
error
)
{
op
*
fuseops
.
OpenFileOp
)
error
{
err
=
fuse
.
ENOSYS
return
fuse
.
ENOSYS
return
}
}
func
(
fs
*
NotImplementedFileSystem
)
ReadFile
(
func
(
fs
*
NotImplementedFileSystem
)
ReadFile
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
ReadFileOp
)
(
err
error
)
{
op
*
fuseops
.
ReadFileOp
)
error
{
err
=
fuse
.
ENOSYS
return
fuse
.
ENOSYS
return
}
}
func
(
fs
*
NotImplementedFileSystem
)
WriteFile
(
func
(
fs
*
NotImplementedFileSystem
)
WriteFile
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
WriteFileOp
)
(
err
error
)
{
op
*
fuseops
.
WriteFileOp
)
error
{
err
=
fuse
.
ENOSYS
return
fuse
.
ENOSYS
return
}
}
func
(
fs
*
NotImplementedFileSystem
)
SyncFile
(
func
(
fs
*
NotImplementedFileSystem
)
SyncFile
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
SyncFileOp
)
(
err
error
)
{
op
*
fuseops
.
SyncFileOp
)
error
{
err
=
fuse
.
ENOSYS
return
fuse
.
ENOSYS
return
}
}
func
(
fs
*
NotImplementedFileSystem
)
FlushFile
(
func
(
fs
*
NotImplementedFileSystem
)
FlushFile
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
FlushFileOp
)
(
err
error
)
{
op
*
fuseops
.
FlushFileOp
)
error
{
err
=
fuse
.
ENOSYS
return
fuse
.
ENOSYS
return
}
}
func
(
fs
*
NotImplementedFileSystem
)
ReleaseFileHandle
(
func
(
fs
*
NotImplementedFileSystem
)
ReleaseFileHandle
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
ReleaseFileHandleOp
)
(
err
error
)
{
op
*
fuseops
.
ReleaseFileHandleOp
)
error
{
err
=
fuse
.
ENOSYS
return
fuse
.
ENOSYS
return
}
}
func
(
fs
*
NotImplementedFileSystem
)
ReadSymlink
(
func
(
fs
*
NotImplementedFileSystem
)
ReadSymlink
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
ReadSymlinkOp
)
(
err
error
)
{
op
*
fuseops
.
ReadSymlinkOp
)
error
{
err
=
fuse
.
ENOSYS
return
fuse
.
ENOSYS
return
}
}
func
(
fs
*
NotImplementedFileSystem
)
RemoveXattr
(
func
(
fs
*
NotImplementedFileSystem
)
RemoveXattr
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
RemoveXattrOp
)
(
err
error
)
{
op
*
fuseops
.
RemoveXattrOp
)
error
{
err
=
fuse
.
ENOSYS
return
fuse
.
ENOSYS
return
}
}
func
(
fs
*
NotImplementedFileSystem
)
GetXattr
(
func
(
fs
*
NotImplementedFileSystem
)
GetXattr
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
GetXattrOp
)
(
err
error
)
{
op
*
fuseops
.
GetXattrOp
)
error
{
err
=
fuse
.
ENOSYS
return
fuse
.
ENOSYS
return
}
}
func
(
fs
*
NotImplementedFileSystem
)
ListXattr
(
func
(
fs
*
NotImplementedFileSystem
)
ListXattr
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
ListXattrOp
)
(
err
error
)
{
op
*
fuseops
.
ListXattrOp
)
error
{
err
=
fuse
.
ENOSYS
return
fuse
.
ENOSYS
return
}
}
func
(
fs
*
NotImplementedFileSystem
)
SetXattr
(
func
(
fs
*
NotImplementedFileSystem
)
SetXattr
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
SetXattrOp
)
(
err
error
)
{
op
*
fuseops
.
SetXattrOp
)
error
{
err
=
fuse
.
ENOSYS
return
fuse
.
ENOSYS
return
}
}
func
(
fs
*
NotImplementedFileSystem
)
Fallocate
(
func
(
fs
*
NotImplementedFileSystem
)
Fallocate
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
FallocateOp
)
(
err
error
)
{
op
*
fuseops
.
FallocateOp
)
error
{
err
=
fuse
.
ENOSYS
return
fuse
.
ENOSYS
return
}
}
func
(
fs
*
NotImplementedFileSystem
)
Destroy
()
{
func
(
fs
*
NotImplementedFileSystem
)
Destroy
()
{
...
...
internal/buffer/in_message.go
View file @
ae5da07e
...
@@ -49,38 +49,34 @@ type InMessage struct {
...
@@ -49,38 +49,34 @@ type InMessage struct {
// Initialize with the data read by a single call to r.Read. The first call to
// Initialize with the data read by a single call to r.Read. The first call to
// Consume will consume the bytes directly after the fusekernel.InHeader
// Consume will consume the bytes directly after the fusekernel.InHeader
// struct.
// struct.
func
(
m
*
InMessage
)
Init
(
r
io
.
Reader
)
(
err
error
)
{
func
(
m
*
InMessage
)
Init
(
r
io
.
Reader
)
error
{
n
,
err
:=
r
.
Read
(
m
.
storage
[
:
])
n
,
err
:=
r
.
Read
(
m
.
storage
[
:
])
if
err
!=
nil
{
if
err
!=
nil
{
return
return
err
}
}
// Make sure the message is long enough.
// Make sure the message is long enough.
const
headerSize
=
unsafe
.
Sizeof
(
fusekernel
.
InHeader
{})
const
headerSize
=
unsafe
.
Sizeof
(
fusekernel
.
InHeader
{})
if
uintptr
(
n
)
<
headerSize
{
if
uintptr
(
n
)
<
headerSize
{
err
=
fmt
.
Errorf
(
"Unexpectedly read only %d bytes."
,
n
)
return
fmt
.
Errorf
(
"Unexpectedly read only %d bytes."
,
n
)
return
}
}
m
.
remaining
=
m
.
storage
[
headerSize
:
n
]
m
.
remaining
=
m
.
storage
[
headerSize
:
n
]
// Check the header's length.
// Check the header's length.
if
int
(
m
.
Header
()
.
Len
)
!=
n
{
if
int
(
m
.
Header
()
.
Len
)
!=
n
{
err
=
fmt
.
Errorf
(
return
fmt
.
Errorf
(
"Header says %d bytes, but we read %d"
,
"Header says %d bytes, but we read %d"
,
m
.
Header
()
.
Len
,
m
.
Header
()
.
Len
,
n
)
n
)
return
}
}
return
return
nil
}
}
// Return a reference to the header read in the most recent call to Init.
// Return a reference to the header read in the most recent call to Init.
func
(
m
*
InMessage
)
Header
()
(
h
*
fusekernel
.
InHeader
)
{
func
(
m
*
InMessage
)
Header
()
*
fusekernel
.
InHeader
{
h
=
(
*
fusekernel
.
InHeader
)(
unsafe
.
Pointer
(
&
m
.
storage
[
0
]))
return
(
*
fusekernel
.
InHeader
)(
unsafe
.
Pointer
(
&
m
.
storage
[
0
]))
return
}
}
// Return the number of bytes left to consume.
// Return the number of bytes left to consume.
...
@@ -90,26 +86,26 @@ func (m *InMessage) Len() uintptr {
...
@@ -90,26 +86,26 @@ func (m *InMessage) Len() uintptr {
// Consume the next n bytes from the message, returning a nil pointer if there
// Consume the next n bytes from the message, returning a nil pointer if there
// are fewer than n bytes available.
// are fewer than n bytes available.
func
(
m
*
InMessage
)
Consume
(
n
uintptr
)
(
p
unsafe
.
Pointer
)
{
func
(
m
*
InMessage
)
Consume
(
n
uintptr
)
unsafe
.
Pointer
{
if
m
.
Len
()
==
0
||
n
>
m
.
Len
()
{
if
m
.
Len
()
==
0
||
n
>
m
.
Len
()
{
return
return
nil
}
}
p
=
unsafe
.
Pointer
(
&
m
.
remaining
[
0
])
p
:
=
unsafe
.
Pointer
(
&
m
.
remaining
[
0
])
m
.
remaining
=
m
.
remaining
[
n
:
]
m
.
remaining
=
m
.
remaining
[
n
:
]
return
return
p
}
}
// Equivalent to Consume, except returns a slice of bytes. The result will be
// Equivalent to Consume, except returns a slice of bytes. The result will be
// nil if Consume would fail.
// nil if Consume would fail.
func
(
m
*
InMessage
)
ConsumeBytes
(
n
uintptr
)
(
b
[]
byte
)
{
func
(
m
*
InMessage
)
ConsumeBytes
(
n
uintptr
)
[]
byte
{
if
n
>
m
.
Len
()
{
if
n
>
m
.
Len
()
{
return
return
nil
}
}
b
=
m
.
remaining
[
:
n
]
b
:
=
m
.
remaining
[
:
n
]
m
.
remaining
=
m
.
remaining
[
n
:
]
m
.
remaining
=
m
.
remaining
[
n
:
]
return
return
b
}
}
internal/buffer/out_message.go
View file @
ae5da07e
...
@@ -81,28 +81,28 @@ func (m *OutMessage) OutHeader() *fusekernel.OutHeader {
...
@@ -81,28 +81,28 @@ func (m *OutMessage) OutHeader() *fusekernel.OutHeader {
// Grow grows m's buffer by the given number of bytes, returning a pointer to
// Grow grows m's buffer by the given number of bytes, returning a pointer to
// the start of the new segment, which is guaranteed to be zeroed. If there is
// the start of the new segment, which is guaranteed to be zeroed. If there is
// insufficient space, it returns nil.
// insufficient space, it returns nil.
func
(
m
*
OutMessage
)
Grow
(
n
int
)
(
p
unsafe
.
Pointer
)
{
func
(
m
*
OutMessage
)
Grow
(
n
int
)
unsafe
.
Pointer
{
p
=
m
.
GrowNoZero
(
n
)
p
:
=
m
.
GrowNoZero
(
n
)
if
p
!=
nil
{
if
p
!=
nil
{
memclr
(
p
,
uintptr
(
n
))
memclr
(
p
,
uintptr
(
n
))
}
}
return
return
p
}
}
// GrowNoZero is equivalent to Grow, except the new segment is not zeroed. Use
// GrowNoZero is equivalent to Grow, except the new segment is not zeroed. Use
// with caution!
// with caution!
func
(
m
*
OutMessage
)
GrowNoZero
(
n
int
)
(
p
unsafe
.
Pointer
)
{
func
(
m
*
OutMessage
)
GrowNoZero
(
n
int
)
unsafe
.
Pointer
{
// Will we overflow the buffer?
// Will we overflow the buffer?
o
:=
m
.
payloadOffset
o
:=
m
.
payloadOffset
if
len
(
m
.
payload
)
-
o
<
n
{
if
len
(
m
.
payload
)
-
o
<
n
{
return
return
nil
}
}
p
=
unsafe
.
Pointer
(
uintptr
(
unsafe
.
Pointer
(
&
m
.
payload
))
+
uintptr
(
o
))
p
:
=
unsafe
.
Pointer
(
uintptr
(
unsafe
.
Pointer
(
&
m
.
payload
))
+
uintptr
(
o
))
m
.
payloadOffset
=
o
+
n
m
.
payloadOffset
=
o
+
n
return
return
p
}
}
// ShrinkTo shrinks m to the given size. It panics if the size is greater than
// ShrinkTo shrinks m to the given size. It panics if the size is greater than
...
...
internal/buffer/out_message_test.go
View file @
ae5da07e
...
@@ -24,16 +24,16 @@ func toByteSlice(p unsafe.Pointer, n int) []byte {
...
@@ -24,16 +24,16 @@ func toByteSlice(p unsafe.Pointer, n int) []byte {
}
}
// fillWithGarbage writes random data to [p, p+n).
// fillWithGarbage writes random data to [p, p+n).
func
fillWithGarbage
(
p
unsafe
.
Pointer
,
n
int
)
(
err
error
)
{
func
fillWithGarbage
(
p
unsafe
.
Pointer
,
n
int
)
error
{
b
:=
toByteSlice
(
p
,
n
)
b
:=
toByteSlice
(
p
,
n
)
_
,
err
=
io
.
ReadFull
(
rand
.
Reader
,
b
)
_
,
err
:
=
io
.
ReadFull
(
rand
.
Reader
,
b
)
return
return
err
}
}
func
randBytes
(
n
int
)
(
b
[]
byte
,
err
error
)
{
func
randBytes
(
n
int
)
(
[]
byte
,
error
)
{
b
=
make
([]
byte
,
n
)
b
:
=
make
([]
byte
,
n
)
_
,
err
=
io
.
ReadFull
(
rand
.
Reader
,
b
)
_
,
err
:
=
io
.
ReadFull
(
rand
.
Reader
,
b
)
return
return
b
,
err
}
}
// findNonZero finds the offset of the first non-zero byte in [p, p+n). If
// findNonZero finds the offset of the first non-zero byte in [p, p+n). If
...
...
internal/freelist/freelist.go
View file @
ae5da07e
...
@@ -22,16 +22,16 @@ type Freelist struct {
...
@@ -22,16 +22,16 @@ type Freelist struct {
}
}
// Get an element from the freelist, returning nil if empty.
// Get an element from the freelist, returning nil if empty.
func
(
fl
*
Freelist
)
Get
()
(
p
unsafe
.
Pointer
)
{
func
(
fl
*
Freelist
)
Get
()
unsafe
.
Pointer
{
l
:=
len
(
fl
.
list
)
l
:=
len
(
fl
.
list
)
if
l
==
0
{
if
l
==
0
{
return
return
nil
}
}
p
=
fl
.
list
[
l
-
1
]
p
:
=
fl
.
list
[
l
-
1
]
fl
.
list
=
fl
.
list
[
:
l
-
1
]
fl
.
list
=
fl
.
list
[
:
l
-
1
]
return
return
p
}
}
// Contribute an element back to the freelist.
// Contribute an element back to the freelist.
...
...
mount.go
View file @
ae5da07e
...
@@ -35,25 +35,23 @@ type Server interface {
...
@@ -35,25 +35,23 @@ type Server interface {
func
Mount
(
func
Mount
(
dir
string
,
dir
string
,
server
Server
,
server
Server
,
config
*
MountConfig
)
(
mfs
*
MountedFileSystem
,
err
error
)
{
config
*
MountConfig
)
(
*
MountedFileSystem
,
error
)
{
// Sanity check: make sure the mount point exists and is a directory. This
// Sanity check: make sure the mount point exists and is a directory. This
// saves us from some confusing errors later on OS X.
// saves us from some confusing errors later on OS X.
fi
,
err
:=
os
.
Stat
(
dir
)
fi
,
err
:=
os
.
Stat
(
dir
)
switch
{
switch
{
case
os
.
IsNotExist
(
err
)
:
case
os
.
IsNotExist
(
err
)
:
return
return
nil
,
err
case
err
!=
nil
:
case
err
!=
nil
:
err
=
fmt
.
Errorf
(
"Statting mount point: %v"
,
err
)
return
nil
,
fmt
.
Errorf
(
"Statting mount point: %v"
,
err
)
return
case
!
fi
.
IsDir
()
:
case
!
fi
.
IsDir
()
:
err
=
fmt
.
Errorf
(
"Mount point %s is not a directory"
,
dir
)
return
nil
,
fmt
.
Errorf
(
"Mount point %s is not a directory"
,
dir
)
return
}
}
// Initialize the struct.
// Initialize the struct.
mfs
=
&
MountedFileSystem
{
mfs
:
=
&
MountedFileSystem
{
dir
:
dir
,
dir
:
dir
,
joinStatusAvailable
:
make
(
chan
struct
{}),
joinStatusAvailable
:
make
(
chan
struct
{}),
}
}
...
@@ -62,8 +60,7 @@ func Mount(
...
@@ -62,8 +60,7 @@ func Mount(
ready
:=
make
(
chan
error
,
1
)
ready
:=
make
(
chan
error
,
1
)
dev
,
err
:=
mount
(
dir
,
config
,
ready
)
dev
,
err
:=
mount
(
dir
,
config
,
ready
)
if
err
!=
nil
{
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"mount: %v"
,
err
)
return
nil
,
fmt
.
Errorf
(
"mount: %v"
,
err
)
return
}
}
// Choose a parent context for ops.
// Choose a parent context for ops.
...
@@ -78,10 +75,8 @@ func Mount(
...
@@ -78,10 +75,8 @@ func Mount(
config
.
DebugLogger
,
config
.
DebugLogger
,
config
.
ErrorLogger
,
config
.
ErrorLogger
,
dev
)
dev
)
if
err
!=
nil
{
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"newConnection: %v"
,
err
)
return
nil
,
fmt
.
Errorf
(
"newConnection: %v"
,
err
)
return
}
}
// Serve the connection in the background. When done, set the join status.
// Serve the connection in the background. When done, set the join status.
...
@@ -92,10 +87,9 @@ func Mount(
...
@@ -92,10 +87,9 @@ func Mount(
}()
}()
// Wait for the mount process to complete.
// Wait for the mount process to complete.
if
err
=
<-
ready
;
err
!=
nil
{
if
err
:=
<-
ready
;
err
!=
nil
{
err
=
fmt
.
Errorf
(
"mount (background): %v"
,
err
)
return
nil
,
fmt
.
Errorf
(
"mount (background): %v"
,
err
)
return
}
}
return
return
mfs
,
nil
}
}
mount_config.go
View file @
ae5da07e
...
@@ -213,14 +213,14 @@ func (c *MountConfig) toMap() (opts map[string]string) {
...
@@ -213,14 +213,14 @@ func (c *MountConfig) toMap() (opts map[string]string) {
opts
[
k
]
=
v
opts
[
k
]
=
v
}
}
return
return
opts
}
}
func
escapeOptionsKey
(
s
string
)
(
res
string
)
{
func
escapeOptionsKey
(
s
string
)
(
res
string
)
{
res
=
s
res
=
s
res
=
strings
.
Replace
(
res
,
`\`
,
`\\`
,
-
1
)
res
=
strings
.
Replace
(
res
,
`\`
,
`\\`
,
-
1
)
res
=
strings
.
Replace
(
res
,
`,`
,
`\,`
,
-
1
)
res
=
strings
.
Replace
(
res
,
`,`
,
`\,`
,
-
1
)
return
return
res
}
}
func
mapToOptionsString
(
opts
map
[
string
]
string
)
string
{
func
mapToOptionsString
(
opts
map
[
string
]
string
)
string
{
...
...
mount_darwin.go
View file @
ae5da07e
...
@@ -76,13 +76,11 @@ func openOSXFUSEDev(devPrefix string) (dev *os.File, err error) {
...
@@ -76,13 +76,11 @@ func openOSXFUSEDev(devPrefix string) (dev *os.File, err error) {
if
os
.
IsNotExist
(
err
)
{
if
os
.
IsNotExist
(
err
)
{
if
i
==
0
{
if
i
==
0
{
// Not even the first device was found. Fuse must not be loaded.
// Not even the first device was found. Fuse must not be loaded.
err
=
errNotLoaded
return
nil
,
errNotLoaded
return
}
}
// Otherwise we've run out of kernel-provided devices
// Otherwise we've run out of kernel-provided devices
err
=
errNoAvail
return
nil
,
errNoAvail
return
}
}
if
err2
,
ok
:=
err
.
(
*
os
.
PathError
);
ok
&&
err2
.
Err
==
syscall
.
EBUSY
{
if
err2
,
ok
:=
err
.
(
*
os
.
PathError
);
ok
&&
err2
.
Err
==
syscall
.
EBUSY
{
...
@@ -90,7 +88,7 @@ func openOSXFUSEDev(devPrefix string) (dev *os.File, err error) {
...
@@ -90,7 +88,7 @@ func openOSXFUSEDev(devPrefix string) (dev *os.File, err error) {
continue
continue
}
}
return
return
dev
,
nil
}
}
}
}
...
@@ -100,7 +98,7 @@ func callMount(
...
@@ -100,7 +98,7 @@ func callMount(
dir
string
,
dir
string
,
cfg
*
MountConfig
,
cfg
*
MountConfig
,
dev
*
os
.
File
,
dev
*
os
.
File
,
ready
chan
<-
error
)
(
err
error
)
{
ready
chan
<-
error
)
error
{
// The mount helper doesn't understand any escaping.
// The mount helper doesn't understand any escaping.
for
k
,
v
:=
range
cfg
.
toMap
()
{
for
k
,
v
:=
range
cfg
.
toMap
()
{
...
@@ -143,9 +141,8 @@ func callMount(
...
@@ -143,9 +141,8 @@ func callMount(
cmd
.
Stdout
=
&
buf
cmd
.
Stdout
=
&
buf
cmd
.
Stderr
=
&
buf
cmd
.
Stderr
=
&
buf
err
=
cmd
.
Start
()
if
err
:=
cmd
.
Start
();
err
!=
nil
{
if
err
!=
nil
{
return
err
return
}
}
// In the background, wait for the command to complete.
// In the background, wait for the command to complete.
...
@@ -162,7 +159,7 @@ func callMount(
...
@@ -162,7 +159,7 @@ func callMount(
ready
<-
err
ready
<-
err
}()
}()
return
return
nil
}
}
// Begin the process of mounting at the given directory, returning a connection
// Begin the process of mounting at the given directory, returning a connection
...
@@ -188,8 +185,7 @@ func mount(
...
@@ -188,8 +185,7 @@ func mount(
if
err
==
errNotLoaded
{
if
err
==
errNotLoaded
{
err
=
loadOSXFUSE
(
loc
.
Load
)
err
=
loadOSXFUSE
(
loc
.
Load
)
if
err
!=
nil
{
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"loadOSXFUSE: %v"
,
err
)
return
nil
,
fmt
.
Errorf
(
"loadOSXFUSE: %v"
,
err
)
return
}
}
dev
,
err
=
openOSXFUSEDev
(
loc
.
DevicePrefix
)
dev
,
err
=
openOSXFUSEDev
(
loc
.
DevicePrefix
)
...
@@ -197,21 +193,17 @@ func mount(
...
@@ -197,21 +193,17 @@ func mount(
// Propagate errors.
// Propagate errors.
if
err
!=
nil
{
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"openOSXFUSEDev: %v"
,
err
)
return
nil
,
fmt
.
Errorf
(
"openOSXFUSEDev: %v"
,
err
)
return
}
}
// Call the mount binary with the device.
// Call the mount binary with the device.
err
=
callMount
(
loc
.
Mount
,
loc
.
DaemonVar
,
dir
,
cfg
,
dev
,
ready
)
if
err
:=
callMount
(
loc
.
Mount
,
loc
.
DaemonVar
,
dir
,
cfg
,
dev
,
ready
);
err
!=
nil
{
if
err
!=
nil
{
dev
.
Close
()
dev
.
Close
()
err
=
fmt
.
Errorf
(
"callMount: %v"
,
err
)
return
nil
,
fmt
.
Errorf
(
"callMount: %v"
,
err
)
return
}
}
return
return
dev
,
nil
}
}
err
=
errOSXFUSENotFound
return
nil
,
errOSXFUSENotFound
return
}
}
mount_test.go
View file @
ae5da07e
...
@@ -26,8 +26,8 @@ type minimalFS struct {
...
@@ -26,8 +26,8 @@ type minimalFS struct {
func
(
fs
*
minimalFS
)
StatFS
(
func
(
fs
*
minimalFS
)
StatFS
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
StatFSOp
)
(
err
error
)
{
op
*
fuseops
.
StatFSOp
)
error
{
return
return
nil
}
}
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
...
...
samples/cachingfs/caching_fs.go
View file @
ae5da07e
...
@@ -82,7 +82,7 @@ type CachingFS interface {
...
@@ -82,7 +82,7 @@ type CachingFS interface {
//
//
func
NewCachingFS
(
func
NewCachingFS
(
lookupEntryTimeout
time
.
Duration
,
lookupEntryTimeout
time
.
Duration
,
getattrTimeout
time
.
Duration
)
(
fs
CachingFS
,
err
error
)
{
getattrTimeout
time
.
Duration
)
(
CachingFS
,
error
)
{
roundUp
:=
func
(
n
fuseops
.
InodeID
)
fuseops
.
InodeID
{
roundUp
:=
func
(
n
fuseops
.
InodeID
)
fuseops
.
InodeID
{
return
numInodes
*
((
n
+
numInodes
-
1
)
/
numInodes
)
return
numInodes
*
((
n
+
numInodes
-
1
)
/
numInodes
)
}
}
...
@@ -96,8 +96,7 @@ func NewCachingFS(
...
@@ -96,8 +96,7 @@ func NewCachingFS(
cfs
.
mu
=
syncutil
.
NewInvariantMutex
(
cfs
.
checkInvariants
)
cfs
.
mu
=
syncutil
.
NewInvariantMutex
(
cfs
.
checkInvariants
)
fs
=
cfs
return
cfs
,
nil
return
}
}
const
(
const
(
...
@@ -262,14 +261,14 @@ func (fs *cachingFS) SetKeepCache(keep bool) {
...
@@ -262,14 +261,14 @@ func (fs *cachingFS) SetKeepCache(keep bool) {
func
(
fs
*
cachingFS
)
StatFS
(
func
(
fs
*
cachingFS
)
StatFS
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
StatFSOp
)
(
err
error
)
{
op
*
fuseops
.
StatFSOp
)
error
{
return
return
nil
}
}
// LOCKS_EXCLUDED(fs.mu)
// LOCKS_EXCLUDED(fs.mu)
func
(
fs
*
cachingFS
)
LookUpInode
(
func
(
fs
*
cachingFS
)
LookUpInode
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
LookUpInodeOp
)
(
err
error
)
{
op
*
fuseops
.
LookUpInodeOp
)
error
{
fs
.
mu
.
Lock
()
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
defer
fs
.
mu
.
Unlock
()
...
@@ -281,8 +280,7 @@ func (fs *cachingFS) LookUpInode(
...
@@ -281,8 +280,7 @@ func (fs *cachingFS) LookUpInode(
case
"foo"
:
case
"foo"
:
// Parent must be the root.
// Parent must be the root.
if
op
.
Parent
!=
fuseops
.
RootInodeID
{
if
op
.
Parent
!=
fuseops
.
RootInodeID
{
err
=
fuse
.
ENOENT
return
fuse
.
ENOENT
return
}
}
id
=
fs
.
fooID
()
id
=
fs
.
fooID
()
...
@@ -291,8 +289,7 @@ func (fs *cachingFS) LookUpInode(
...
@@ -291,8 +289,7 @@ func (fs *cachingFS) LookUpInode(
case
"dir"
:
case
"dir"
:
// Parent must be the root.
// Parent must be the root.
if
op
.
Parent
!=
fuseops
.
RootInodeID
{
if
op
.
Parent
!=
fuseops
.
RootInodeID
{
err
=
fuse
.
ENOENT
return
fuse
.
ENOENT
return
}
}
id
=
fs
.
dirID
()
id
=
fs
.
dirID
()
...
@@ -301,16 +298,14 @@ func (fs *cachingFS) LookUpInode(
...
@@ -301,16 +298,14 @@ func (fs *cachingFS) LookUpInode(
case
"bar"
:
case
"bar"
:
// Parent must be dir.
// Parent must be dir.
if
op
.
Parent
==
fuseops
.
RootInodeID
||
op
.
Parent
%
numInodes
!=
dirOffset
{
if
op
.
Parent
==
fuseops
.
RootInodeID
||
op
.
Parent
%
numInodes
!=
dirOffset
{
err
=
fuse
.
ENOENT
return
fuse
.
ENOENT
return
}
}
id
=
fs
.
barID
()
id
=
fs
.
barID
()
attrs
=
fs
.
barAttrs
()
attrs
=
fs
.
barAttrs
()
default
:
default
:
err
=
fuse
.
ENOENT
return
fuse
.
ENOENT
return
}
}
// Fill in the response.
// Fill in the response.
...
@@ -318,13 +313,13 @@ func (fs *cachingFS) LookUpInode(
...
@@ -318,13 +313,13 @@ func (fs *cachingFS) LookUpInode(
op
.
Entry
.
Attributes
=
attrs
op
.
Entry
.
Attributes
=
attrs
op
.
Entry
.
EntryExpiration
=
time
.
Now
()
.
Add
(
fs
.
lookupEntryTimeout
)
op
.
Entry
.
EntryExpiration
=
time
.
Now
()
.
Add
(
fs
.
lookupEntryTimeout
)
return
return
nil
}
}
// LOCKS_EXCLUDED(fs.mu)
// LOCKS_EXCLUDED(fs.mu)
func
(
fs
*
cachingFS
)
GetInodeAttributes
(
func
(
fs
*
cachingFS
)
GetInodeAttributes
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
GetInodeAttributesOp
)
(
err
error
)
{
op
*
fuseops
.
GetInodeAttributesOp
)
error
{
fs
.
mu
.
Lock
()
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
defer
fs
.
mu
.
Unlock
()
...
@@ -349,29 +344,30 @@ func (fs *cachingFS) GetInodeAttributes(
...
@@ -349,29 +344,30 @@ func (fs *cachingFS) GetInodeAttributes(
op
.
Attributes
=
attrs
op
.
Attributes
=
attrs
op
.
AttributesExpiration
=
time
.
Now
()
.
Add
(
fs
.
getattrTimeout
)
op
.
AttributesExpiration
=
time
.
Now
()
.
Add
(
fs
.
getattrTimeout
)
return
return
nil
}
}
func
(
fs
*
cachingFS
)
OpenDir
(
func
(
fs
*
cachingFS
)
OpenDir
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
OpenDirOp
)
(
err
error
)
{
op
*
fuseops
.
OpenDirOp
)
error
{
return
return
nil
}
}
func
(
fs
*
cachingFS
)
OpenFile
(
func
(
fs
*
cachingFS
)
OpenFile
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
OpenFileOp
)
(
err
error
)
{
op
*
fuseops
.
OpenFileOp
)
error
{
fs
.
mu
.
Lock
()
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
defer
fs
.
mu
.
Unlock
()
op
.
KeepPageCache
=
fs
.
keepPageCache
op
.
KeepPageCache
=
fs
.
keepPageCache
return
return
nil
}
}
func
(
fs
*
cachingFS
)
ReadFile
(
func
(
fs
*
cachingFS
)
ReadFile
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
ReadFileOp
)
(
err
error
)
{
op
*
fuseops
.
ReadFileOp
)
error
{
var
err
error
op
.
BytesRead
,
err
=
io
.
ReadFull
(
rand
.
Reader
,
op
.
Dst
)
op
.
BytesRead
,
err
=
io
.
ReadFull
(
rand
.
Reader
,
op
.
Dst
)
return
return
err
}
}
samples/cachingfs/caching_fs_test.go
View file @
ae5da07e
...
@@ -83,7 +83,7 @@ func (t *cachingFSTest) statAll() (foo, dir, bar os.FileInfo) {
...
@@ -83,7 +83,7 @@ func (t *cachingFSTest) statAll() (foo, dir, bar os.FileInfo) {
bar
,
err
=
os
.
Stat
(
path
.
Join
(
t
.
Dir
,
"dir/bar"
))
bar
,
err
=
os
.
Stat
(
path
.
Join
(
t
.
Dir
,
"dir/bar"
))
AssertEq
(
nil
,
err
)
AssertEq
(
nil
,
err
)
return
return
foo
,
dir
,
bar
}
}
func
(
t
*
cachingFSTest
)
openFiles
()
(
foo
,
dir
,
bar
*
os
.
File
)
{
func
(
t
*
cachingFSTest
)
openFiles
()
(
foo
,
dir
,
bar
*
os
.
File
)
{
...
@@ -98,7 +98,7 @@ func (t *cachingFSTest) openFiles() (foo, dir, bar *os.File) {
...
@@ -98,7 +98,7 @@ func (t *cachingFSTest) openFiles() (foo, dir, bar *os.File) {
bar
,
err
=
os
.
Open
(
path
.
Join
(
t
.
Dir
,
"dir/bar"
))
bar
,
err
=
os
.
Open
(
path
.
Join
(
t
.
Dir
,
"dir/bar"
))
AssertEq
(
nil
,
err
)
AssertEq
(
nil
,
err
)
return
return
foo
,
dir
,
bar
}
}
func
(
t
*
cachingFSTest
)
statFiles
(
func
(
t
*
cachingFSTest
)
statFiles
(
...
@@ -114,7 +114,7 @@ func (t *cachingFSTest) statFiles(
...
@@ -114,7 +114,7 @@ func (t *cachingFSTest) statFiles(
bar
,
err
=
h
.
Stat
()
bar
,
err
=
h
.
Stat
()
AssertEq
(
nil
,
err
)
AssertEq
(
nil
,
err
)
return
return
foo
,
dir
,
bar
}
}
func
getInodeID
(
fi
os
.
FileInfo
)
uint64
{
func
getInodeID
(
fi
os
.
FileInfo
)
uint64
{
...
...
samples/dynamicfs/dynamic_fs.go
View file @
ae5da07e
...
@@ -33,15 +33,14 @@ import (
...
@@ -33,15 +33,14 @@ import (
// This implementation depends on direct IO in fuse. Without it, all read
// This implementation depends on direct IO in fuse. Without it, all read
// operations are suppressed because the kernel detects that they read beyond
// operations are suppressed because the kernel detects that they read beyond
// the end of the files.
// the end of the files.
func
NewDynamicFS
(
clock
timeutil
.
Clock
)
(
server
fuse
.
Server
,
err
error
)
{
func
NewDynamicFS
(
clock
timeutil
.
Clock
)
(
fuse
.
Server
,
error
)
{
createTime
:=
clock
.
Now
()
createTime
:=
clock
.
Now
()
fs
:=
&
dynamicFS
{
fs
:=
&
dynamicFS
{
clock
:
clock
,
clock
:
clock
,
createTime
:
createTime
,
createTime
:
createTime
,
fileHandles
:
make
(
map
[
fuseops
.
HandleID
]
string
),
fileHandles
:
make
(
map
[
fuseops
.
HandleID
]
string
),
}
}
server
=
fuseutil
.
NewFileSystemServer
(
fs
)
return
fuseutil
.
NewFileSystemServer
(
fs
),
nil
return
}
}
type
dynamicFS
struct
{
type
dynamicFS
struct
{
...
@@ -114,16 +113,14 @@ var gInodeInfo = map[fuseops.InodeID]inodeInfo{
...
@@ -114,16 +113,14 @@ var gInodeInfo = map[fuseops.InodeID]inodeInfo{
func
findChildInode
(
func
findChildInode
(
name
string
,
name
string
,
children
[]
fuseutil
.
Dirent
)
(
inode
fuseops
.
InodeID
,
err
error
)
{
children
[]
fuseutil
.
Dirent
)
(
fuseops
.
InodeID
,
error
)
{
for
_
,
e
:=
range
children
{
for
_
,
e
:=
range
children
{
if
e
.
Name
==
name
{
if
e
.
Name
==
name
{
inode
=
e
.
Inode
return
e
.
Inode
,
nil
return
}
}
}
}
err
=
fuse
.
ENOENT
return
0
,
fuse
.
ENOENT
return
}
}
func
(
fs
*
dynamicFS
)
findUnusedHandle
()
fuseops
.
HandleID
{
func
(
fs
*
dynamicFS
)
findUnusedHandle
()
fuseops
.
HandleID
{
...
@@ -138,69 +135,64 @@ func (fs *dynamicFS) findUnusedHandle() fuseops.HandleID {
...
@@ -138,69 +135,64 @@ func (fs *dynamicFS) findUnusedHandle() fuseops.HandleID {
func
(
fs
*
dynamicFS
)
GetInodeAttributes
(
func
(
fs
*
dynamicFS
)
GetInodeAttributes
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
GetInodeAttributesOp
)
(
err
error
)
{
op
*
fuseops
.
GetInodeAttributesOp
)
error
{
// Find the info for this inode.
// Find the info for this inode.
info
,
ok
:=
gInodeInfo
[
op
.
Inode
]
info
,
ok
:=
gInodeInfo
[
op
.
Inode
]
if
!
ok
{
if
!
ok
{
err
=
fuse
.
ENOENT
return
fuse
.
ENOENT
return
}
}
// Copy over its attributes.
// Copy over its attributes.
op
.
Attributes
=
info
.
attributes
op
.
Attributes
=
info
.
attributes
return
return
nil
}
}
func
(
fs
*
dynamicFS
)
LookUpInode
(
func
(
fs
*
dynamicFS
)
LookUpInode
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
LookUpInodeOp
)
(
err
error
)
{
op
*
fuseops
.
LookUpInodeOp
)
error
{
// Find the info for the parent.
// Find the info for the parent.
parentInfo
,
ok
:=
gInodeInfo
[
op
.
Parent
]
parentInfo
,
ok
:=
gInodeInfo
[
op
.
Parent
]
if
!
ok
{
if
!
ok
{
err
=
fuse
.
ENOENT
return
fuse
.
ENOENT
return
}
}
// Find the child within the parent.
// Find the child within the parent.
childInode
,
err
:=
findChildInode
(
op
.
Name
,
parentInfo
.
children
)
childInode
,
err
:=
findChildInode
(
op
.
Name
,
parentInfo
.
children
)
if
err
!=
nil
{
if
err
!=
nil
{
return
return
err
}
}
// Copy over information.
// Copy over information.
op
.
Entry
.
Child
=
childInode
op
.
Entry
.
Child
=
childInode
op
.
Entry
.
Attributes
=
gInodeInfo
[
childInode
]
.
attributes
op
.
Entry
.
Attributes
=
gInodeInfo
[
childInode
]
.
attributes
return
return
nil
}
}
func
(
fs
*
dynamicFS
)
OpenDir
(
func
(
fs
*
dynamicFS
)
OpenDir
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
OpenDirOp
)
(
err
error
)
{
op
*
fuseops
.
OpenDirOp
)
error
{
// Allow opening directory.
// Allow opening directory.
return
return
nil
}
}
func
(
fs
*
dynamicFS
)
ReadDir
(
func
(
fs
*
dynamicFS
)
ReadDir
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
ReadDirOp
)
(
err
error
)
{
op
*
fuseops
.
ReadDirOp
)
error
{
// Find the info for this inode.
// Find the info for this inode.
info
,
ok
:=
gInodeInfo
[
op
.
Inode
]
info
,
ok
:=
gInodeInfo
[
op
.
Inode
]
if
!
ok
{
if
!
ok
{
err
=
fuse
.
ENOENT
return
fuse
.
ENOENT
return
}
}
if
!
info
.
dir
{
if
!
info
.
dir
{
err
=
fuse
.
EIO
return
fuse
.
EIO
return
}
}
entries
:=
info
.
children
entries
:=
info
.
children
// Grab the range of interest.
// Grab the range of interest.
if
op
.
Offset
>
fuseops
.
DirOffset
(
len
(
entries
))
{
if
op
.
Offset
>
fuseops
.
DirOffset
(
len
(
entries
))
{
err
=
fuse
.
EIO
return
fuse
.
EIO
return
}
}
entries
=
entries
[
op
.
Offset
:
]
entries
=
entries
[
op
.
Offset
:
]
...
@@ -215,12 +207,12 @@ func (fs *dynamicFS) ReadDir(
...
@@ -215,12 +207,12 @@ func (fs *dynamicFS) ReadDir(
op
.
BytesRead
+=
n
op
.
BytesRead
+=
n
}
}
return
return
nil
}
}
func
(
fs
*
dynamicFS
)
OpenFile
(
func
(
fs
*
dynamicFS
)
OpenFile
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
OpenFileOp
)
(
err
error
)
{
op
*
fuseops
.
OpenFileOp
)
error
{
fs
.
mu
.
Lock
()
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
defer
fs
.
mu
.
Unlock
()
var
contents
string
var
contents
string
...
@@ -233,51 +225,49 @@ func (fs *dynamicFS) OpenFile(
...
@@ -233,51 +225,49 @@ func (fs *dynamicFS) OpenFile(
case
weekdayInode
:
case
weekdayInode
:
contents
=
fmt
.
Sprintf
(
"Today is %s."
,
fs
.
clock
.
Now
()
.
Weekday
())
contents
=
fmt
.
Sprintf
(
"Today is %s."
,
fs
.
clock
.
Now
()
.
Weekday
())
default
:
default
:
err
=
fuse
.
EINVAL
return
fuse
.
EINVAL
return
}
}
handle
:=
fs
.
findUnusedHandle
()
handle
:=
fs
.
findUnusedHandle
()
fs
.
fileHandles
[
handle
]
=
contents
fs
.
fileHandles
[
handle
]
=
contents
op
.
UseDirectIO
=
true
op
.
UseDirectIO
=
true
op
.
Handle
=
handle
op
.
Handle
=
handle
return
return
nil
}
}
func
(
fs
*
dynamicFS
)
ReadFile
(
func
(
fs
*
dynamicFS
)
ReadFile
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
ReadFileOp
)
(
err
error
)
{
op
*
fuseops
.
ReadFileOp
)
error
{
fs
.
mu
.
Lock
()
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
defer
fs
.
mu
.
Unlock
()
contents
,
ok
:=
fs
.
fileHandles
[
op
.
Handle
]
contents
,
ok
:=
fs
.
fileHandles
[
op
.
Handle
]
if
!
ok
{
if
!
ok
{
log
.
Printf
(
"ReadFile: no open file handle: %d"
,
op
.
Handle
)
log
.
Printf
(
"ReadFile: no open file handle: %d"
,
op
.
Handle
)
err
=
fuse
.
EIO
return
fuse
.
EIO
return
}
}
reader
:=
strings
.
NewReader
(
contents
)
reader
:=
strings
.
NewReader
(
contents
)
var
err
error
op
.
BytesRead
,
err
=
reader
.
ReadAt
(
op
.
Dst
,
op
.
Offset
)
op
.
BytesRead
,
err
=
reader
.
ReadAt
(
op
.
Dst
,
op
.
Offset
)
if
err
==
io
.
EOF
{
if
err
==
io
.
EOF
{
err
=
nil
return
nil
}
}
return
return
err
}
}
func
(
fs
*
dynamicFS
)
ReleaseFileHandle
(
func
(
fs
*
dynamicFS
)
ReleaseFileHandle
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
ReleaseFileHandleOp
)
(
err
error
)
{
op
*
fuseops
.
ReleaseFileHandleOp
)
error
{
fs
.
mu
.
Lock
()
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
defer
fs
.
mu
.
Unlock
()
_
,
ok
:=
fs
.
fileHandles
[
op
.
Handle
]
_
,
ok
:=
fs
.
fileHandles
[
op
.
Handle
]
if
!
ok
{
if
!
ok
{
log
.
Printf
(
"ReleaseFileHandle: bad handle: %d"
,
op
.
Handle
)
log
.
Printf
(
"ReleaseFileHandle: bad handle: %d"
,
op
.
Handle
)
err
=
fuse
.
EIO
return
fuse
.
EIO
return
}
}
delete
(
fs
.
fileHandles
,
op
.
Handle
)
delete
(
fs
.
fileHandles
,
op
.
Handle
)
return
return
nil
}
}
func
(
fs
*
dynamicFS
)
StatFS
(
ctx
context
.
Context
,
func
(
fs
*
dynamicFS
)
StatFS
(
ctx
context
.
Context
,
op
*
fuseops
.
StatFSOp
)
(
err
error
)
{
op
*
fuseops
.
StatFSOp
)
error
{
return
return
nil
}
}
samples/errorfs/error_fs.go
View file @
ae5da07e
...
@@ -49,12 +49,10 @@ type FS interface {
...
@@ -49,12 +49,10 @@ type FS interface {
SetError
(
t
reflect
.
Type
,
err
syscall
.
Errno
)
SetError
(
t
reflect
.
Type
,
err
syscall
.
Errno
)
}
}
func
New
()
(
fs
FS
,
err
error
)
{
func
New
()
(
FS
,
error
)
{
fs
=
&
errorFS
{
return
&
errorFS
{
errors
:
make
(
map
[
reflect
.
Type
]
syscall
.
Errno
),
errors
:
make
(
map
[
reflect
.
Type
]
syscall
.
Errno
),
}
},
nil
return
}
}
type
errorFS
struct
{
type
errorFS
struct
{
...
@@ -95,9 +93,10 @@ func (fs *errorFS) transformError(op interface{}, err *error) bool {
...
@@ -95,9 +93,10 @@ func (fs *errorFS) transformError(op interface{}, err *error) bool {
// LOCKS_EXCLUDED(fs.mu)
// LOCKS_EXCLUDED(fs.mu)
func
(
fs
*
errorFS
)
GetInodeAttributes
(
func
(
fs
*
errorFS
)
GetInodeAttributes
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
GetInodeAttributesOp
)
(
err
error
)
{
op
*
fuseops
.
GetInodeAttributesOp
)
error
{
var
err
error
if
fs
.
transformError
(
op
,
&
err
)
{
if
fs
.
transformError
(
op
,
&
err
)
{
return
return
err
}
}
// Figure out which inode the request is for.
// Figure out which inode the request is for.
...
@@ -111,100 +110,99 @@ func (fs *errorFS) GetInodeAttributes(
...
@@ -111,100 +110,99 @@ func (fs *errorFS) GetInodeAttributes(
op
.
Attributes
=
fooAttrs
op
.
Attributes
=
fooAttrs
default
:
default
:
err
=
fmt
.
Errorf
(
"Unknown inode: %d"
,
op
.
Inode
)
return
fmt
.
Errorf
(
"Unknown inode: %d"
,
op
.
Inode
)
return
}
}
return
return
nil
}
}
func
(
fs
*
errorFS
)
StatFS
(
func
(
fs
*
errorFS
)
StatFS
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
StatFSOp
)
(
err
error
)
{
op
*
fuseops
.
StatFSOp
)
error
{
return
return
nil
}
}
// LOCKS_EXCLUDED(fs.mu)
// LOCKS_EXCLUDED(fs.mu)
func
(
fs
*
errorFS
)
LookUpInode
(
func
(
fs
*
errorFS
)
LookUpInode
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
LookUpInodeOp
)
(
err
error
)
{
op
*
fuseops
.
LookUpInodeOp
)
error
{
var
err
error
if
fs
.
transformError
(
op
,
&
err
)
{
if
fs
.
transformError
(
op
,
&
err
)
{
return
return
err
}
}
// Is this a known inode?
// Is this a known inode?
if
!
(
op
.
Parent
==
fuseops
.
RootInodeID
&&
op
.
Name
==
"foo"
)
{
if
!
(
op
.
Parent
==
fuseops
.
RootInodeID
&&
op
.
Name
==
"foo"
)
{
err
=
syscall
.
ENOENT
return
syscall
.
ENOENT
return
}
}
op
.
Entry
.
Child
=
fooInodeID
op
.
Entry
.
Child
=
fooInodeID
op
.
Entry
.
Attributes
=
fooAttrs
op
.
Entry
.
Attributes
=
fooAttrs
return
return
nil
}
}
// LOCKS_EXCLUDED(fs.mu)
// LOCKS_EXCLUDED(fs.mu)
func
(
fs
*
errorFS
)
OpenFile
(
func
(
fs
*
errorFS
)
OpenFile
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
OpenFileOp
)
(
err
error
)
{
op
*
fuseops
.
OpenFileOp
)
error
{
var
err
error
if
fs
.
transformError
(
op
,
&
err
)
{
if
fs
.
transformError
(
op
,
&
err
)
{
return
return
err
}
}
if
op
.
Inode
!=
fooInodeID
{
if
op
.
Inode
!=
fooInodeID
{
err
=
fmt
.
Errorf
(
"Unsupported inode ID: %d"
,
op
.
Inode
)
return
fmt
.
Errorf
(
"Unsupported inode ID: %d"
,
op
.
Inode
)
return
}
}
return
return
nil
}
}
// LOCKS_EXCLUDED(fs.mu)
// LOCKS_EXCLUDED(fs.mu)
func
(
fs
*
errorFS
)
ReadFile
(
func
(
fs
*
errorFS
)
ReadFile
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
ReadFileOp
)
(
err
error
)
{
op
*
fuseops
.
ReadFileOp
)
error
{
var
err
error
if
fs
.
transformError
(
op
,
&
err
)
{
if
fs
.
transformError
(
op
,
&
err
)
{
return
return
err
}
}
if
op
.
Inode
!=
fooInodeID
||
op
.
Offset
!=
0
{
if
op
.
Inode
!=
fooInodeID
||
op
.
Offset
!=
0
{
err
=
fmt
.
Errorf
(
"Unexpected request: %#v"
,
op
)
return
fmt
.
Errorf
(
"Unexpected request: %#v"
,
op
)
return
}
}
op
.
BytesRead
=
copy
(
op
.
Dst
,
FooContents
)
op
.
BytesRead
=
copy
(
op
.
Dst
,
FooContents
)
return
return
nil
}
}
// LOCKS_EXCLUDED(fs.mu)
// LOCKS_EXCLUDED(fs.mu)
func
(
fs
*
errorFS
)
OpenDir
(
func
(
fs
*
errorFS
)
OpenDir
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
OpenDirOp
)
(
err
error
)
{
op
*
fuseops
.
OpenDirOp
)
error
{
var
err
error
if
fs
.
transformError
(
op
,
&
err
)
{
if
fs
.
transformError
(
op
,
&
err
)
{
return
return
err
}
}
if
op
.
Inode
!=
fuseops
.
RootInodeID
{
if
op
.
Inode
!=
fuseops
.
RootInodeID
{
err
=
fmt
.
Errorf
(
"Unsupported inode ID: %d"
,
op
.
Inode
)
return
fmt
.
Errorf
(
"Unsupported inode ID: %d"
,
op
.
Inode
)
return
}
}
return
return
nil
}
}
// LOCKS_EXCLUDED(fs.mu)
// LOCKS_EXCLUDED(fs.mu)
func
(
fs
*
errorFS
)
ReadDir
(
func
(
fs
*
errorFS
)
ReadDir
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
ReadDirOp
)
(
err
error
)
{
op
*
fuseops
.
ReadDirOp
)
error
{
var
err
error
if
fs
.
transformError
(
op
,
&
err
)
{
if
fs
.
transformError
(
op
,
&
err
)
{
return
return
err
}
}
if
op
.
Inode
!=
fuseops
.
RootInodeID
||
op
.
Offset
!=
0
{
if
op
.
Inode
!=
fuseops
.
RootInodeID
||
op
.
Offset
!=
0
{
err
=
fmt
.
Errorf
(
"Unexpected request: %#v"
,
op
)
return
fmt
.
Errorf
(
"Unexpected request: %#v"
,
op
)
return
}
}
op
.
BytesRead
=
fuseutil
.
WriteDirent
(
op
.
BytesRead
=
fuseutil
.
WriteDirent
(
...
@@ -216,5 +214,5 @@ func (fs *errorFS) ReadDir(
...
@@ -216,5 +214,5 @@ func (fs *errorFS) ReadDir(
Type
:
fuseutil
.
DT_File
,
Type
:
fuseutil
.
DT_File
,
})
})
return
return
nil
}
}
samples/flushfs/flush_fs.go
View file @
ae5da07e
...
@@ -35,14 +35,13 @@ import (
...
@@ -35,14 +35,13 @@ import (
// The directory cannot be modified.
// The directory cannot be modified.
func
NewFileSystem
(
func
NewFileSystem
(
reportFlush
func
(
string
)
error
,
reportFlush
func
(
string
)
error
,
reportFsync
func
(
string
)
error
)
(
server
fuse
.
Server
,
err
error
)
{
reportFsync
func
(
string
)
error
)
(
fuse
.
Server
,
error
)
{
fs
:=
&
flushFS
{
fs
:=
&
flushFS
{
reportFlush
:
reportFlush
,
reportFlush
:
reportFlush
,
reportFsync
:
reportFsync
,
reportFsync
:
reportFsync
,
}
}
server
=
fuseutil
.
NewFileSystemServer
(
fs
)
return
fuseutil
.
NewFileSystemServer
(
fs
),
nil
return
}
}
const
(
const
(
...
@@ -90,25 +89,19 @@ func (fs *flushFS) barAttributes() fuseops.InodeAttributes {
...
@@ -90,25 +89,19 @@ func (fs *flushFS) barAttributes() fuseops.InodeAttributes {
}
}
// LOCKS_REQUIRED(fs.mu)
// LOCKS_REQUIRED(fs.mu)
func
(
fs
*
flushFS
)
getAttributes
(
id
fuseops
.
InodeID
)
(
func
(
fs
*
flushFS
)
getAttributes
(
id
fuseops
.
InodeID
)
(
fuseops
.
InodeAttributes
,
error
)
{
attrs
fuseops
.
InodeAttributes
,
err
error
)
{
switch
id
{
switch
id
{
case
fuseops
.
RootInodeID
:
case
fuseops
.
RootInodeID
:
attrs
=
fs
.
rootAttributes
()
return
fs
.
rootAttributes
(),
nil
return
case
fooID
:
case
fooID
:
attrs
=
fs
.
fooAttributes
()
return
fs
.
fooAttributes
(),
nil
return
case
barID
:
case
barID
:
attrs
=
fs
.
barAttributes
()
return
fs
.
barAttributes
(),
nil
return
default
:
default
:
err
=
fuse
.
ENOENT
return
fuseops
.
InodeAttributes
{},
fuse
.
ENOENT
return
}
}
}
}
...
@@ -118,20 +111,19 @@ func (fs *flushFS) getAttributes(id fuseops.InodeID) (
...
@@ -118,20 +111,19 @@ func (fs *flushFS) getAttributes(id fuseops.InodeID) (
func
(
fs
*
flushFS
)
StatFS
(
func
(
fs
*
flushFS
)
StatFS
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
StatFSOp
)
(
err
error
)
{
op
*
fuseops
.
StatFSOp
)
error
{
return
return
nil
}
}
func
(
fs
*
flushFS
)
LookUpInode
(
func
(
fs
*
flushFS
)
LookUpInode
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
LookUpInodeOp
)
(
err
error
)
{
op
*
fuseops
.
LookUpInodeOp
)
error
{
fs
.
mu
.
Lock
()
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
defer
fs
.
mu
.
Unlock
()
// Sanity check.
// Sanity check.
if
op
.
Parent
!=
fuseops
.
RootInodeID
{
if
op
.
Parent
!=
fuseops
.
RootInodeID
{
err
=
fuse
.
ENOENT
return
fuse
.
ENOENT
return
}
}
// Set up the entry.
// Set up the entry.
...
@@ -149,70 +141,69 @@ func (fs *flushFS) LookUpInode(
...
@@ -149,70 +141,69 @@ func (fs *flushFS) LookUpInode(
}
}
default
:
default
:
err
=
fuse
.
ENOENT
return
fuse
.
ENOENT
return
}
}
return
return
nil
}
}
func
(
fs
*
flushFS
)
GetInodeAttributes
(
func
(
fs
*
flushFS
)
GetInodeAttributes
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
GetInodeAttributesOp
)
(
err
error
)
{
op
*
fuseops
.
GetInodeAttributesOp
)
error
{
fs
.
mu
.
Lock
()
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
defer
fs
.
mu
.
Unlock
()
var
err
error
op
.
Attributes
,
err
=
fs
.
getAttributes
(
op
.
Inode
)
op
.
Attributes
,
err
=
fs
.
getAttributes
(
op
.
Inode
)
return
return
err
}
}
func
(
fs
*
flushFS
)
SetInodeAttributes
(
func
(
fs
*
flushFS
)
SetInodeAttributes
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
SetInodeAttributesOp
)
(
err
error
)
{
op
*
fuseops
.
SetInodeAttributesOp
)
error
{
fs
.
mu
.
Lock
()
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
defer
fs
.
mu
.
Unlock
()
// Ignore any changes and simply return existing attributes.
// Ignore any changes and simply return existing attributes.
var
err
error
op
.
Attributes
,
err
=
fs
.
getAttributes
(
op
.
Inode
)
op
.
Attributes
,
err
=
fs
.
getAttributes
(
op
.
Inode
)
return
err
return
}
}
func
(
fs
*
flushFS
)
OpenFile
(
func
(
fs
*
flushFS
)
OpenFile
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
OpenFileOp
)
(
err
error
)
{
op
*
fuseops
.
OpenFileOp
)
error
{
fs
.
mu
.
Lock
()
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
defer
fs
.
mu
.
Unlock
()
// Sanity check.
// Sanity check.
if
op
.
Inode
!=
fooID
{
if
op
.
Inode
!=
fooID
{
err
=
fuse
.
ENOSYS
return
fuse
.
ENOSYS
return
}
}
return
return
nil
}
}
func
(
fs
*
flushFS
)
ReadFile
(
func
(
fs
*
flushFS
)
ReadFile
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
ReadFileOp
)
(
err
error
)
{
op
*
fuseops
.
ReadFileOp
)
error
{
fs
.
mu
.
Lock
()
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
defer
fs
.
mu
.
Unlock
()
// Ensure the offset is in range.
// Ensure the offset is in range.
if
op
.
Offset
>
int64
(
len
(
fs
.
fooContents
))
{
if
op
.
Offset
>
int64
(
len
(
fs
.
fooContents
))
{
return
return
nil
}
}
// Read what we can.
// Read what we can.
op
.
BytesRead
=
copy
(
op
.
Dst
,
fs
.
fooContents
[
op
.
Offset
:
])
op
.
BytesRead
=
copy
(
op
.
Dst
,
fs
.
fooContents
[
op
.
Offset
:
])
return
return
nil
}
}
func
(
fs
*
flushFS
)
WriteFile
(
func
(
fs
*
flushFS
)
WriteFile
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
WriteFileOp
)
(
err
error
)
{
op
*
fuseops
.
WriteFileOp
)
error
{
fs
.
mu
.
Lock
()
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
defer
fs
.
mu
.
Unlock
()
...
@@ -231,32 +222,30 @@ func (fs *flushFS) WriteFile(
...
@@ -231,32 +222,30 @@ func (fs *flushFS) WriteFile(
panic
(
fmt
.
Sprintf
(
"Unexpected short copy: %v"
,
n
))
panic
(
fmt
.
Sprintf
(
"Unexpected short copy: %v"
,
n
))
}
}
return
return
nil
}
}
func
(
fs
*
flushFS
)
SyncFile
(
func
(
fs
*
flushFS
)
SyncFile
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
SyncFileOp
)
(
err
error
)
{
op
*
fuseops
.
SyncFileOp
)
error
{
fs
.
mu
.
Lock
()
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
defer
fs
.
mu
.
Unlock
()
err
=
fs
.
reportFsync
(
string
(
fs
.
fooContents
))
return
fs
.
reportFsync
(
string
(
fs
.
fooContents
))
return
}
}
func
(
fs
*
flushFS
)
FlushFile
(
func
(
fs
*
flushFS
)
FlushFile
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
FlushFileOp
)
(
err
error
)
{
op
*
fuseops
.
FlushFileOp
)
error
{
fs
.
mu
.
Lock
()
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
defer
fs
.
mu
.
Unlock
()
err
=
fs
.
reportFlush
(
string
(
fs
.
fooContents
))
return
fs
.
reportFlush
(
string
(
fs
.
fooContents
))
return
}
}
func
(
fs
*
flushFS
)
OpenDir
(
func
(
fs
*
flushFS
)
OpenDir
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
OpenDirOp
)
(
err
error
)
{
op
*
fuseops
.
OpenDirOp
)
error
{
fs
.
mu
.
Lock
()
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
defer
fs
.
mu
.
Unlock
()
...
@@ -266,16 +255,15 @@ func (fs *flushFS) OpenDir(
...
@@ -266,16 +255,15 @@ func (fs *flushFS) OpenDir(
case
barID
:
case
barID
:
default
:
default
:
err
=
fuse
.
ENOENT
return
fuse
.
ENOENT
return
}
}
return
return
nil
}
}
func
(
fs
*
flushFS
)
ReadDir
(
func
(
fs
*
flushFS
)
ReadDir
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
ReadDirOp
)
(
err
error
)
{
op
*
fuseops
.
ReadDirOp
)
error
{
fs
.
mu
.
Lock
()
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
defer
fs
.
mu
.
Unlock
()
...
@@ -303,21 +291,19 @@ func (fs *flushFS) ReadDir(
...
@@ -303,21 +291,19 @@ func (fs *flushFS) ReadDir(
case
barID
:
case
barID
:
default
:
default
:
err
=
fmt
.
Errorf
(
"Unexpected inode: %v"
,
op
.
Inode
)
return
fmt
.
Errorf
(
"Unexpected inode: %v"
,
op
.
Inode
)
return
}
}
// If the offset is for the end of the listing, we're done. Otherwise we
// If the offset is for the end of the listing, we're done. Otherwise we
// expect it to be for the start.
// expect it to be for the start.
switch
op
.
Offset
{
switch
op
.
Offset
{
case
fuseops
.
DirOffset
(
len
(
dirents
))
:
case
fuseops
.
DirOffset
(
len
(
dirents
))
:
return
return
nil
case
0
:
case
0
:
default
:
default
:
err
=
fmt
.
Errorf
(
"Unexpected offset: %v"
,
op
.
Offset
)
return
fmt
.
Errorf
(
"Unexpected offset: %v"
,
op
.
Offset
)
return
}
}
// Fill in the listing.
// Fill in the listing.
...
@@ -326,12 +312,11 @@ func (fs *flushFS) ReadDir(
...
@@ -326,12 +312,11 @@ func (fs *flushFS) ReadDir(
// We don't support doing this in anything more than one shot.
// We don't support doing this in anything more than one shot.
if
n
==
0
{
if
n
==
0
{
err
=
fmt
.
Errorf
(
"Couldn't fit listing in %v bytes"
,
len
(
op
.
Dst
))
return
fmt
.
Errorf
(
"Couldn't fit listing in %v bytes"
,
len
(
op
.
Dst
))
return
}
}
op
.
BytesRead
+=
n
op
.
BytesRead
+=
n
}
}
return
return
nil
}
}
samples/flushfs/flush_fs_test.go
View file @
ae5da07e
...
@@ -121,30 +121,24 @@ var isDarwin = runtime.GOOS == "darwin"
...
@@ -121,30 +121,24 @@ var isDarwin = runtime.GOOS == "darwin"
func
readReports
(
f
*
os
.
File
)
(
reports
[]
string
,
err
error
)
{
func
readReports
(
f
*
os
.
File
)
(
reports
[]
string
,
err
error
)
{
// Seek the file to the start.
// Seek the file to the start.
_
,
err
=
f
.
Seek
(
0
,
0
)
if
_
,
err
:=
f
.
Seek
(
0
,
0
);
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"Seek: %v"
,
err
)
err
=
fmt
.
Errorf
(
"Seek: %v"
,
err
)
return
}
}
// We expect reports to end in a newline (including the final one).
// We expect reports to end in a newline (including the final one).
reader
:=
bufio
.
NewReader
(
f
)
reader
:=
bufio
.
NewReader
(
f
)
for
{
for
{
var
record
[]
byte
record
,
err
:=
reader
.
ReadBytes
(
'\n'
)
record
,
err
=
reader
.
ReadBytes
(
'\n'
)
if
err
==
io
.
EOF
{
if
err
==
io
.
EOF
{
if
len
(
record
)
!=
0
{
if
len
(
record
)
!=
0
{
err
=
fmt
.
Errorf
(
"Unexpected record:
\n
%s"
,
hex
.
Dump
(
record
))
return
nil
,
fmt
.
Errorf
(
"Unexpected record:
\n
%s"
,
hex
.
Dump
(
record
))
return
}
}
err
=
nil
return
reports
,
nil
return
}
}
if
err
!=
nil
{
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"ReadBytes: %v"
,
err
)
return
nil
,
fmt
.
Errorf
(
"ReadBytes: %v"
,
err
)
return
}
}
// Strip the newline.
// Strip the newline.
...
@@ -153,41 +147,39 @@ func readReports(f *os.File) (reports []string, err error) {
...
@@ -153,41 +147,39 @@ func readReports(f *os.File) (reports []string, err error) {
}
}
// Return a copy of the current contents of t.flushes.
// Return a copy of the current contents of t.flushes.
func
(
t
*
flushFSTest
)
getFlushes
()
(
p
[]
string
)
{
func
(
t
*
flushFSTest
)
getFlushes
()
[]
string
{
var
err
error
p
,
err
:=
readReports
(
t
.
flushes
)
if
p
,
err
=
readReports
(
t
.
flushes
);
err
!=
nil
{
if
err
!=
nil
{
panic
(
err
)
panic
(
err
)
}
}
return
p
return
}
}
// Return a copy of the current contents of t.fsyncs.
// Return a copy of the current contents of t.fsyncs.
func
(
t
*
flushFSTest
)
getFsyncs
()
(
p
[]
string
)
{
func
(
t
*
flushFSTest
)
getFsyncs
()
[]
string
{
var
err
error
p
,
err
:=
readReports
(
t
.
fsyncs
)
if
p
,
err
=
readReports
(
t
.
fsyncs
);
err
!=
nil
{
if
err
!=
nil
{
panic
(
err
)
panic
(
err
)
}
}
return
p
return
}
}
// Like syscall.Dup2, but correctly annotates the syscall as blocking. See here
// Like syscall.Dup2, but correctly annotates the syscall as blocking. See here
// for more info: https://github.com/golang/go/issues/10202
// for more info: https://github.com/golang/go/issues/10202
func
dup2
(
oldfd
int
,
newfd
int
)
(
err
error
)
{
func
dup2
(
oldfd
int
,
newfd
int
)
error
{
_
,
_
,
e1
:=
syscall
.
Syscall
(
_
,
_
,
e1
:=
syscall
.
Syscall
(
syscall
.
SYS_DUP2
,
uintptr
(
oldfd
),
uintptr
(
newfd
),
0
)
syscall
.
SYS_DUP2
,
uintptr
(
oldfd
),
uintptr
(
newfd
),
0
)
if
e1
!=
0
{
if
e1
!=
0
{
err
=
e1
return
e1
}
}
return
return
nil
}
}
// Call msync(2) with the MS_SYNC flag on a slice previously returned by
// Call msync(2) with the MS_SYNC flag on a slice previously returned by
// mmap(2).
// mmap(2).
func
msync
(
p
[]
byte
)
(
err
error
)
{
func
msync
(
p
[]
byte
)
error
{
_
,
_
,
errno
:=
unix
.
Syscall
(
_
,
_
,
errno
:=
unix
.
Syscall
(
unix
.
SYS_MSYNC
,
unix
.
SYS_MSYNC
,
uintptr
(
unsafe
.
Pointer
(
&
p
[
0
])),
uintptr
(
unsafe
.
Pointer
(
&
p
[
0
])),
...
@@ -195,11 +187,10 @@ func msync(p []byte) (err error) {
...
@@ -195,11 +187,10 @@ func msync(p []byte) (err error) {
unix
.
MS_SYNC
)
unix
.
MS_SYNC
)
if
errno
!=
0
{
if
errno
!=
0
{
err
=
errno
return
errno
return
}
}
return
return
nil
}
}
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
...
...
samples/forgetfs/forget_fs.go
View file @
ae5da07e
...
@@ -38,7 +38,7 @@ import (
...
@@ -38,7 +38,7 @@ import (
// after we expect it to be dead. Its Check method may be used to check that
// after we expect it to be dead. Its Check method may be used to check that
// there are no inodes with unexpected reference counts remaining, after
// there are no inodes with unexpected reference counts remaining, after
// unmounting.
// unmounting.
func
NewFileSystem
()
(
fs
*
ForgetFS
)
{
func
NewFileSystem
()
*
ForgetFS
{
// Set up the actual file system.
// Set up the actual file system.
impl
:=
&
fsImpl
{
impl
:=
&
fsImpl
{
inodes
:
map
[
fuseops
.
InodeID
]
*
inode
{
inodes
:
map
[
fuseops
.
InodeID
]
*
inode
{
...
@@ -78,12 +78,10 @@ func NewFileSystem() (fs *ForgetFS) {
...
@@ -78,12 +78,10 @@ func NewFileSystem() (fs *ForgetFS) {
impl
.
mu
=
syncutil
.
NewInvariantMutex
(
impl
.
checkInvariants
)
impl
.
mu
=
syncutil
.
NewInvariantMutex
(
impl
.
checkInvariants
)
// Set up a wrapper that exposes only certain methods.
// Set up a wrapper that exposes only certain methods.
fs
=
&
ForgetFS
{
return
&
ForgetFS
{
impl
:
impl
,
impl
:
impl
,
server
:
fuseutil
.
NewFileSystemServer
(
impl
),
server
:
fuseutil
.
NewFileSystemServer
(
impl
),
}
}
return
}
}
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
...
@@ -206,8 +204,8 @@ func (fs *fsImpl) Check() {
...
@@ -206,8 +204,8 @@ func (fs *fsImpl) Check() {
// Look up the inode and verify it hasn't been forgotten.
// Look up the inode and verify it hasn't been forgotten.
//
//
// LOCKS_REQUIRED(fs.mu)
// LOCKS_REQUIRED(fs.mu)
func
(
fs
*
fsImpl
)
findInodeByID
(
id
fuseops
.
InodeID
)
(
in
*
inode
)
{
func
(
fs
*
fsImpl
)
findInodeByID
(
id
fuseops
.
InodeID
)
*
inode
{
in
=
fs
.
inodes
[
id
]
in
:
=
fs
.
inodes
[
id
]
if
in
==
nil
{
if
in
==
nil
{
panic
(
fmt
.
Sprintf
(
"Unknown inode: %v"
,
id
))
panic
(
fmt
.
Sprintf
(
"Unknown inode: %v"
,
id
))
}
}
...
@@ -216,7 +214,7 @@ func (fs *fsImpl) findInodeByID(id fuseops.InodeID) (in *inode) {
...
@@ -216,7 +214,7 @@ func (fs *fsImpl) findInodeByID(id fuseops.InodeID) (in *inode) {
panic
(
fmt
.
Sprintf
(
"Forgotten inode: %v"
,
id
))
panic
(
fmt
.
Sprintf
(
"Forgotten inode: %v"
,
id
))
}
}
return
return
in
}
}
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
...
@@ -225,13 +223,13 @@ func (fs *fsImpl) findInodeByID(id fuseops.InodeID) (in *inode) {
...
@@ -225,13 +223,13 @@ func (fs *fsImpl) findInodeByID(id fuseops.InodeID) (in *inode) {
func
(
fs
*
fsImpl
)
StatFS
(
func
(
fs
*
fsImpl
)
StatFS
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
StatFSOp
)
(
err
error
)
{
op
*
fuseops
.
StatFSOp
)
error
{
return
return
nil
}
}
func
(
fs
*
fsImpl
)
LookUpInode
(
func
(
fs
*
fsImpl
)
LookUpInode
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
LookUpInodeOp
)
(
err
error
)
{
op
*
fuseops
.
LookUpInodeOp
)
error
{
fs
.
mu
.
Lock
()
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
defer
fs
.
mu
.
Unlock
()
...
@@ -248,8 +246,7 @@ func (fs *fsImpl) LookUpInode(
...
@@ -248,8 +246,7 @@ func (fs *fsImpl) LookUpInode(
childID
=
cannedID_Bar
childID
=
cannedID_Bar
default
:
default
:
err
=
fuse
.
ENOENT
return
fuse
.
ENOENT
return
}
}
// Look up the child.
// Look up the child.
...
@@ -262,12 +259,12 @@ func (fs *fsImpl) LookUpInode(
...
@@ -262,12 +259,12 @@ func (fs *fsImpl) LookUpInode(
Attributes
:
child
.
attributes
,
Attributes
:
child
.
attributes
,
}
}
return
return
nil
}
}
func
(
fs
*
fsImpl
)
GetInodeAttributes
(
func
(
fs
*
fsImpl
)
GetInodeAttributes
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
GetInodeAttributesOp
)
(
err
error
)
{
op
*
fuseops
.
GetInodeAttributesOp
)
error
{
fs
.
mu
.
Lock
()
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
defer
fs
.
mu
.
Unlock
()
...
@@ -277,12 +274,12 @@ func (fs *fsImpl) GetInodeAttributes(
...
@@ -277,12 +274,12 @@ func (fs *fsImpl) GetInodeAttributes(
// Return appropriate attributes.
// Return appropriate attributes.
op
.
Attributes
=
in
.
attributes
op
.
Attributes
=
in
.
attributes
return
return
nil
}
}
func
(
fs
*
fsImpl
)
ForgetInode
(
func
(
fs
*
fsImpl
)
ForgetInode
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
ForgetInodeOp
)
(
err
error
)
{
op
*
fuseops
.
ForgetInodeOp
)
error
{
fs
.
mu
.
Lock
()
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
defer
fs
.
mu
.
Unlock
()
...
@@ -290,12 +287,12 @@ func (fs *fsImpl) ForgetInode(
...
@@ -290,12 +287,12 @@ func (fs *fsImpl) ForgetInode(
in
:=
fs
.
findInodeByID
(
op
.
Inode
)
in
:=
fs
.
findInodeByID
(
op
.
Inode
)
in
.
DecrementLookupCount
(
op
.
N
)
in
.
DecrementLookupCount
(
op
.
N
)
return
return
nil
}
}
func
(
fs
*
fsImpl
)
MkDir
(
func
(
fs
*
fsImpl
)
MkDir
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
MkDirOp
)
(
err
error
)
{
op
*
fuseops
.
MkDirOp
)
error
{
fs
.
mu
.
Lock
()
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
defer
fs
.
mu
.
Unlock
()
...
@@ -322,12 +319,12 @@ func (fs *fsImpl) MkDir(
...
@@ -322,12 +319,12 @@ func (fs *fsImpl) MkDir(
Attributes
:
child
.
attributes
,
Attributes
:
child
.
attributes
,
}
}
return
return
nil
}
}
func
(
fs
*
fsImpl
)
CreateFile
(
func
(
fs
*
fsImpl
)
CreateFile
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
CreateFileOp
)
(
err
error
)
{
op
*
fuseops
.
CreateFileOp
)
error
{
fs
.
mu
.
Lock
()
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
defer
fs
.
mu
.
Unlock
()
...
@@ -354,31 +351,31 @@ func (fs *fsImpl) CreateFile(
...
@@ -354,31 +351,31 @@ func (fs *fsImpl) CreateFile(
Attributes
:
child
.
attributes
,
Attributes
:
child
.
attributes
,
}
}
return
return
nil
}
}
func
(
fs
*
fsImpl
)
OpenFile
(
func
(
fs
*
fsImpl
)
OpenFile
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
OpenFileOp
)
(
err
error
)
{
op
*
fuseops
.
OpenFileOp
)
error
{
fs
.
mu
.
Lock
()
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
defer
fs
.
mu
.
Unlock
()
// Verify that the inode has not been forgotten.
// Verify that the inode has not been forgotten.
_
=
fs
.
findInodeByID
(
op
.
Inode
)
_
=
fs
.
findInodeByID
(
op
.
Inode
)
return
return
nil
}
}
func
(
fs
*
fsImpl
)
OpenDir
(
func
(
fs
*
fsImpl
)
OpenDir
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
OpenDirOp
)
(
err
error
)
{
op
*
fuseops
.
OpenDirOp
)
error
{
fs
.
mu
.
Lock
()
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
defer
fs
.
mu
.
Unlock
()
// Verify that the inode has not been forgotten.
// Verify that the inode has not been forgotten.
_
=
fs
.
findInodeByID
(
op
.
Inode
)
_
=
fs
.
findInodeByID
(
op
.
Inode
)
return
return
nil
}
}
func
(
fs
*
fsImpl
)
Destroy
()
{
func
(
fs
*
fsImpl
)
Destroy
()
{
...
...
samples/hellofs/hello_fs.go
View file @
ae5da07e
...
@@ -33,13 +33,12 @@ import (
...
@@ -33,13 +33,12 @@ import (
// world
// world
//
//
// Each file contains the string "Hello, world!".
// Each file contains the string "Hello, world!".
func
NewHelloFS
(
clock
timeutil
.
Clock
)
(
server
fuse
.
Server
,
err
error
)
{
func
NewHelloFS
(
clock
timeutil
.
Clock
)
(
fuse
.
Server
,
error
)
{
fs
:=
&
helloFS
{
fs
:=
&
helloFS
{
Clock
:
clock
,
Clock
:
clock
,
}
}
server
=
fuseutil
.
NewFileSystemServer
(
fs
)
return
fuseutil
.
NewFileSystemServer
(
fs
),
nil
return
}
}
type
helloFS
struct
{
type
helloFS
struct
{
...
@@ -128,16 +127,14 @@ var gInodeInfo = map[fuseops.InodeID]inodeInfo{
...
@@ -128,16 +127,14 @@ var gInodeInfo = map[fuseops.InodeID]inodeInfo{
func
findChildInode
(
func
findChildInode
(
name
string
,
name
string
,
children
[]
fuseutil
.
Dirent
)
(
inode
fuseops
.
InodeID
,
err
error
)
{
children
[]
fuseutil
.
Dirent
)
(
fuseops
.
InodeID
,
error
)
{
for
_
,
e
:=
range
children
{
for
_
,
e
:=
range
children
{
if
e
.
Name
==
name
{
if
e
.
Name
==
name
{
inode
=
e
.
Inode
return
e
.
Inode
,
nil
return
}
}
}
}
err
=
fuse
.
ENOENT
return
0
,
fuse
.
ENOENT
return
}
}
func
(
fs
*
helloFS
)
patchAttributes
(
func
(
fs
*
helloFS
)
patchAttributes
(
...
@@ -150,24 +147,23 @@ func (fs *helloFS) patchAttributes(
...
@@ -150,24 +147,23 @@ func (fs *helloFS) patchAttributes(
func
(
fs
*
helloFS
)
StatFS
(
func
(
fs
*
helloFS
)
StatFS
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
StatFSOp
)
(
err
error
)
{
op
*
fuseops
.
StatFSOp
)
error
{
return
return
nil
}
}
func
(
fs
*
helloFS
)
LookUpInode
(
func
(
fs
*
helloFS
)
LookUpInode
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
LookUpInodeOp
)
(
err
error
)
{
op
*
fuseops
.
LookUpInodeOp
)
error
{
// Find the info for the parent.
// Find the info for the parent.
parentInfo
,
ok
:=
gInodeInfo
[
op
.
Parent
]
parentInfo
,
ok
:=
gInodeInfo
[
op
.
Parent
]
if
!
ok
{
if
!
ok
{
err
=
fuse
.
ENOENT
return
fuse
.
ENOENT
return
}
}
// Find the child within the parent.
// Find the child within the parent.
childInode
,
err
:=
findChildInode
(
op
.
Name
,
parentInfo
.
children
)
childInode
,
err
:=
findChildInode
(
op
.
Name
,
parentInfo
.
children
)
if
err
!=
nil
{
if
err
!=
nil
{
return
return
err
}
}
// Copy over information.
// Copy over information.
...
@@ -177,17 +173,16 @@ func (fs *helloFS) LookUpInode(
...
@@ -177,17 +173,16 @@ func (fs *helloFS) LookUpInode(
// Patch attributes.
// Patch attributes.
fs
.
patchAttributes
(
&
op
.
Entry
.
Attributes
)
fs
.
patchAttributes
(
&
op
.
Entry
.
Attributes
)
return
return
nil
}
}
func
(
fs
*
helloFS
)
GetInodeAttributes
(
func
(
fs
*
helloFS
)
GetInodeAttributes
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
GetInodeAttributesOp
)
(
err
error
)
{
op
*
fuseops
.
GetInodeAttributesOp
)
error
{
// Find the info for this inode.
// Find the info for this inode.
info
,
ok
:=
gInodeInfo
[
op
.
Inode
]
info
,
ok
:=
gInodeInfo
[
op
.
Inode
]
if
!
ok
{
if
!
ok
{
err
=
fuse
.
ENOENT
return
fuse
.
ENOENT
return
}
}
// Copy over its attributes.
// Copy over its attributes.
...
@@ -196,37 +191,34 @@ func (fs *helloFS) GetInodeAttributes(
...
@@ -196,37 +191,34 @@ func (fs *helloFS) GetInodeAttributes(
// Patch attributes.
// Patch attributes.
fs
.
patchAttributes
(
&
op
.
Attributes
)
fs
.
patchAttributes
(
&
op
.
Attributes
)
return
return
nil
}
}
func
(
fs
*
helloFS
)
OpenDir
(
func
(
fs
*
helloFS
)
OpenDir
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
OpenDirOp
)
(
err
error
)
{
op
*
fuseops
.
OpenDirOp
)
error
{
// Allow opening any directory.
// Allow opening any directory.
return
return
nil
}
}
func
(
fs
*
helloFS
)
ReadDir
(
func
(
fs
*
helloFS
)
ReadDir
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
ReadDirOp
)
(
err
error
)
{
op
*
fuseops
.
ReadDirOp
)
error
{
// Find the info for this inode.
// Find the info for this inode.
info
,
ok
:=
gInodeInfo
[
op
.
Inode
]
info
,
ok
:=
gInodeInfo
[
op
.
Inode
]
if
!
ok
{
if
!
ok
{
err
=
fuse
.
ENOENT
return
fuse
.
ENOENT
return
}
}
if
!
info
.
dir
{
if
!
info
.
dir
{
err
=
fuse
.
EIO
return
fuse
.
EIO
return
}
}
entries
:=
info
.
children
entries
:=
info
.
children
// Grab the range of interest.
// Grab the range of interest.
if
op
.
Offset
>
fuseops
.
DirOffset
(
len
(
entries
))
{
if
op
.
Offset
>
fuseops
.
DirOffset
(
len
(
entries
))
{
err
=
fuse
.
EIO
return
fuse
.
EIO
return
}
}
entries
=
entries
[
op
.
Offset
:
]
entries
=
entries
[
op
.
Offset
:
]
...
@@ -241,28 +233,29 @@ func (fs *helloFS) ReadDir(
...
@@ -241,28 +233,29 @@ func (fs *helloFS) ReadDir(
op
.
BytesRead
+=
n
op
.
BytesRead
+=
n
}
}
return
return
nil
}
}
func
(
fs
*
helloFS
)
OpenFile
(
func
(
fs
*
helloFS
)
OpenFile
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
OpenFileOp
)
(
err
error
)
{
op
*
fuseops
.
OpenFileOp
)
error
{
// Allow opening any file.
// Allow opening any file.
return
return
nil
}
}
func
(
fs
*
helloFS
)
ReadFile
(
func
(
fs
*
helloFS
)
ReadFile
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
ReadFileOp
)
(
err
error
)
{
op
*
fuseops
.
ReadFileOp
)
error
{
// Let io.ReaderAt deal with the semantics.
// Let io.ReaderAt deal with the semantics.
reader
:=
strings
.
NewReader
(
"Hello, world!"
)
reader
:=
strings
.
NewReader
(
"Hello, world!"
)
var
err
error
op
.
BytesRead
,
err
=
reader
.
ReadAt
(
op
.
Dst
,
op
.
Offset
)
op
.
BytesRead
,
err
=
reader
.
ReadAt
(
op
.
Dst
,
op
.
Offset
)
// Special case: FUSE doesn't expect us to return io.EOF.
// Special case: FUSE doesn't expect us to return io.EOF.
if
err
==
io
.
EOF
{
if
err
==
io
.
EOF
{
err
=
nil
return
nil
}
}
return
return
err
}
}
samples/in_process.go
View file @
ae5da07e
...
@@ -75,7 +75,7 @@ func (t *SampleTest) SetUp(ti *ogletest.TestInfo) {
...
@@ -75,7 +75,7 @@ func (t *SampleTest) SetUp(ti *ogletest.TestInfo) {
func
(
t
*
SampleTest
)
initialize
(
func
(
t
*
SampleTest
)
initialize
(
ctx
context
.
Context
,
ctx
context
.
Context
,
server
fuse
.
Server
,
server
fuse
.
Server
,
config
*
fuse
.
MountConfig
)
(
err
error
)
{
config
*
fuse
.
MountConfig
)
error
{
// Initialize the context used by the test.
// Initialize the context used by the test.
t
.
Ctx
=
ctx
t
.
Ctx
=
ctx
...
@@ -89,20 +89,19 @@ func (t *SampleTest) initialize(
...
@@ -89,20 +89,19 @@ func (t *SampleTest) initialize(
t
.
Clock
.
SetTime
(
time
.
Date
(
2012
,
8
,
15
,
22
,
56
,
0
,
0
,
time
.
Local
))
t
.
Clock
.
SetTime
(
time
.
Date
(
2012
,
8
,
15
,
22
,
56
,
0
,
0
,
time
.
Local
))
// Set up a temporary directory.
// Set up a temporary directory.
var
err
error
t
.
Dir
,
err
=
ioutil
.
TempDir
(
""
,
"sample_test"
)
t
.
Dir
,
err
=
ioutil
.
TempDir
(
""
,
"sample_test"
)
if
err
!=
nil
{
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"TempDir: %v"
,
err
)
return
fmt
.
Errorf
(
"TempDir: %v"
,
err
)
return
}
}
// Mount the file system.
// Mount the file system.
t
.
mfs
,
err
=
fuse
.
Mount
(
t
.
Dir
,
server
,
config
)
t
.
mfs
,
err
=
fuse
.
Mount
(
t
.
Dir
,
server
,
config
)
if
err
!=
nil
{
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"Mount: %v"
,
err
)
return
fmt
.
Errorf
(
"Mount: %v"
,
err
)
return
}
}
return
return
nil
}
}
// Unmount the file system and clean up. Panics on error.
// Unmount the file system and clean up. Panics on error.
...
@@ -126,28 +125,23 @@ func (t *SampleTest) destroy() (err error) {
...
@@ -126,28 +125,23 @@ func (t *SampleTest) destroy() (err error) {
// Was the file system mounted?
// Was the file system mounted?
if
t
.
mfs
==
nil
{
if
t
.
mfs
==
nil
{
return
return
nil
}
}
// Unmount the file system.
// Unmount the file system.
err
=
unmount
(
t
.
Dir
)
if
err
:=
unmount
(
t
.
Dir
);
err
!=
nil
{
if
err
!=
nil
{
return
fmt
.
Errorf
(
"unmount: %v"
,
err
)
err
=
fmt
.
Errorf
(
"unmount: %v"
,
err
)
return
}
}
// Unlink the mount point.
// Unlink the mount point.
if
err
=
os
.
Remove
(
t
.
Dir
);
err
!=
nil
{
if
err
:=
os
.
Remove
(
t
.
Dir
);
err
!=
nil
{
err
=
fmt
.
Errorf
(
"Unlinking mount point: %v"
,
err
)
return
fmt
.
Errorf
(
"Unlinking mount point: %v"
,
err
)
return
}
}
// Join the file system.
// Join the file system.
err
=
t
.
mfs
.
Join
(
t
.
Ctx
)
if
err
:=
t
.
mfs
.
Join
(
t
.
Ctx
);
err
!=
nil
{
if
err
!=
nil
{
return
fmt
.
Errorf
(
"mfs.Join: %v"
,
err
)
err
=
fmt
.
Errorf
(
"mfs.Join: %v"
,
err
)
return
}
}
return
return
nil
}
}
samples/interruptfs/interrupt_fs.go
View file @
ae5da07e
...
@@ -56,13 +56,11 @@ type InterruptFS struct {
...
@@ -56,13 +56,11 @@ type InterruptFS struct {
flushReceived
chan
struct
{}
flushReceived
chan
struct
{}
}
}
func
New
()
(
fs
*
InterruptFS
)
{
func
New
()
*
InterruptFS
{
fs
=
&
InterruptFS
{
return
&
InterruptFS
{
readReceived
:
make
(
chan
struct
{}),
readReceived
:
make
(
chan
struct
{}),
flushReceived
:
make
(
chan
struct
{}),
flushReceived
:
make
(
chan
struct
{}),
}
}
return
}
}
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
...
@@ -101,35 +99,33 @@ func (fs *InterruptFS) EnableFlushBlocking() {
...
@@ -101,35 +99,33 @@ func (fs *InterruptFS) EnableFlushBlocking() {
func
(
fs
*
InterruptFS
)
StatFS
(
func
(
fs
*
InterruptFS
)
StatFS
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
StatFSOp
)
(
err
error
)
{
op
*
fuseops
.
StatFSOp
)
error
{
return
return
nil
}
}
func
(
fs
*
InterruptFS
)
LookUpInode
(
func
(
fs
*
InterruptFS
)
LookUpInode
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
LookUpInodeOp
)
(
err
error
)
{
op
*
fuseops
.
LookUpInodeOp
)
error
{
// We support only one parent.
// We support only one parent.
if
op
.
Parent
!=
fuseops
.
RootInodeID
{
if
op
.
Parent
!=
fuseops
.
RootInodeID
{
err
=
fmt
.
Errorf
(
"Unexpected parent: %v"
,
op
.
Parent
)
return
fmt
.
Errorf
(
"Unexpected parent: %v"
,
op
.
Parent
)
return
}
}
// We support only one name.
// We support only one name.
if
op
.
Name
!=
"foo"
{
if
op
.
Name
!=
"foo"
{
err
=
fuse
.
ENOENT
return
fuse
.
ENOENT
return
}
}
// Fill in the response.
// Fill in the response.
op
.
Entry
.
Child
=
fooID
op
.
Entry
.
Child
=
fooID
op
.
Entry
.
Attributes
=
fooAttrs
op
.
Entry
.
Attributes
=
fooAttrs
return
return
nil
}
}
func
(
fs
*
InterruptFS
)
GetInodeAttributes
(
func
(
fs
*
InterruptFS
)
GetInodeAttributes
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
GetInodeAttributesOp
)
(
err
error
)
{
op
*
fuseops
.
GetInodeAttributesOp
)
error
{
switch
op
.
Inode
{
switch
op
.
Inode
{
case
fuseops
.
RootInodeID
:
case
fuseops
.
RootInodeID
:
op
.
Attributes
=
rootAttrs
op
.
Attributes
=
rootAttrs
...
@@ -138,22 +134,21 @@ func (fs *InterruptFS) GetInodeAttributes(
...
@@ -138,22 +134,21 @@ func (fs *InterruptFS) GetInodeAttributes(
op
.
Attributes
=
fooAttrs
op
.
Attributes
=
fooAttrs
default
:
default
:
err
=
fmt
.
Errorf
(
"Unexpected inode ID: %v"
,
op
.
Inode
)
return
fmt
.
Errorf
(
"Unexpected inode ID: %v"
,
op
.
Inode
)
return
}
}
return
return
nil
}
}
func
(
fs
*
InterruptFS
)
OpenFile
(
func
(
fs
*
InterruptFS
)
OpenFile
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
OpenFileOp
)
(
err
error
)
{
op
*
fuseops
.
OpenFileOp
)
error
{
return
return
nil
}
}
func
(
fs
*
InterruptFS
)
ReadFile
(
func
(
fs
*
InterruptFS
)
ReadFile
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
ReadFileOp
)
(
err
error
)
{
op
*
fuseops
.
ReadFileOp
)
error
{
fs
.
mu
.
Lock
()
fs
.
mu
.
Lock
()
shouldBlock
:=
fs
.
blockForReads
shouldBlock
:=
fs
.
blockForReads
...
@@ -173,15 +168,15 @@ func (fs *InterruptFS) ReadFile(
...
@@ -173,15 +168,15 @@ func (fs *InterruptFS) ReadFile(
}
}
<-
done
<-
done
err
=
ctx
.
Err
()
return
ctx
.
Err
()
}
}
return
return
nil
}
}
func
(
fs
*
InterruptFS
)
FlushFile
(
func
(
fs
*
InterruptFS
)
FlushFile
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
FlushFileOp
)
(
err
error
)
{
op
*
fuseops
.
FlushFileOp
)
error
{
fs
.
mu
.
Lock
()
fs
.
mu
.
Lock
()
shouldBlock
:=
fs
.
blockForFlushes
shouldBlock
:=
fs
.
blockForFlushes
...
@@ -201,8 +196,8 @@ func (fs *InterruptFS) FlushFile(
...
@@ -201,8 +196,8 @@ func (fs *InterruptFS) FlushFile(
}
}
<-
done
<-
done
err
=
ctx
.
Err
()
return
ctx
.
Err
()
}
}
return
return
nil
}
}
samples/memfs/inode.go
View file @
ae5da07e
...
@@ -73,20 +73,17 @@ type inode struct {
...
@@ -73,20 +73,17 @@ type inode struct {
// Create a new inode with the supplied attributes, which need not contain
// Create a new inode with the supplied attributes, which need not contain
// time-related information (the inode object will take care of that).
// time-related information (the inode object will take care of that).
func
newInode
(
func
newInode
(
attrs
fuseops
.
InodeAttributes
)
*
inode
{
attrs
fuseops
.
InodeAttributes
)
(
in
*
inode
)
{
// Update time info.
// Update time info.
now
:=
time
.
Now
()
now
:=
time
.
Now
()
attrs
.
Mtime
=
now
attrs
.
Mtime
=
now
attrs
.
Crtime
=
now
attrs
.
Crtime
=
now
// Create the object.
// Create the object.
in
=
&
inode
{
return
&
inode
{
attrs
:
attrs
,
attrs
:
attrs
,
xattrs
:
make
(
map
[
string
][]
byte
),
xattrs
:
make
(
map
[
string
][]
byte
),
}
}
return
}
}
func
(
in
*
inode
)
CheckInvariants
()
{
func
(
in
*
inode
)
CheckInvariants
()
{
...
@@ -168,12 +165,11 @@ func (in *inode) findChild(name string) (i int, ok bool) {
...
@@ -168,12 +165,11 @@ func (in *inode) findChild(name string) (i int, ok bool) {
var
e
fuseutil
.
Dirent
var
e
fuseutil
.
Dirent
for
i
,
e
=
range
in
.
entries
{
for
i
,
e
=
range
in
.
entries
{
if
e
.
Name
==
name
{
if
e
.
Name
==
name
{
ok
=
true
return
i
,
true
return
}
}
}
}
return
return
0
,
false
}
}
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
...
@@ -183,14 +179,15 @@ func (in *inode) findChild(name string) (i int, ok bool) {
...
@@ -183,14 +179,15 @@ func (in *inode) findChild(name string) (i int, ok bool) {
// Return the number of children of the directory.
// Return the number of children of the directory.
//
//
// REQUIRES: in.isDir()
// REQUIRES: in.isDir()
func
(
in
*
inode
)
Len
()
(
n
int
)
{
func
(
in
*
inode
)
Len
()
int
{
var
n
int
for
_
,
e
:=
range
in
.
entries
{
for
_
,
e
:=
range
in
.
entries
{
if
e
.
Type
!=
fuseutil
.
DT_Unknown
{
if
e
.
Type
!=
fuseutil
.
DT_Unknown
{
n
++
n
++
}
}
}
}
return
return
n
}
}
// Find an entry for the given child name and return its inode ID.
// Find an entry for the given child name and return its inode ID.
...
@@ -206,7 +203,7 @@ func (in *inode) LookUpChild(name string) (
...
@@ -206,7 +203,7 @@ func (in *inode) LookUpChild(name string) (
typ
=
in
.
entries
[
index
]
.
Type
typ
=
in
.
entries
[
index
]
.
Type
}
}
return
return
id
,
typ
,
ok
}
}
// Add an entry for a child.
// Add an entry for a child.
...
@@ -272,11 +269,12 @@ func (in *inode) RemoveChild(name string) {
...
@@ -272,11 +269,12 @@ func (in *inode) RemoveChild(name string) {
// Serve a ReadDir request.
// Serve a ReadDir request.
//
//
// REQUIRES: in.isDir()
// REQUIRES: in.isDir()
func
(
in
*
inode
)
ReadDir
(
p
[]
byte
,
offset
int
)
(
n
int
)
{
func
(
in
*
inode
)
ReadDir
(
p
[]
byte
,
offset
int
)
int
{
if
!
in
.
isDir
()
{
if
!
in
.
isDir
()
{
panic
(
"ReadDir called on non-directory."
)
panic
(
"ReadDir called on non-directory."
)
}
}
var
n
int
for
i
:=
offset
;
i
<
len
(
in
.
entries
);
i
++
{
for
i
:=
offset
;
i
<
len
(
in
.
entries
);
i
++
{
e
:=
in
.
entries
[
i
]
e
:=
in
.
entries
[
i
]
...
@@ -293,36 +291,35 @@ func (in *inode) ReadDir(p []byte, offset int) (n int) {
...
@@ -293,36 +291,35 @@ func (in *inode) ReadDir(p []byte, offset int) (n int) {
n
+=
tmp
n
+=
tmp
}
}
return
return
n
}
}
// Read from the file's contents. See documentation for ioutil.ReaderAt.
// Read from the file's contents. See documentation for ioutil.ReaderAt.
//
//
// REQUIRES: in.isFile()
// REQUIRES: in.isFile()
func
(
in
*
inode
)
ReadAt
(
p
[]
byte
,
off
int64
)
(
n
int
,
err
error
)
{
func
(
in
*
inode
)
ReadAt
(
p
[]
byte
,
off
int64
)
(
int
,
error
)
{
if
!
in
.
isFile
()
{
if
!
in
.
isFile
()
{
panic
(
"ReadAt called on non-file."
)
panic
(
"ReadAt called on non-file."
)
}
}
// Ensure the offset is in range.
// Ensure the offset is in range.
if
off
>
int64
(
len
(
in
.
contents
))
{
if
off
>
int64
(
len
(
in
.
contents
))
{
err
=
io
.
EOF
return
0
,
io
.
EOF
return
}
}
// Read what we can.
// Read what we can.
n
=
copy
(
p
,
in
.
contents
[
off
:
])
n
:
=
copy
(
p
,
in
.
contents
[
off
:
])
if
n
<
len
(
p
)
{
if
n
<
len
(
p
)
{
err
=
io
.
EOF
return
n
,
io
.
EOF
}
}
return
return
n
,
nil
}
}
// Write to the file's contents. See documentation for ioutil.WriterAt.
// Write to the file's contents. See documentation for ioutil.WriterAt.
//
//
// REQUIRES: in.isFile()
// REQUIRES: in.isFile()
func
(
in
*
inode
)
WriteAt
(
p
[]
byte
,
off
int64
)
(
n
int
,
err
error
)
{
func
(
in
*
inode
)
WriteAt
(
p
[]
byte
,
off
int64
)
(
int
,
error
)
{
if
!
in
.
isFile
()
{
if
!
in
.
isFile
()
{
panic
(
"WriteAt called on non-file."
)
panic
(
"WriteAt called on non-file."
)
}
}
...
@@ -339,14 +336,14 @@ func (in *inode) WriteAt(p []byte, off int64) (n int, err error) {
...
@@ -339,14 +336,14 @@ func (in *inode) WriteAt(p []byte, off int64) (n int, err error) {
}
}
// Copy in the data.
// Copy in the data.
n
=
copy
(
in
.
contents
[
off
:
],
p
)
n
:
=
copy
(
in
.
contents
[
off
:
],
p
)
// Sanity check.
// Sanity check.
if
n
!=
len
(
p
)
{
if
n
!=
len
(
p
)
{
panic
(
fmt
.
Sprintf
(
"Unexpected short copy: %v"
,
n
))
panic
(
fmt
.
Sprintf
(
"Unexpected short copy: %v"
,
n
))
}
}
return
return
n
,
nil
}
}
// Update attributes from non-nil parameters.
// Update attributes from non-nil parameters.
...
@@ -384,17 +381,15 @@ func (in *inode) SetAttributes(
...
@@ -384,17 +381,15 @@ func (in *inode) SetAttributes(
}
}
}
}
func
(
in
*
inode
)
Fallocate
(
mode
uint32
,
offset
uint64
,
length
uint64
)
(
func
(
in
*
inode
)
Fallocate
(
mode
uint32
,
offset
uint64
,
length
uint64
)
error
{
err
error
)
{
if
mode
!=
0
{
if
mode
==
0
{
return
fuse
.
ENOSYS
}
newSize
:=
int
(
offset
+
length
)
newSize
:=
int
(
offset
+
length
)
if
newSize
>
len
(
in
.
contents
)
{
if
newSize
>
len
(
in
.
contents
)
{
padding
:=
make
([]
byte
,
newSize
-
len
(
in
.
contents
))
padding
:=
make
([]
byte
,
newSize
-
len
(
in
.
contents
))
in
.
contents
=
append
(
in
.
contents
,
padding
...
)
in
.
contents
=
append
(
in
.
contents
,
padding
...
)
in
.
attrs
.
Size
=
offset
+
length
in
.
attrs
.
Size
=
offset
+
length
}
}
}
else
{
return
nil
err
=
fuse
.
ENOSYS
}
return
}
}
samples/memfs/memfs.go
View file @
ae5da07e
This diff is collapsed.
Click to expand it.
samples/memfs/posix_test.go
View file @
ae5da07e
...
@@ -39,8 +39,7 @@ func TestPosix(t *testing.T) { RunTests(t) }
...
@@ -39,8 +39,7 @@ func TestPosix(t *testing.T) { RunTests(t) }
func
getFileOffset
(
f
*
os
.
File
)
(
offset
int64
,
err
error
)
{
func
getFileOffset
(
f
*
os
.
File
)
(
offset
int64
,
err
error
)
{
const
relativeToCurrent
=
1
const
relativeToCurrent
=
1
offset
,
err
=
f
.
Seek
(
0
,
relativeToCurrent
)
return
f
.
Seek
(
0
,
relativeToCurrent
)
return
}
}
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
...
...
samples/mount_sample/mount.go
View file @
ae5da07e
...
@@ -42,11 +42,10 @@ var fFsyncError = flag.Int("flushfs.fsync_error", 0, "")
...
@@ -42,11 +42,10 @@ var fFsyncError = flag.Int("flushfs.fsync_error", 0, "")
var
fReadOnly
=
flag
.
Bool
(
"read_only"
,
false
,
"Mount in read-only mode."
)
var
fReadOnly
=
flag
.
Bool
(
"read_only"
,
false
,
"Mount in read-only mode."
)
var
fDebug
=
flag
.
Bool
(
"debug"
,
false
,
"Enable debug logging."
)
var
fDebug
=
flag
.
Bool
(
"debug"
,
false
,
"Enable debug logging."
)
func
makeFlushFS
()
(
server
fuse
.
Server
,
err
error
)
{
func
makeFlushFS
()
(
fuse
.
Server
,
error
)
{
// Check the flags.
// Check the flags.
if
*
fFlushesFile
==
0
||
*
fFsyncsFile
==
0
{
if
*
fFlushesFile
==
0
||
*
fFsyncsFile
==
0
{
err
=
fmt
.
Errorf
(
"You must set the flushfs flags."
)
return
nil
,
fmt
.
Errorf
(
"You must set the flushfs flags."
)
return
}
}
// Set up the files.
// Set up the files.
...
@@ -67,18 +66,15 @@ func makeFlushFS() (server fuse.Server, err error) {
...
@@ -67,18 +66,15 @@ func makeFlushFS() (server fuse.Server, err error) {
// Report flushes and fsyncs by writing the contents followed by a newline.
// Report flushes and fsyncs by writing the contents followed by a newline.
report
:=
func
(
f
*
os
.
File
,
outErr
error
)
func
(
string
)
error
{
report
:=
func
(
f
*
os
.
File
,
outErr
error
)
func
(
string
)
error
{
return
func
(
s
string
)
(
err
error
)
{
return
func
(
s
string
)
error
{
buf
:=
[]
byte
(
s
)
buf
:=
[]
byte
(
s
)
buf
=
append
(
buf
,
'\n'
)
buf
=
append
(
buf
,
'\n'
)
_
,
err
=
f
.
Write
(
buf
)
if
_
,
err
:=
f
.
Write
(
buf
);
err
!=
nil
{
if
err
!=
nil
{
return
fmt
.
Errorf
(
"Write: %v"
,
err
)
err
=
fmt
.
Errorf
(
"Write: %v"
,
err
)
return
}
}
err
=
outErr
return
outErr
return
}
}
}
}
...
@@ -86,31 +82,25 @@ func makeFlushFS() (server fuse.Server, err error) {
...
@@ -86,31 +82,25 @@ func makeFlushFS() (server fuse.Server, err error) {
reportFsync
:=
report
(
fsyncs
,
fsyncErr
)
reportFsync
:=
report
(
fsyncs
,
fsyncErr
)
// Create the file system.
// Create the file system.
server
,
err
=
flushfs
.
NewFileSystem
(
reportFlush
,
reportFsync
)
return
flushfs
.
NewFileSystem
(
reportFlush
,
reportFsync
)
return
}
}
func
makeFS
()
(
server
fuse
.
Server
,
err
error
)
{
func
makeFS
()
(
fuse
.
Server
,
error
)
{
switch
*
fType
{
switch
*
fType
{
default
:
default
:
err
=
fmt
.
Errorf
(
"Unknown FS type: %v"
,
*
fType
)
return
nil
,
fmt
.
Errorf
(
"Unknown FS type: %v"
,
*
fType
)
case
"flushfs"
:
case
"flushfs"
:
server
,
err
=
makeFlushFS
()
return
makeFlushFS
()
}
}
return
}
}
func
getReadyFile
()
(
f
*
os
.
File
,
err
error
)
{
func
getReadyFile
()
(
*
os
.
File
,
error
)
{
if
*
fReadyFile
==
0
{
if
*
fReadyFile
==
0
{
err
=
errors
.
New
(
"You must set --ready_file."
)
return
nil
,
errors
.
New
(
"You must set --ready_file."
)
return
}
}
f
=
os
.
NewFile
(
uintptr
(
*
fReadyFile
),
"(ready file)"
)
return
os
.
NewFile
(
uintptr
(
*
fReadyFile
),
"(ready file)"
),
nil
return
}
}
func
main
()
{
func
main
()
{
...
...
samples/statfs/statfs.go
View file @
ae5da07e
...
@@ -47,15 +47,13 @@ type FS interface {
...
@@ -47,15 +47,13 @@ type FS interface {
MostRecentWriteSize
()
int
MostRecentWriteSize
()
int
}
}
func
New
()
(
fs
FS
)
{
func
New
()
FS
{
fs
=
&
statFS
{
return
&
statFS
{
cannedStatResponse
:
fuseops
.
InodeAttributes
{
cannedStatResponse
:
fuseops
.
InodeAttributes
{
Mode
:
0666
,
Mode
:
0666
,
},
},
mostRecentWriteSize
:
-
1
,
mostRecentWriteSize
:
-
1
,
}
}
return
}
}
const
childInodeID
=
fuseops
.
RootInodeID
+
1
const
childInodeID
=
fuseops
.
RootInodeID
+
1
...
@@ -118,32 +116,31 @@ func (fs *statFS) MostRecentWriteSize() int {
...
@@ -118,32 +116,31 @@ func (fs *statFS) MostRecentWriteSize() int {
// LOCKS_EXCLUDED(fs.mu)
// LOCKS_EXCLUDED(fs.mu)
func
(
fs
*
statFS
)
StatFS
(
func
(
fs
*
statFS
)
StatFS
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
StatFSOp
)
(
err
error
)
{
op
*
fuseops
.
StatFSOp
)
error
{
fs
.
mu
.
Lock
()
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
defer
fs
.
mu
.
Unlock
()
*
op
=
fs
.
cannedResponse
*
op
=
fs
.
cannedResponse
return
return
nil
}
}
func
(
fs
*
statFS
)
LookUpInode
(
func
(
fs
*
statFS
)
LookUpInode
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
LookUpInodeOp
)
(
err
error
)
{
op
*
fuseops
.
LookUpInodeOp
)
error
{
// Only the root has children.
// Only the root has children.
if
op
.
Parent
!=
fuseops
.
RootInodeID
{
if
op
.
Parent
!=
fuseops
.
RootInodeID
{
err
=
fuse
.
ENOENT
return
fuse
.
ENOENT
return
}
}
op
.
Entry
.
Child
=
childInodeID
op
.
Entry
.
Child
=
childInodeID
op
.
Entry
.
Attributes
=
fs
.
fileAttrs
()
op
.
Entry
.
Attributes
=
fs
.
fileAttrs
()
return
return
nil
}
}
func
(
fs
*
statFS
)
GetInodeAttributes
(
func
(
fs
*
statFS
)
GetInodeAttributes
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
GetInodeAttributesOp
)
(
err
error
)
{
op
*
fuseops
.
GetInodeAttributesOp
)
error
{
switch
op
.
Inode
{
switch
op
.
Inode
{
case
fuseops
.
RootInodeID
:
case
fuseops
.
RootInodeID
:
op
.
Attributes
=
dirAttrs
()
op
.
Attributes
=
dirAttrs
()
...
@@ -152,32 +149,32 @@ func (fs *statFS) GetInodeAttributes(
...
@@ -152,32 +149,32 @@ func (fs *statFS) GetInodeAttributes(
op
.
Attributes
=
fs
.
fileAttrs
()
op
.
Attributes
=
fs
.
fileAttrs
()
default
:
default
:
err
=
fuse
.
ENOENT
return
fuse
.
ENOENT
}
}
return
return
nil
}
}
func
(
fs
*
statFS
)
SetInodeAttributes
(
func
(
fs
*
statFS
)
SetInodeAttributes
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
SetInodeAttributesOp
)
(
err
error
)
{
op
*
fuseops
.
SetInodeAttributesOp
)
error
{
// Ignore calls to truncate existing files when opening.
// Ignore calls to truncate existing files when opening.
return
return
nil
}
}
func
(
fs
*
statFS
)
OpenFile
(
func
(
fs
*
statFS
)
OpenFile
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
OpenFileOp
)
(
err
error
)
{
op
*
fuseops
.
OpenFileOp
)
error
{
return
return
nil
}
}
// LOCKS_EXCLUDED(fs.mu)
// LOCKS_EXCLUDED(fs.mu)
func
(
fs
*
statFS
)
WriteFile
(
func
(
fs
*
statFS
)
WriteFile
(
ctx
context
.
Context
,
ctx
context
.
Context
,
op
*
fuseops
.
WriteFileOp
)
(
err
error
)
{
op
*
fuseops
.
WriteFileOp
)
error
{
fs
.
mu
.
Lock
()
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
defer
fs
.
mu
.
Unlock
()
fs
.
mostRecentWriteSize
=
len
(
op
.
Data
)
fs
.
mostRecentWriteSize
=
len
(
op
.
Data
)
return
return
nil
}
}
samples/statfs/statfs_darwin_test.go
View file @
ae5da07e
...
@@ -35,7 +35,7 @@ var gDfOutputRegexp = regexp.MustCompile(`^\S+\s+(\d+)\s+(\d+)\s+(\d+)\s+\d+%\s+
...
@@ -35,7 +35,7 @@ var gDfOutputRegexp = regexp.MustCompile(`^\S+\s+(\d+)\s+(\d+)\s+(\d+)\s+\d+%\s+
// Helpers
// Helpers
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
func
convertName
(
in
[]
int8
)
(
s
string
)
{
func
convertName
(
in
[]
int8
)
string
{
var
tmp
[]
byte
var
tmp
[]
byte
for
_
,
v
:=
range
in
{
for
_
,
v
:=
range
in
{
if
v
==
0
{
if
v
==
0
{
...
@@ -45,8 +45,7 @@ func convertName(in []int8) (s string) {
...
@@ -45,8 +45,7 @@ func convertName(in []int8) (s string) {
tmp
=
append
(
tmp
,
byte
(
v
))
tmp
=
append
(
tmp
,
byte
(
v
))
}
}
s
=
string
(
tmp
)
return
string
(
tmp
)
return
}
}
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
...
...
samples/statfs/statfs_test.go
View file @
ae5da07e
...
@@ -53,7 +53,7 @@ func df(dir string) (capacity, used, available uint64, err error) {
...
@@ -53,7 +53,7 @@ func df(dir string) (capacity, used, available uint64, err error) {
output
,
err
:=
cmd
.
CombinedOutput
()
output
,
err
:=
cmd
.
CombinedOutput
()
if
err
!=
nil
{
if
err
!=
nil
{
return
return
0
,
0
,
0
,
err
}
}
// Scrape it.
// Scrape it.
...
@@ -65,23 +65,22 @@ func df(dir string) (capacity, used, available uint64, err error) {
...
@@ -65,23 +65,22 @@ func df(dir string) (capacity, used, available uint64, err error) {
submatches
:=
gDfOutputRegexp
.
FindSubmatch
(
line
)
submatches
:=
gDfOutputRegexp
.
FindSubmatch
(
line
)
if
submatches
==
nil
{
if
submatches
==
nil
{
err
=
fmt
.
Errorf
(
"Unable to parse line: %q"
,
line
)
return
0
,
0
,
0
,
fmt
.
Errorf
(
"Unable to parse line: %q"
,
line
)
return
}
}
capacity
,
err
=
strconv
.
ParseUint
(
string
(
submatches
[
1
]),
10
,
64
)
capacity
,
err
=
strconv
.
ParseUint
(
string
(
submatches
[
1
]),
10
,
64
)
if
err
!=
nil
{
if
err
!=
nil
{
return
return
0
,
0
,
0
,
err
}
}
used
,
err
=
strconv
.
ParseUint
(
string
(
submatches
[
2
]),
10
,
64
)
used
,
err
=
strconv
.
ParseUint
(
string
(
submatches
[
2
]),
10
,
64
)
if
err
!=
nil
{
if
err
!=
nil
{
return
return
0
,
0
,
0
,
err
}
}
available
,
err
=
strconv
.
ParseUint
(
string
(
submatches
[
3
]),
10
,
64
)
available
,
err
=
strconv
.
ParseUint
(
string
(
submatches
[
3
]),
10
,
64
)
if
err
!=
nil
{
if
err
!=
nil
{
return
return
0
,
0
,
0
,
err
}
}
// Scale appropriately based on the BLOCKSIZE set above.
// Scale appropriately based on the BLOCKSIZE set above.
...
@@ -89,11 +88,10 @@ func df(dir string) (capacity, used, available uint64, err error) {
...
@@ -89,11 +88,10 @@ func df(dir string) (capacity, used, available uint64, err error) {
used
*=
1024
used
*=
1024
available
*=
1024
available
*=
1024
return
return
capacity
,
used
,
available
,
nil
}
}
err
=
fmt
.
Errorf
(
"Unable to parse df output:
\n
%s"
,
output
)
return
0
,
0
,
0
,
fmt
.
Errorf
(
"Unable to parse df output:
\n
%s"
,
output
)
return
}
}
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
...
...
samples/subprocess.go
View file @
ae5da07e
...
@@ -80,23 +80,21 @@ var getToolContents_Err error
...
@@ -80,23 +80,21 @@ var getToolContents_Err error
var
getToolContents_Once
sync
.
Once
var
getToolContents_Once
sync
.
Once
// Implementation detail of getToolPath.
// Implementation detail of getToolPath.
func
getToolContentsImpl
()
(
contents
[]
byte
,
err
error
)
{
func
getToolContentsImpl
()
(
[]
byte
,
error
)
{
// Fast path: has the user set the flag?
// Fast path: has the user set the flag?
if
*
fToolPath
!=
""
{
if
*
fToolPath
!=
""
{
contents
,
err
=
ioutil
.
ReadFile
(
*
fToolPath
)
contents
,
err
:
=
ioutil
.
ReadFile
(
*
fToolPath
)
if
err
!=
nil
{
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"Reading mount_sample contents: %v"
,
err
)
return
nil
,
fmt
.
Errorf
(
"Reading mount_sample contents: %v"
,
err
)
return
}
}
return
return
contents
,
err
}
}
// Create a temporary directory into which we will compile the tool.
// Create a temporary directory into which we will compile the tool.
tempDir
,
err
:=
ioutil
.
TempDir
(
""
,
"sample_test"
)
tempDir
,
err
:=
ioutil
.
TempDir
(
""
,
"sample_test"
)
if
err
!=
nil
{
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"TempDir: %v"
,
err
)
return
nil
,
fmt
.
Errorf
(
"TempDir: %v"
,
err
)
return
}
}
toolPath
:=
path
.
Join
(
tempDir
,
"mount_sample"
)
toolPath
:=
path
.
Join
(
tempDir
,
"mount_sample"
)
...
@@ -114,34 +112,30 @@ func getToolContentsImpl() (contents []byte, err error) {
...
@@ -114,34 +112,30 @@ func getToolContentsImpl() (contents []byte, err error) {
output
,
err
:=
cmd
.
CombinedOutput
()
output
,
err
:=
cmd
.
CombinedOutput
()
if
err
!=
nil
{
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
return
nil
,
fmt
.
Errorf
(
"mount_sample exited with %v, output:
\n
%s"
,
"mount_sample exited with %v, output:
\n
%s"
,
err
,
err
,
string
(
output
))
string
(
output
))
return
}
}
// Slurp the tool contents.
// Slurp the tool contents.
contents
,
err
=
ioutil
.
ReadFile
(
toolPath
)
contents
,
err
:
=
ioutil
.
ReadFile
(
toolPath
)
if
err
!=
nil
{
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"ReadFile: %v"
,
err
)
return
nil
,
fmt
.
Errorf
(
"ReadFile: %v"
,
err
)
return
}
}
return
return
contents
,
nil
}
}
// Build the mount_sample tool if it has not yet been built for this process.
// Build the mount_sample tool if it has not yet been built for this process.
// Return its contents.
// Return its contents.
func
getToolContents
()
(
contents
[]
byte
,
err
error
)
{
func
getToolContents
()
(
[]
byte
,
error
)
{
// Get hold of the binary contents, if we haven't yet.
// Get hold of the binary contents, if we haven't yet.
getToolContents_Once
.
Do
(
func
()
{
getToolContents_Once
.
Do
(
func
()
{
getToolContents_Contents
,
getToolContents_Err
=
getToolContentsImpl
()
getToolContents_Contents
,
getToolContents_Err
=
getToolContentsImpl
()
})
})
contents
,
err
=
getToolContents_Contents
,
getToolContents_Err
return
getToolContents_Contents
,
getToolContents_Err
return
}
}
func
waitForMountSample
(
func
waitForMountSample
(
...
@@ -184,29 +178,27 @@ func waitForReady(readyReader *os.File, c chan<- struct{}) {
...
@@ -184,29 +178,27 @@ func waitForReady(readyReader *os.File, c chan<- struct{}) {
}
}
// Like SetUp, but doens't panic.
// Like SetUp, but doens't panic.
func
(
t
*
SubprocessTest
)
initialize
(
ctx
context
.
Context
)
(
err
error
)
{
func
(
t
*
SubprocessTest
)
initialize
(
ctx
context
.
Context
)
error
{
// Initialize the context.
// Initialize the context.
t
.
Ctx
=
ctx
t
.
Ctx
=
ctx
// Set up a temporary directory.
// Set up a temporary directory.
var
err
error
t
.
Dir
,
err
=
ioutil
.
TempDir
(
""
,
"sample_test"
)
t
.
Dir
,
err
=
ioutil
.
TempDir
(
""
,
"sample_test"
)
if
err
!=
nil
{
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"TempDir: %v"
,
err
)
return
fmt
.
Errorf
(
"TempDir: %v"
,
err
)
return
}
}
// Build/read the mount_sample tool.
// Build/read the mount_sample tool.
toolContents
,
err
:=
getToolContents
()
toolContents
,
err
:=
getToolContents
()
if
err
!=
nil
{
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"getTooltoolContents: %v"
,
err
)
return
fmt
.
Errorf
(
"getTooltoolContents: %v"
,
err
)
return
}
}
// Create a temporary file to hold the contents of the tool.
// Create a temporary file to hold the contents of the tool.
toolFile
,
err
:=
ioutil
.
TempFile
(
""
,
"sample_test"
)
toolFile
,
err
:=
ioutil
.
TempFile
(
""
,
"sample_test"
)
if
err
!=
nil
{
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"TempFile: %v"
,
err
)
return
fmt
.
Errorf
(
"TempFile: %v"
,
err
)
return
}
}
defer
toolFile
.
Close
()
defer
toolFile
.
Close
()
...
@@ -217,21 +209,18 @@ func (t *SubprocessTest) initialize(ctx context.Context) (err error) {
...
@@ -217,21 +209,18 @@ func (t *SubprocessTest) initialize(ctx context.Context) (err error) {
// Write out the tool contents and make them executable.
// Write out the tool contents and make them executable.
if
_
,
err
=
toolFile
.
Write
(
toolContents
);
err
!=
nil
{
if
_
,
err
=
toolFile
.
Write
(
toolContents
);
err
!=
nil
{
err
=
fmt
.
Errorf
(
"toolFile.Write: %v"
,
err
)
return
fmt
.
Errorf
(
"toolFile.Write: %v"
,
err
)
return
}
}
if
err
=
toolFile
.
Chmod
(
0500
);
err
!=
nil
{
if
err
=
toolFile
.
Chmod
(
0500
);
err
!=
nil
{
err
=
fmt
.
Errorf
(
"toolFile.Chmod: %v"
,
err
)
return
fmt
.
Errorf
(
"toolFile.Chmod: %v"
,
err
)
return
}
}
// Close the tool file to prevent "text file busy" errors below.
// Close the tool file to prevent "text file busy" errors below.
err
=
toolFile
.
Close
()
err
=
toolFile
.
Close
()
toolFile
=
nil
toolFile
=
nil
if
err
!=
nil
{
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"toolFile.Close: %v"
,
err
)
return
fmt
.
Errorf
(
"toolFile.Close: %v"
,
err
)
return
}
}
// Set up basic args for the subprocess.
// Set up basic args for the subprocess.
...
@@ -247,8 +236,7 @@ func (t *SubprocessTest) initialize(ctx context.Context) (err error) {
...
@@ -247,8 +236,7 @@ func (t *SubprocessTest) initialize(ctx context.Context) (err error) {
// Set up a pipe for the "ready" status.
// Set up a pipe for the "ready" status.
readyReader
,
readyWriter
,
err
:=
os
.
Pipe
()
readyReader
,
readyWriter
,
err
:=
os
.
Pipe
()
if
err
!=
nil
{
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"Pipe: %v"
,
err
)
return
fmt
.
Errorf
(
"Pipe: %v"
,
err
)
return
}
}
defer
readyReader
.
Close
()
defer
readyReader
.
Close
()
...
@@ -280,9 +268,8 @@ func (t *SubprocessTest) initialize(ctx context.Context) (err error) {
...
@@ -280,9 +268,8 @@ func (t *SubprocessTest) initialize(ctx context.Context) (err error) {
}
}
// Start the command.
// Start the command.
if
err
=
mountCmd
.
Start
();
err
!=
nil
{
if
err
:=
mountCmd
.
Start
();
err
!=
nil
{
err
=
fmt
.
Errorf
(
"mountCmd.Start: %v"
,
err
)
return
fmt
.
Errorf
(
"mountCmd.Start: %v"
,
err
)
return
}
}
// Launch a goroutine that waits for it and returns its status.
// Launch a goroutine that waits for it and returns its status.
...
@@ -296,14 +283,14 @@ func (t *SubprocessTest) initialize(ctx context.Context) (err error) {
...
@@ -296,14 +283,14 @@ func (t *SubprocessTest) initialize(ctx context.Context) (err error) {
select
{
select
{
case
<-
readyChan
:
case
<-
readyChan
:
case
err
=
<-
mountSampleErr
:
case
err
:
=
<-
mountSampleErr
:
return
return
err
}
}
// TearDown is no responsible for joining.
// TearDown is no responsible for joining.
t
.
mountSampleErr
=
mountSampleErr
t
.
mountSampleErr
=
mountSampleErr
return
return
nil
}
}
// Unmount the file system and clean up. Panics on error.
// Unmount the file system and clean up. Panics on error.
...
@@ -329,7 +316,7 @@ func (t *SubprocessTest) destroy() (err error) {
...
@@ -329,7 +316,7 @@ func (t *SubprocessTest) destroy() (err error) {
// If we didn't try to mount the file system, there's nothing further to do.
// If we didn't try to mount the file system, there's nothing further to do.
if
t
.
mountSampleErr
==
nil
{
if
t
.
mountSampleErr
==
nil
{
return
return
nil
}
}
// In the background, initiate an unmount.
// In the background, initiate an unmount.
...
@@ -358,9 +345,9 @@ func (t *SubprocessTest) destroy() (err error) {
...
@@ -358,9 +345,9 @@ func (t *SubprocessTest) destroy() (err error) {
}()
}()
// Wait for the subprocess.
// Wait for the subprocess.
if
err
=
<-
t
.
mountSampleErr
;
err
!=
nil
{
if
err
:
=
<-
t
.
mountSampleErr
;
err
!=
nil
{
return
return
err
}
}
return
return
nil
}
}
samples/unmount.go
View file @
ae5da07e
...
@@ -27,12 +27,12 @@ import (
...
@@ -27,12 +27,12 @@ import (
// "resource busy" errors, which happen from time to time on OS X (due to weird
// "resource busy" errors, which happen from time to time on OS X (due to weird
// requests from the Finder) and when tests don't or can't synchronize all
// requests from the Finder) and when tests don't or can't synchronize all
// events.
// events.
func
unmount
(
dir
string
)
(
err
error
)
{
func
unmount
(
dir
string
)
error
{
delay
:=
10
*
time
.
Millisecond
delay
:=
10
*
time
.
Millisecond
for
{
for
{
err
=
fuse
.
Unmount
(
dir
)
err
:
=
fuse
.
Unmount
(
dir
)
if
err
==
nil
{
if
err
==
nil
{
return
return
err
}
}
if
strings
.
Contains
(
err
.
Error
(),
"resource busy"
)
{
if
strings
.
Contains
(
err
.
Error
(),
"resource busy"
)
{
...
@@ -42,7 +42,6 @@ func unmount(dir string) (err error) {
...
@@ -42,7 +42,6 @@ func unmount(dir string) (err error) {
continue
continue
}
}
err
=
fmt
.
Errorf
(
"Unmount: %v"
,
err
)
return
fmt
.
Errorf
(
"Unmount: %v"
,
err
)
return
}
}
}
}
unmount_linux.go
View file @
ae5da07e
...
@@ -6,18 +6,17 @@ import (
...
@@ -6,18 +6,17 @@ import (
"os/exec"
"os/exec"
)
)
func
unmount
(
dir
string
)
(
err
error
)
{
func
unmount
(
dir
string
)
error
{
// Call fusermount.
// Call fusermount.
cmd
:=
exec
.
Command
(
"fusermount"
,
"-u"
,
dir
)
cmd
:=
exec
.
Command
(
"fusermount"
,
"-u"
,
dir
)
output
,
err
:=
cmd
.
CombinedOutput
()
output
,
err
:=
cmd
.
CombinedOutput
()
if
err
!=
nil
{
if
err
!=
nil
{
if
len
(
output
)
>
0
{
if
len
(
output
)
>
0
{
output
=
bytes
.
TrimRight
(
output
,
"
\n
"
)
output
=
bytes
.
TrimRight
(
output
,
"
\n
"
)
err
=
fmt
.
Errorf
(
"%v: %s"
,
err
,
output
)
return
fmt
.
Errorf
(
"%v: %s"
,
err
,
output
)
}
}
return
return
err
}
}
return
nil
return
}
}
unmount_std.go
View file @
ae5da07e
...
@@ -7,12 +7,10 @@ import (
...
@@ -7,12 +7,10 @@ import (
"syscall"
"syscall"
)
)
func
unmount
(
dir
string
)
(
err
error
)
{
func
unmount
(
dir
string
)
error
{
err
=
syscall
.
Unmount
(
dir
,
0
)
if
err
:=
syscall
.
Unmount
(
dir
,
0
);
err
!=
nil
{
if
err
!=
nil
{
return
&
os
.
PathError
{
Op
:
"unmount"
,
Path
:
dir
,
Err
:
err
}
err
=
&
os
.
PathError
{
Op
:
"unmount"
,
Path
:
dir
,
Err
:
err
}
return
}
}
return
return
nil
}
}
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