Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
go-fuse
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Levin Zimmermann
go-fuse
Commits
ae2e1d5c
Commit
ae2e1d5c
authored
Apr 16, 2017
by
OneOfOne
Committed by
Han-Wen Nienhuys
Apr 20, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Flock implementation with test.
Fixes #134
parent
51b6e576
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
124 additions
and
13 deletions
+124
-13
fuse/api.go
fuse/api.go
+2
-0
fuse/defaultraw.go
fuse/defaultraw.go
+4
-0
fuse/lockingfs.go
fuse/lockingfs.go
+5
-0
fuse/nodefs/api.go
fuse/nodefs/api.go
+2
-0
fuse/nodefs/defaultfile.go
fuse/nodefs/defaultfile.go
+1
-0
fuse/nodefs/files.go
fuse/nodefs/files.go
+8
-0
fuse/nodefs/fsops.go
fuse/nodefs/fsops.go
+11
-0
fuse/nodefs/lockingfile.go
fuse/nodefs/lockingfile.go
+6
-0
fuse/test/flock_test.go
fuse/test/flock_test.go
+54
-0
fuse/test/loopback_test.go
fuse/test/loopback_test.go
+1
-0
fuse/types.go
fuse/types.go
+21
-13
fuse/upgrade.go
fuse/upgrade.go
+9
-0
No files found.
fuse/api.go
View file @
ae2e1d5c
...
@@ -123,6 +123,8 @@ type RawFileSystem interface {
...
@@ -123,6 +123,8 @@ type RawFileSystem interface {
Open
(
input
*
OpenIn
,
out
*
OpenOut
)
(
status
Status
)
Open
(
input
*
OpenIn
,
out
*
OpenOut
)
(
status
Status
)
Read
(
input
*
ReadIn
,
buf
[]
byte
)
(
ReadResult
,
Status
)
Read
(
input
*
ReadIn
,
buf
[]
byte
)
(
ReadResult
,
Status
)
Flock
(
input
*
FlockIn
,
flags
int
)
(
code
Status
)
Release
(
input
*
ReleaseIn
)
Release
(
input
*
ReleaseIn
)
Write
(
input
*
WriteIn
,
data
[]
byte
)
(
written
uint32
,
code
Status
)
Write
(
input
*
WriteIn
,
data
[]
byte
)
(
written
uint32
,
code
Status
)
Flush
(
input
*
FlushIn
)
Status
Flush
(
input
*
FlushIn
)
Status
...
...
fuse/defaultraw.go
View file @
ae2e1d5c
...
@@ -117,6 +117,10 @@ func (fs *defaultRawFileSystem) Read(input *ReadIn, buf []byte) (ReadResult, Sta
...
@@ -117,6 +117,10 @@ func (fs *defaultRawFileSystem) Read(input *ReadIn, buf []byte) (ReadResult, Sta
return
nil
,
ENOSYS
return
nil
,
ENOSYS
}
}
func
(
fs
*
defaultRawFileSystem
)
Flock
(
input
*
FlockIn
,
flags
int
)
Status
{
return
ENOSYS
}
func
(
fs
*
defaultRawFileSystem
)
Release
(
input
*
ReleaseIn
)
{
func
(
fs
*
defaultRawFileSystem
)
Release
(
input
*
ReleaseIn
)
{
}
}
...
...
fuse/lockingfs.go
View file @
ae2e1d5c
...
@@ -159,6 +159,11 @@ func (fs *lockingRawFileSystem) Read(input *ReadIn, buf []byte) (ReadResult, Sta
...
@@ -159,6 +159,11 @@ func (fs *lockingRawFileSystem) Read(input *ReadIn, buf []byte) (ReadResult, Sta
return
fs
.
RawFS
.
Read
(
input
,
buf
)
return
fs
.
RawFS
.
Read
(
input
,
buf
)
}
}
func
(
fs
*
lockingRawFileSystem
)
Flock
(
input
*
FlockIn
,
flags
int
)
Status
{
defer
fs
.
locked
()()
return
fs
.
RawFS
.
Flock
(
input
,
flags
)
}
func
(
fs
*
lockingRawFileSystem
)
Write
(
input
*
WriteIn
,
data
[]
byte
)
(
written
uint32
,
code
Status
)
{
func
(
fs
*
lockingRawFileSystem
)
Write
(
input
*
WriteIn
,
data
[]
byte
)
(
written
uint32
,
code
Status
)
{
defer
fs
.
locked
()()
defer
fs
.
locked
()()
return
fs
.
RawFS
.
Write
(
input
,
data
)
return
fs
.
RawFS
.
Write
(
input
,
data
)
...
...
fuse/nodefs/api.go
View file @
ae2e1d5c
...
@@ -130,6 +130,8 @@ type File interface {
...
@@ -130,6 +130,8 @@ type File interface {
Read
(
dest
[]
byte
,
off
int64
)
(
fuse
.
ReadResult
,
fuse
.
Status
)
Read
(
dest
[]
byte
,
off
int64
)
(
fuse
.
ReadResult
,
fuse
.
Status
)
Write
(
data
[]
byte
,
off
int64
)
(
written
uint32
,
code
fuse
.
Status
)
Write
(
data
[]
byte
,
off
int64
)
(
written
uint32
,
code
fuse
.
Status
)
Flock
(
flags
int
)
fuse
.
Status
// Flush is called for close() call on a file descriptor. In
// Flush is called for close() call on a file descriptor. In
// case of duplicated descriptor, it may be called more than
// case of duplicated descriptor, it may be called more than
// once for a file.
// once for a file.
...
...
fuse/nodefs/defaultfile.go
View file @
ae2e1d5c
...
@@ -37,6 +37,7 @@ func (f *defaultFile) Write(data []byte, off int64) (uint32, fuse.Status) {
...
@@ -37,6 +37,7 @@ func (f *defaultFile) Write(data []byte, off int64) (uint32, fuse.Status) {
return
0
,
fuse
.
ENOSYS
return
0
,
fuse
.
ENOSYS
}
}
func
(
f
*
defaultFile
)
Flock
(
flags
int
)
fuse
.
Status
{
return
fuse
.
ENOSYS
}
func
(
f
*
defaultFile
)
Flush
()
fuse
.
Status
{
func
(
f
*
defaultFile
)
Flush
()
fuse
.
Status
{
return
fuse
.
OK
return
fuse
.
OK
}
}
...
...
fuse/nodefs/files.go
View file @
ae2e1d5c
...
@@ -167,6 +167,14 @@ func (f *loopbackFile) Fsync(flags int) (code fuse.Status) {
...
@@ -167,6 +167,14 @@ func (f *loopbackFile) Fsync(flags int) (code fuse.Status) {
return
r
return
r
}
}
func
(
f
*
loopbackFile
)
Flock
(
flags
int
)
fuse
.
Status
{
f
.
lock
.
Lock
()
r
:=
fuse
.
ToStatus
(
syscall
.
Flock
(
int
(
f
.
File
.
Fd
()),
flags
))
f
.
lock
.
Unlock
()
return
r
}
func
(
f
*
loopbackFile
)
Truncate
(
size
uint64
)
fuse
.
Status
{
func
(
f
*
loopbackFile
)
Truncate
(
size
uint64
)
fuse
.
Status
{
f
.
lock
.
Lock
()
f
.
lock
.
Lock
()
r
:=
fuse
.
ToStatus
(
syscall
.
Ftruncate
(
int
(
f
.
File
.
Fd
()),
int64
(
size
)))
r
:=
fuse
.
ToStatus
(
syscall
.
Ftruncate
(
int
(
f
.
File
.
Fd
()),
int64
(
size
)))
...
...
fuse/nodefs/fsops.go
View file @
ae2e1d5c
...
@@ -455,6 +455,17 @@ func (c *rawBridge) Read(input *fuse.ReadIn, buf []byte) (fuse.ReadResult, fuse.
...
@@ -455,6 +455,17 @@ func (c *rawBridge) Read(input *fuse.ReadIn, buf []byte) (fuse.ReadResult, fuse.
return
node
.
Node
()
.
Read
(
f
,
buf
,
int64
(
input
.
Offset
),
&
input
.
Context
)
return
node
.
Node
()
.
Read
(
f
,
buf
,
int64
(
input
.
Offset
),
&
input
.
Context
)
}
}
func
(
c
*
rawBridge
)
Flock
(
input
*
fuse
.
FlockIn
,
flags
int
)
fuse
.
Status
{
node
:=
c
.
toInode
(
input
.
NodeId
)
opened
:=
node
.
mount
.
getOpenedFile
(
input
.
Fh
)
if
opened
!=
nil
{
return
opened
.
WithFlags
.
File
.
Flock
(
flags
)
}
return
fuse
.
EBADF
}
func
(
c
*
rawBridge
)
StatFs
(
header
*
fuse
.
InHeader
,
out
*
fuse
.
StatfsOut
)
fuse
.
Status
{
func
(
c
*
rawBridge
)
StatFs
(
header
*
fuse
.
InHeader
,
out
*
fuse
.
StatfsOut
)
fuse
.
Status
{
node
:=
c
.
toInode
(
header
.
NodeId
)
node
:=
c
.
toInode
(
header
.
NodeId
)
s
:=
node
.
Node
()
.
StatFs
()
s
:=
node
.
Node
()
.
StatFs
()
...
...
fuse/nodefs/lockingfile.go
View file @
ae2e1d5c
...
@@ -54,6 +54,12 @@ func (f *lockingFile) Flush() fuse.Status {
...
@@ -54,6 +54,12 @@ func (f *lockingFile) Flush() fuse.Status {
return
f
.
file
.
Flush
()
return
f
.
file
.
Flush
()
}
}
func
(
f
*
lockingFile
)
Flock
(
flags
int
)
fuse
.
Status
{
f
.
mu
.
Lock
()
defer
f
.
mu
.
Unlock
()
return
f
.
file
.
Flock
(
flags
)
}
func
(
f
*
lockingFile
)
Release
()
{
func
(
f
*
lockingFile
)
Release
()
{
f
.
mu
.
Lock
()
f
.
mu
.
Lock
()
defer
f
.
mu
.
Unlock
()
defer
f
.
mu
.
Unlock
()
...
...
fuse/test/flock_test.go
0 → 100644
View file @
ae2e1d5c
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build linux
package
test
import
(
"bytes"
"os"
"os/exec"
"syscall"
"testing"
)
func
TestFlock
(
t
*
testing
.
T
)
{
cmd
,
err
:=
exec
.
LookPath
(
"flock"
)
if
err
!=
nil
{
t
.
Skip
(
"flock command not found."
)
}
tc
:=
NewTestCase
(
t
)
defer
tc
.
Cleanup
()
contents
:=
[]
byte
{
1
,
2
,
3
}
tc
.
WriteFile
(
tc
.
origFile
,
[]
byte
(
contents
),
0700
)
f
,
err
:=
os
.
OpenFile
(
tc
.
mountFile
,
os
.
O_WRONLY
,
0
)
if
err
!=
nil
{
t
.
Fatalf
(
"OpenFile(%q): %v"
,
tc
.
mountFile
,
err
)
}
defer
f
.
Close
()
if
err
=
syscall
.
Flock
(
int
(
f
.
Fd
()),
syscall
.
LOCK_EX
);
err
!=
nil
{
t
.
Errorf
(
"Flock returned: %v"
,
err
)
return
}
if
out
,
err
:=
runExternalFlock
(
cmd
,
tc
.
mountFile
);
!
bytes
.
Contains
(
out
,
[]
byte
(
"failed to get lock"
))
{
t
.
Errorf
(
"runExternalFlock(%q): %s (%v)"
,
tc
.
mountFile
,
out
,
err
)
}
}
func
runExternalFlock
(
flockPath
,
fname
string
)
([]
byte
,
error
)
{
f
,
err
:=
os
.
OpenFile
(
fname
,
os
.
O_WRONLY
,
0
)
if
err
!=
nil
{
return
nil
,
err
}
defer
f
.
Close
()
cmd
:=
exec
.
Command
(
flockPath
,
"--verbose"
,
"--exclusive"
,
"--nonblock"
,
"3"
)
cmd
.
Env
=
append
(
cmd
.
Env
,
"LC_ALL=C"
)
// in case the user's shell language is different
cmd
.
ExtraFiles
=
[]
*
os
.
File
{
f
}
return
cmd
.
CombinedOutput
()
}
fuse/test/loopback_test.go
View file @
ae2e1d5c
...
@@ -510,6 +510,7 @@ func TestAccess(t *testing.T) {
...
@@ -510,6 +510,7 @@ func TestAccess(t *testing.T) {
contents
:=
[]
byte
{
1
,
2
,
3
}
contents
:=
[]
byte
{
1
,
2
,
3
}
tc
.
WriteFile
(
tc
.
origFile
,
[]
byte
(
contents
),
0700
)
tc
.
WriteFile
(
tc
.
origFile
,
[]
byte
(
contents
),
0700
)
if
err
:=
os
.
Chmod
(
tc
.
origFile
,
0
);
err
!=
nil
{
if
err
:=
os
.
Chmod
(
tc
.
origFile
,
0
);
err
!=
nil
{
t
.
Fatalf
(
"Chmod failed: %v"
,
err
)
t
.
Fatalf
(
"Chmod failed: %v"
,
err
)
}
}
...
...
fuse/types.go
View file @
ae2e1d5c
...
@@ -18,25 +18,28 @@ const (
...
@@ -18,25 +18,28 @@ const (
type
Status
int32
type
Status
int32
const
(
const
(
OK
=
Status
(
0
)
OK
=
Status
(
0
)
// EACCESS Permission denied
// EACCESS Permission denied
EACCES
=
Status
(
syscall
.
EACCES
)
EACCES
=
Status
(
syscall
.
EACCES
)
// EBUSY Device or resource busy
// EBUSY Device or resource busy
EBUSY
=
Status
(
syscall
.
EBUSY
)
EBUSY
=
Status
(
syscall
.
EBUSY
)
// EAGAIN Resource temporarily unavailable
EAGAIN
=
Status
(
syscall
.
EAGAIN
)
// EINVAL Invalid argument
// EINVAL Invalid argument
EINVAL
=
Status
(
syscall
.
EINVAL
)
EINVAL
=
Status
(
syscall
.
EINVAL
)
// EIO I/O error
// EIO I/O error
EIO
=
Status
(
syscall
.
EIO
)
EIO
=
Status
(
syscall
.
EIO
)
// ENOENT No such file or directory
// ENOENT No such file or directory
ENOENT
=
Status
(
syscall
.
ENOENT
)
ENOENT
=
Status
(
syscall
.
ENOENT
)
// ENOSYS Function not implemented
// ENOSYS Function not implemented
ENOSYS
=
Status
(
syscall
.
ENOSYS
)
ENOSYS
=
Status
(
syscall
.
ENOSYS
)
// ENODATA No data available
// ENODATA No data available
ENODATA
=
Status
(
syscall
.
ENODATA
)
ENODATA
=
Status
(
syscall
.
ENODATA
)
...
@@ -45,22 +48,22 @@ const (
...
@@ -45,22 +48,22 @@ const (
ENOTDIR
=
Status
(
syscall
.
ENOTDIR
)
ENOTDIR
=
Status
(
syscall
.
ENOTDIR
)
// EPERM Operation not permitted
// EPERM Operation not permitted
EPERM
=
Status
(
syscall
.
EPERM
)
EPERM
=
Status
(
syscall
.
EPERM
)
// ERANGE Math result not representable
// ERANGE Math result not representable
ERANGE
=
Status
(
syscall
.
ERANGE
)
ERANGE
=
Status
(
syscall
.
ERANGE
)
// EXDEV Cross-device link
// EXDEV Cross-device link
EXDEV
=
Status
(
syscall
.
EXDEV
)
EXDEV
=
Status
(
syscall
.
EXDEV
)
// EBADF Bad file number
// EBADF Bad file number
EBADF
=
Status
(
syscall
.
EBADF
)
EBADF
=
Status
(
syscall
.
EBADF
)
// ENODEV No such device
// ENODEV No such device
ENODEV
=
Status
(
syscall
.
ENODEV
)
ENODEV
=
Status
(
syscall
.
ENODEV
)
// EROFS Read-only file system
// EROFS Read-only file system
EROFS
=
Status
(
syscall
.
EROFS
)
EROFS
=
Status
(
syscall
.
EROFS
)
)
)
type
ForgetIn
struct
{
type
ForgetIn
struct
{
...
@@ -462,3 +465,8 @@ type FallocateIn struct {
...
@@ -462,3 +465,8 @@ type FallocateIn struct {
Mode
uint32
Mode
uint32
Padding
uint32
Padding
uint32
}
}
type
FlockIn
struct
{
InHeader
Fh
uint64
}
fuse/upgrade.go
View file @
ae2e1d5c
...
@@ -244,6 +244,15 @@ func (fs *wrappingFS) Read(input *ReadIn, buf []byte) (ReadResult, Status) {
...
@@ -244,6 +244,15 @@ func (fs *wrappingFS) Read(input *ReadIn, buf []byte) (ReadResult, Status) {
return
nil
,
ENOSYS
return
nil
,
ENOSYS
}
}
func
(
fs
*
wrappingFS
)
Flock
(
input
*
FlockIn
,
flags
int
)
Status
{
if
s
,
ok
:=
fs
.
fs
.
(
interface
{
Flock
(
input
*
FlockIn
,
flags
int
)
Status
});
ok
{
return
s
.
Flock
(
input
,
flags
)
}
return
ENOSYS
}
func
(
fs
*
wrappingFS
)
Release
(
input
*
ReleaseIn
)
{
func
(
fs
*
wrappingFS
)
Release
(
input
*
ReleaseIn
)
{
if
s
,
ok
:=
fs
.
fs
.
(
interface
{
if
s
,
ok
:=
fs
.
fs
.
(
interface
{
Release
(
input
*
ReleaseIn
)
Release
(
input
*
ReleaseIn
)
...
...
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