Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
go-fuse
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
go-fuse
Commits
04f7c3eb
Commit
04f7c3eb
authored
Oct 26, 2011
by
Han-Wen Nienhuys
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement and test MemUnionFs.Reset()
parent
0c055e17
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
159 additions
and
8 deletions
+159
-8
unionfs/memunionfs.go
unionfs/memunionfs.go
+59
-8
unionfs/memunionfs_test.go
unionfs/memunionfs_test.go
+100
-0
No files found.
unionfs/memunionfs.go
View file @
04f7c3eb
...
...
@@ -17,15 +17,14 @@ var _ = log.Println
// A unionfs that only uses on-disk backing store for file contents.
type
MemUnionFs
struct
{
fuse
.
DefaultNodeFileSystem
readonly
fuse
.
FileSystem
backingStore
string
root
*
memNode
connector
*
fuse
.
FileSystemConnector
mutex
sync
.
RWMutex
root
*
memNode
cond
*
sync
.
Cond
nextFree
int
readonly
fuse
.
FileSystem
openWritable
int
// All paths that have been renamed or deleted will be marked
...
...
@@ -65,6 +64,25 @@ func (me *MemUnionFs) release() {
me
.
cond
.
Broadcast
()
}
// Reset drops the state of the filesystem back its original.
func
(
me
*
MemUnionFs
)
Reset
()
{
me
.
mutex
.
Lock
()
defer
me
.
mutex
.
Unlock
()
me
.
root
.
reset
(
""
)
for
path
,
_
:=
range
me
.
deleted
{
parent
,
base
:=
filepath
.
Split
(
path
)
parent
=
stripSlash
(
parent
)
last
,
rest
:=
me
.
connector
.
Node
(
me
.
root
.
Inode
(),
parent
)
if
len
(
rest
)
==
0
{
me
.
connector
.
EntryNotify
(
last
,
base
)
}
}
me
.
deleted
=
make
(
map
[
string
]
bool
,
len
(
me
.
deleted
))
me
.
clearBackingStore
()
}
func
(
me
*
MemUnionFs
)
Reap
()
map
[
string
]
*
Result
{
me
.
mutex
.
Lock
()
defer
me
.
mutex
.
Unlock
()
...
...
@@ -110,7 +128,11 @@ func (me *MemUnionFs) Clear() {
me
.
mutex
.
Lock
()
defer
me
.
mutex
.
Unlock
()
me
.
deleted
=
make
(
map
[
string
]
bool
)
me
.
root
.
Clear
(
""
)
me
.
root
.
clear
(
""
)
me
.
clearBackingStore
()
}
func
(
me
*
MemUnionFs
)
clearBackingStore
()
{
f
,
err
:=
os
.
Open
(
me
.
backingStore
)
if
err
!=
nil
{
return
...
...
@@ -263,7 +285,6 @@ func (me *memNode) lookup(name string, context *fuse.Context) (fi *os.FileInfo,
if
_
,
del
:=
me
.
fs
.
deleted
[
fn
];
del
{
return
nil
,
nil
,
fuse
.
ENOENT
}
fi
,
code
=
me
.
fs
.
readonly
.
GetAttr
(
fn
,
context
)
if
!
code
.
Ok
()
{
return
nil
,
nil
,
code
...
...
@@ -613,13 +634,43 @@ func (me *memNode) Reap(path string, results map[string]*Result) {
}
}
func
(
me
*
memNode
)
C
lear
(
path
string
)
{
func
(
me
*
memNode
)
c
lear
(
path
string
)
{
me
.
original
=
path
me
.
changed
=
false
me
.
backing
=
""
for
n
,
ch
:=
range
me
.
Inode
()
.
FsChildren
()
{
p
:=
filepath
.
Join
(
path
,
n
)
mn
:=
ch
.
FsNode
()
.
(
*
memNode
)
mn
.
C
lear
(
p
)
mn
.
c
lear
(
p
)
}
}
func
(
me
*
memNode
)
reset
(
path
string
)
(
entryNotify
bool
)
{
for
n
,
ch
:=
range
me
.
Inode
()
.
FsChildren
()
{
p
:=
filepath
.
Join
(
path
,
n
)
mn
:=
ch
.
FsNode
()
.
(
*
memNode
)
if
mn
.
reset
(
p
)
{
me
.
Inode
()
.
RmChild
(
n
)
me
.
fs
.
connector
.
EntryNotify
(
me
.
Inode
(),
n
)
}
}
if
me
.
backing
!=
""
||
me
.
original
!=
path
{
return
true
}
if
me
.
changed
{
info
,
code
:=
me
.
fs
.
readonly
.
GetAttr
(
me
.
original
,
nil
)
if
!
code
.
Ok
()
{
return
true
}
me
.
info
=
*
info
me
.
fs
.
connector
.
FileNotify
(
me
.
Inode
(),
-
1
,
0
)
if
me
.
Inode
()
.
IsDir
()
{
me
.
fs
.
connector
.
FileNotify
(
me
.
Inode
(),
0
,
0
)
}
}
return
false
}
unionfs/memunionfs_test.go
View file @
04f7c3eb
...
...
@@ -41,6 +41,7 @@ func setupMemUfs(t *testing.T) (workdir string, ufs *MemUnionFs, cleanup func())
EntryTimeout
:
.5
*
entryTtl
,
AttrTimeout
:
.5
*
entryTtl
,
NegativeTimeout
:
.5
*
entryTtl
,
PortableInodes
:
true
,
}
state
,
conn
,
err
:=
fuse
.
MountNodeFileSystem
(
wd
+
"/mnt"
,
memFs
,
opts
)
...
...
@@ -805,3 +806,102 @@ func TestMemUnionGc(t *testing.T) {
t
.
Fatalf
(
"should have 1 file after backing store gc: %v"
,
entries
)
}
}
func
testEq
(
t
*
testing
.
T
,
got
interface
{},
want
interface
{},
expectEq
bool
)
{
gots
:=
fmt
.
Sprintf
(
"%v"
,
got
)
wants
:=
fmt
.
Sprintf
(
"%v"
,
want
)
if
(
gots
==
wants
)
!=
expectEq
{
op
:=
"must differ from"
if
expectEq
{
op
=
"want"
}
t
.
Fatalf
(
"Got %s %s %s."
,
gots
,
op
,
wants
)
}
}
func
TestMemUnionResetAttr
(
t
*
testing
.
T
)
{
wd
,
ufs
,
clean
:=
setupMemUfs
(
t
)
defer
clean
()
ioutil
.
WriteFile
(
wd
+
"/ro/fileattr"
,
[]
byte
{
42
},
0644
)
before
,
_
:=
os
.
Lstat
(
wd
+
"/mnt/fileattr"
)
err
:=
os
.
Chmod
(
wd
+
"/mnt/fileattr"
,
0606
)
CheckSuccess
(
err
)
after
,
_
:=
os
.
Lstat
(
wd
+
"/mnt/fileattr"
)
testEq
(
t
,
after
,
before
,
false
)
ufs
.
Reset
()
afterReset
,
_
:=
os
.
Lstat
(
wd
+
"/mnt/fileattr"
)
testEq
(
t
,
afterReset
,
before
,
true
)
}
func
TestMemUnionResetContent
(
t
*
testing
.
T
)
{
wd
,
ufs
,
clean
:=
setupMemUfs
(
t
)
defer
clean
()
ioutil
.
WriteFile
(
wd
+
"/ro/filecontents"
,
[]
byte
{
42
},
0644
)
before
,
_
:=
ioutil
.
ReadFile
(
wd
+
"/mnt/filecontents"
)
ioutil
.
WriteFile
(
wd
+
"/mnt/filecontents"
,
[]
byte
{
43
},
0644
)
after
,
_
:=
ioutil
.
ReadFile
(
wd
+
"/mnt/filecontents"
)
testEq
(
t
,
after
,
before
,
false
)
ufs
.
Reset
()
afterReset
,
err
:=
ioutil
.
ReadFile
(
wd
+
"/mnt/filecontents"
)
CheckSuccess
(
err
)
testEq
(
t
,
afterReset
,
before
,
true
)
}
func
TestMemUnionResetDelete
(
t
*
testing
.
T
)
{
wd
,
ufs
,
clean
:=
setupMemUfs
(
t
)
defer
clean
()
ioutil
.
WriteFile
(
wd
+
"/ro/todelete"
,
[]
byte
{
42
},
0644
)
before
,
_
:=
os
.
Lstat
(
wd
+
"/mnt/todelete"
)
before
.
Ino
=
0
os
.
Remove
(
wd
+
"/mnt/todelete"
)
after
,
_
:=
os
.
Lstat
(
wd
+
"/mnt/todelete"
)
testEq
(
t
,
after
,
before
,
false
)
ufs
.
Reset
()
afterReset
,
_
:=
os
.
Lstat
(
wd
+
"/mnt/todelete"
)
afterReset
.
Ino
=
0
testEq
(
t
,
afterReset
,
before
,
true
)
}
func
clearInodes
(
infos
[]
*
os
.
FileInfo
)
{
for
_
,
i
:=
range
infos
{
i
.
Ino
=
0
}
}
func
TestMemUnionResetDirEntry
(
t
*
testing
.
T
)
{
wd
,
ufs
,
clean
:=
setupMemUfs
(
t
)
defer
clean
()
os
.
Mkdir
(
wd
+
"/ro/dir"
,
0755
)
ioutil
.
WriteFile
(
wd
+
"/ro/dir/todelete"
,
[]
byte
{
42
},
0644
)
before
,
_
:=
ioutil
.
ReadDir
(
wd
+
"/mnt/dir"
)
clearInodes
(
before
)
ioutil
.
WriteFile
(
wd
+
"/mnt/dir/newfile"
,
[]
byte
{
42
},
0644
)
os
.
Remove
(
wd
+
"/mnt/dir/todelete"
)
after
,
_
:=
ioutil
.
ReadDir
(
wd
+
"/mnt/dir"
)
clearInodes
(
after
)
testEq
(
t
,
fuse
.
OsFileInfos
(
after
),
fuse
.
OsFileInfos
(
before
),
false
)
ufs
.
Reset
()
log
.
Println
(
"reseT"
)
reset
,
_
:=
ioutil
.
ReadDir
(
wd
+
"/mnt/dir"
)
clearInodes
(
reset
)
testEq
(
t
,
fuse
.
OsFileInfos
(
reset
),
fuse
.
OsFileInfos
(
before
),
true
)
}
func
TestMemUnionResetRename
(
t
*
testing
.
T
)
{
wd
,
ufs
,
clean
:=
setupMemUfs
(
t
)
defer
clean
()
os
.
Mkdir
(
wd
+
"/ro/dir"
,
0755
)
ioutil
.
WriteFile
(
wd
+
"/ro/dir/movesrc"
,
[]
byte
{
42
},
0644
)
before
,
_
:=
ioutil
.
ReadDir
(
wd
+
"/mnt/dir"
)
clearInodes
(
before
)
os
.
Rename
(
wd
+
"/mnt/dir/movesrc"
,
wd
+
"/mnt/dir/dest"
)
after
,
_
:=
ioutil
.
ReadDir
(
wd
+
"/mnt/dir"
)
clearInodes
(
after
)
testEq
(
t
,
fuse
.
OsFileInfos
(
after
),
fuse
.
OsFileInfos
(
before
),
false
)
ufs
.
Reset
()
reset
,
_
:=
ioutil
.
ReadDir
(
wd
+
"/mnt/dir"
)
clearInodes
(
reset
)
testEq
(
t
,
fuse
.
OsFileInfos
(
reset
),
fuse
.
OsFileInfos
(
before
),
true
)
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment