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
39e0cbbb
Commit
39e0cbbb
authored
Mar 27, 2019
by
Kirill Smelkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
.
parent
a1e2414a
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
82 additions
and
32 deletions
+82
-32
fuse/api.go
fuse/api.go
+1
-1
fuse/nodefs/fuse.go
fuse/nodefs/fuse.go
+13
-9
fuse/opcode.go
fuse/opcode.go
+3
-0
fuse/print.go
fuse/print.go
+1
-0
fuse/test/cache_test.go
fuse/test/cache_test.go
+64
-22
No files found.
fuse/api.go
View file @
39e0cbbb
...
...
@@ -156,7 +156,7 @@ type MountOptions struct {
EnableLocks
bool
// If set, ask kernel not to do automatic data cache invalidation.
// The filesystem is fully reponsible for invalidating data cache.
// The filesystem is fully re
s
ponsible for invalidating data cache.
PreciseDataCacheControl
bool
}
...
...
fuse/nodefs/fuse.go
View file @
39e0cbbb
...
...
@@ -8,18 +8,22 @@ import (
"github.com/hanwen/go-fuse/fuse"
)
// Mount
Root
mounts a filesystem with the given root node on the given directory.
// Mount mounts a filesystem with the given root node on the given directory.
// Convenience wrapper around fuse.NewServer
func
MountRoot
(
mountpoint
string
,
root
Node
,
opts
*
Options
)
(
*
fuse
.
Server
,
*
FileSystemConnector
,
error
)
{
conn
:=
NewFileSystemConnector
(
root
,
opts
)
mountOpts
:=
fuse
.
MountOptions
{}
if
opts
!=
nil
&&
opts
.
Debug
{
mountOpts
.
Debug
=
opts
.
Debug
}
s
,
err
:=
fuse
.
NewServer
(
conn
.
RawFS
(),
mountpoint
,
&
mountOpts
)
func
Mount
(
mountpoint
string
,
root
Node
,
mountOptions
*
fuse
.
MountOptions
,
nodefsOptions
*
Options
)
(
*
fuse
.
Server
,
*
FileSystemConnector
,
error
)
{
conn
:=
NewFileSystemConnector
(
root
,
nodefsOptions
)
s
,
err
:=
fuse
.
NewServer
(
conn
.
RawFS
(),
mountpoint
,
mountOptions
)
if
err
!=
nil
{
return
nil
,
nil
,
err
}
return
s
,
conn
,
nil
}
// MountRoot is like Mount but uses default fuse mount options.
func
MountRoot
(
mountpoint
string
,
root
Node
,
opts
*
Options
)
(
*
fuse
.
Server
,
*
FileSystemConnector
,
error
)
{
mountOpts
:=
&
fuse
.
MountOptions
{}
if
opts
!=
nil
&&
opts
.
Debug
{
mountOpts
.
Debug
=
opts
.
Debug
}
return
Mount
(
mountpoint
,
root
,
mountOpts
,
opts
)
}
fuse/opcode.go
View file @
39e0cbbb
...
...
@@ -103,6 +103,9 @@ func doInit(server *Server, req *request) {
dataCacheMode
:=
input
.
Flags
&
CAP_AUTO_INVAL_DATA
if
server
.
opts
.
PreciseDataCacheControl
{
// we don't want CAP_AUTO_INVAL_DATA even if we cannot go into fully precise mode
dataCacheMode
=
0
precise
:=
input
.
Flags
&
CAP_PRECISE_INVAL_DATA
if
precise
!=
0
{
dataCacheMode
=
precise
...
...
fuse/print.go
View file @
39e0cbbb
...
...
@@ -47,6 +47,7 @@ var (
CAP_MAX_PAGES
:
"MAX_PAGES"
,
CAP_CACHE_SYMLINKS
:
"CACHE_SYMLINKS"
,
CAP_NO_OPENDIR_SUPPORT
:
"NO_OPENDIR_SUPPORT"
,
CAP_PRECISE_INVAL_DATA
:
"PRECISE_INVAL_DATA"
,
}
releaseFlagNames
=
map
[
int64
]
string
{
RELEASE_FLUSH
:
"FLUSH"
,
...
...
fuse/test/cache_test.go
View file @
39e0cbbb
...
...
@@ -6,11 +6,13 @@ package test
import
(
"bytes"
"fmt"
"io/ioutil"
"os"
"runtime"
"sync"
"testing"
"time"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
...
...
@@ -44,9 +46,17 @@ func setupCacheTest(t *testing.T) (string, *pathfs.PathNodeFs, func()) {
}
pfs
:=
pathfs
.
NewPathNodeFs
(
fs
,
&
pathfs
.
PathNodeFsOptions
{
Debug
:
testutil
.
VerboseTest
()})
mntOpts
:=
&
fuse
.
MountOptions
{
// ask kernel not to invalidate file data automatically
PreciseDataCacheControl
:
true
,
Debug
:
testutil
.
VerboseTest
(),
}
opts
:=
nodefs
.
NewOptions
()
opts
.
AttrTimeout
=
10
*
time
.
Millisecond
opts
.
Debug
=
testutil
.
VerboseTest
()
state
,
_
,
err
:=
nodefs
.
Mount
Root
(
dir
+
"/mnt"
,
pfs
.
Root
()
,
opts
)
state
,
_
,
err
:=
nodefs
.
Mount
(
dir
+
"/mnt"
,
pfs
.
Root
(),
mntOpts
,
opts
)
if
err
!=
nil
{
t
.
Fatalf
(
"MountNodeFileSystem failed: %v"
,
err
)
}
...
...
@@ -67,34 +77,68 @@ func TestFopenKeepCache(t *testing.T) {
t
.
Skip
(
"FOPEN_KEEP_CACHE is broken on Darwin."
)
}
// Failing on 4.20.5-200.fc29.x86_64.
// reported as https://github.com/libfuse/libfuse/issues/362
t
.
Skip
(
"started failing on linux"
)
wd
,
pathfs
,
clean
:=
setupCacheTest
(
t
)
defer
clean
()
// x{read,write}File reads/writes file@path and fail on error
xreadFile
:=
func
(
path
string
)
string
{
data
,
err
:=
ioutil
.
ReadFile
(
path
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
return
string
(
data
)
}
xwriteFile
:=
func
(
path
,
data
string
)
{
if
err
:=
ioutil
.
WriteFile
(
path
,
[]
byte
(
data
),
0644
);
err
!=
nil
{
t
.
Fatal
(
err
)
}
}
// xstat stats path and fails on error
xstat
:=
func
(
path
string
)
os
.
FileInfo
{
st
,
err
:=
os
.
Stat
(
path
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
return
st
}
// XXX Linux FUSE client automatically invalidates cache of a file if it sees size change.
// As workaround we keep len(before) == len(after) to avoid that codepath.
// See https://github.com/hanwen/go-fuse/pull/273 for details.
//
// TODO use len(before) != len(after) if kernel supports precise control over data cache.
before
:=
"before"
after
:=
"after"
if
err
:=
ioutil
.
WriteFile
(
wd
+
"/orig/file.txt"
,
[]
byte
(
before
),
0644
);
err
!=
nil
{
t
.
Fatalf
(
"WriteFile failed: %v"
,
err
)
after
:=
"after
X
"
if
len
(
before
)
!=
len
(
after
)
{
panic
(
"len(before) != len(after)"
)
}
c
,
err
:=
ioutil
.
ReadFile
(
wd
+
"/mnt/file.txt"
)
if
err
!=
nil
{
t
.
Fatalf
(
"ReadFile: %v"
,
err
)
}
else
if
string
(
c
)
!=
before
{
xwriteFile
(
wd
+
"/orig/file.txt"
,
before
)
mtimeBefore
:=
xstat
(
wd
+
"/orig/file.txt"
)
.
ModTime
()
c
:=
xreadFile
(
wd
+
"/mnt/file.txt"
)
if
c
!=
before
{
t
.
Fatalf
(
"ReadFile: got %q, want %q"
,
c
,
before
)
}
if
err
:=
ioutil
.
WriteFile
(
wd
+
"/orig/file.txt"
,
[]
byte
(
after
),
0644
);
err
!=
nil
{
t
.
Fatalf
(
"WriteFile: %v"
,
err
)
// sleep a bit to make sure mtime of file for before and after are different
time
.
Sleep
(
20
*
time
.
Millisecond
)
xwriteFile
(
wd
+
"/orig/file.txt"
,
after
)
mtimeAfter
:=
xstat
(
wd
+
"/orig/file.txt"
)
.
ModTime
()
if
δ
:=
mtimeAfter
.
Sub
(
mtimeBefore
);
δ
==
0
{
panic
(
fmt
.
Sprintf
(
"mtime(orig/before) == mtime(orig/after)"
))
}
c
,
err
=
ioutil
.
ReadFile
(
wd
+
"/mnt/file.txt"
)
if
err
!=
nil
{
t
.
Fatalf
(
"ReadFile: %v"
,
err
)
}
else
if
string
(
c
)
!=
before
{
// sleep enough time for file attributes to expire; restat the file after.
// this forces kernel client to relookup/regetattr the file and reread the attributes.
//
// this way we make sure the kernel knows updated size/mtime before we
// try to read the file next time.
time
.
Sleep
(
100
*
time
.
Millisecond
)
_
=
xstat
(
wd
+
"/mnt/file.txt"
)
c
=
xreadFile
(
wd
+
"/mnt/file.txt"
)
if
c
!=
before
{
t
.
Fatalf
(
"ReadFile: got %q, want cached %q"
,
c
,
before
)
}
...
...
@@ -107,10 +151,8 @@ func TestFopenKeepCache(t *testing.T) {
t
.
Errorf
(
"EntryNotify: %v"
,
code
)
}
c
,
err
=
ioutil
.
ReadFile
(
wd
+
"/mnt/file.txt"
)
if
err
!=
nil
{
t
.
Fatalf
(
"ReadFile: %v"
,
err
)
}
else
if
string
(
c
)
!=
after
{
c
=
xreadFile
(
wd
+
"/mnt/file.txt"
)
if
c
!=
after
{
t
.
Fatalf
(
"ReadFile: got %q after notify, want %q"
,
c
,
after
)
}
}
...
...
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