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
f6e2ba95
Commit
f6e2ba95
authored
Mar 10, 2011
by
Han-Wen Nienhuys
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix mount raciness.
parent
629a0d43
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
43 additions
and
20 deletions
+43
-20
fuse/loopback_test.go
fuse/loopback_test.go
+1
-1
fuse/pathfilesystem.go
fuse/pathfilesystem.go
+42
-19
No files found.
fuse/loopback_test.go
View file @
f6e2ba95
...
@@ -559,7 +559,7 @@ func TestRecursiveMount(t *testing.T) {
...
@@ -559,7 +559,7 @@ func TestRecursiveMount(t *testing.T) {
f
.
Close
()
f
.
Close
()
// The close takes some time to propagate through
log
.
Println
(
"Waiting for kernel to flush file-close to fuse..."
)
time
.
Sleep
(
1e9
)
time
.
Sleep
(
1e9
)
code
=
ts
.
connector
.
Unmount
(
"/mnt"
)
code
=
ts
.
connector
.
Unmount
(
"/mnt"
)
...
...
fuse/pathfilesystem.go
View file @
f6e2ba95
...
@@ -2,23 +2,33 @@ package fuse
...
@@ -2,23 +2,33 @@ package fuse
import
(
import
(
"bytes"
"bytes"
"sync"
"fmt"
"fmt"
"log"
"log"
"path"
"path"
"strings"
"strings"
"sync"
)
)
type
mountData
struct
{
type
mountData
struct
{
// If non-nil the file system mounted here.
// If non-nil the file system mounted here.
fs
PathFilesystem
fs
PathFilesystem
// Protects the variables below.
mutex
sync
.
RWMutex
// If yes, we are looking to unmount the mounted fs.
// If yes, we are looking to unmount the mounted fs.
unmountPending
bool
unmountPending
bool
openFiles
int
// Count files, dirs and mounts.
openDirs
int
openCount
int
subMounts
int
}
// TODO - should we call async or not? what is the goroutine creation
// overhead vs. lock acquisition.
func
(
me
*
mountData
)
incOpenCount
(
delta
int
)
{
me
.
mutex
.
Lock
()
defer
me
.
mutex
.
Unlock
()
me
.
openCount
+=
delta
}
}
func
newMount
(
fs
PathFilesystem
)
*
mountData
{
func
newMount
(
fs
PathFilesystem
)
*
mountData
{
...
@@ -66,12 +76,15 @@ func (me *inodeData) GetPath() (path string, mount *mountData) {
...
@@ -66,12 +76,15 @@ func (me *inodeData) GetPath() (path string, mount *mountData) {
if
inode
==
nil
{
if
inode
==
nil
{
panic
(
"did not find parent with mount"
)
panic
(
"did not find parent with mount"
)
}
}
fullPath
:=
strings
.
Join
(
components
[
j
:
],
"/"
)
mount
=
inode
.
mount
mount
=
inode
.
mount
mount
.
mutex
.
RLock
()
defer
mount
.
mutex
.
RUnlock
()
if
mount
.
unmountPending
{
if
mount
.
unmountPending
{
mount
=
nil
return
""
,
nil
}
}
fullPath
:=
strings
.
Join
(
components
[
j
:
],
"/"
)
return
fullPath
,
mount
return
fullPath
,
mount
}
}
...
@@ -193,6 +206,12 @@ func (me *PathFileSystemConnector) forgetUpdate(nodeId uint64, forgetCount int)
...
@@ -193,6 +206,12 @@ func (me *PathFileSystemConnector) forgetUpdate(nodeId uint64, forgetCount int)
data
,
ok
:=
me
.
inodePathMapByInode
[
nodeId
]
data
,
ok
:=
me
.
inodePathMapByInode
[
nodeId
]
if
ok
{
if
ok
{
data
.
LookupCount
-=
forgetCount
data
.
LookupCount
-=
forgetCount
if
data
.
mount
!=
nil
{
data
.
mount
.
mutex
.
RLock
()
defer
data
.
mount
.
mutex
.
RUnlock
()
}
if
data
.
LookupCount
<=
0
&&
data
.
RefCount
<=
0
&&
(
data
.
mount
==
nil
||
data
.
mount
.
unmountPending
)
{
if
data
.
LookupCount
<=
0
&&
data
.
RefCount
<=
0
&&
(
data
.
mount
==
nil
||
data
.
mount
.
unmountPending
)
{
me
.
inodePathMap
[
data
.
Key
()]
=
nil
,
false
me
.
inodePathMap
[
data
.
Key
()]
=
nil
,
false
}
}
...
@@ -344,11 +363,10 @@ func (me *PathFileSystemConnector) Mount(mountPoint string, fs PathFilesystem) S
...
@@ -344,11 +363,10 @@ func (me *PathFileSystemConnector) Mount(mountPoint string, fs PathFilesystem) S
log
.
Println
(
"Mount: "
,
fs
,
"on"
,
mountPoint
,
node
)
log
.
Println
(
"Mount: "
,
fs
,
"on"
,
mountPoint
,
node
)
}
}
// TODO - this is technically a race-condition?
node
.
mount
=
newMount
(
fs
)
node
.
mount
=
newMount
(
fs
)
if
node
.
Parent
!=
nil
{
if
node
.
Parent
!=
nil
{
_
,
parentMount
:=
node
.
Parent
.
GetPath
()
_
,
parentMount
:=
node
.
Parent
.
GetPath
()
parentMount
.
subMounts
++
parentMount
.
incOpenCount
(
1
)
}
}
return
OK
return
OK
...
@@ -365,7 +383,9 @@ func (me *PathFileSystemConnector) Unmount(path string) Status {
...
@@ -365,7 +383,9 @@ func (me *PathFileSystemConnector) Unmount(path string) Status {
panic
(
path
)
panic
(
path
)
}
}
if
mount
.
openFiles
+
mount
.
openDirs
+
mount
.
subMounts
>
0
{
mount
.
mutex
.
Lock
()
defer
mount
.
mutex
.
Unlock
()
if
mount
.
openCount
>
0
{
log
.
Println
(
"busy: "
,
mount
)
log
.
Println
(
"busy: "
,
mount
)
return
EBUSY
return
EBUSY
}
}
...
@@ -373,7 +393,7 @@ func (me *PathFileSystemConnector) Unmount(path string) Status {
...
@@ -373,7 +393,7 @@ func (me *PathFileSystemConnector) Unmount(path string) Status {
if
me
.
Debug
{
if
me
.
Debug
{
log
.
Println
(
"Unmount: "
,
mount
)
log
.
Println
(
"Unmount: "
,
mount
)
}
}
// node manipulations are racy?
if
node
.
RefCount
>
0
{
if
node
.
RefCount
>
0
{
mount
.
fs
.
Unmount
()
mount
.
fs
.
Unmount
()
mount
.
unmountPending
=
true
mount
.
unmountPending
=
true
...
@@ -383,7 +403,7 @@ func (me *PathFileSystemConnector) Unmount(path string) Status {
...
@@ -383,7 +403,7 @@ func (me *PathFileSystemConnector) Unmount(path string) Status {
if
node
.
Parent
!=
nil
{
if
node
.
Parent
!=
nil
{
_
,
parentMount
:=
node
.
Parent
.
GetPath
()
_
,
parentMount
:=
node
.
Parent
.
GetPath
()
parentMount
.
subMounts
--
parentMount
.
incOpenCount
(
-
1
)
}
}
return
OK
return
OK
}
}
...
@@ -476,8 +496,7 @@ func (me *PathFileSystemConnector) OpenDir(header *InHeader, input *OpenIn) (fla
...
@@ -476,8 +496,7 @@ func (me *PathFileSystemConnector) OpenDir(header *InHeader, input *OpenIn) (fla
return
0
,
nil
,
err
return
0
,
nil
,
err
}
}
// TODO - racy?
mount
.
incOpenCount
(
1
)
mount
.
openDirs
++
de
:=
new
(
FuseDir
)
de
:=
new
(
FuseDir
)
de
.
connector
=
me
de
.
connector
=
me
...
@@ -497,8 +516,7 @@ func (me *PathFileSystemConnector) Open(header *InHeader, input *OpenIn) (flags
...
@@ -497,8 +516,7 @@ func (me *PathFileSystemConnector) Open(header *InHeader, input *OpenIn) (flags
return
0
,
nil
,
err
return
0
,
nil
,
err
}
}
// TODO - racy?
mount
.
incOpenCount
(
1
)
mount
.
openFiles
++
return
0
,
f
,
OK
return
0
,
f
,
OK
}
}
...
@@ -678,19 +696,24 @@ func (me *PathFileSystemConnector) Create(header *InHeader, input *CreateIn, nam
...
@@ -678,19 +696,24 @@ func (me *PathFileSystemConnector) Create(header *InHeader, input *CreateIn, nam
return
0
,
nil
,
nil
,
err
return
0
,
nil
,
nil
,
err
}
}
mount
.
openFiles
++
mount
.
incOpenCount
(
1
)
out
,
code
=
me
.
Lookup
(
header
,
name
)
out
,
code
=
me
.
Lookup
(
header
,
name
)
return
0
,
f
,
out
,
code
return
0
,
f
,
out
,
code
}
}
func
(
me
*
PathFileSystemConnector
)
Release
(
header
*
InHeader
,
f
RawFuseFile
)
{
func
(
me
*
PathFileSystemConnector
)
Release
(
header
*
InHeader
,
f
RawFuseFile
)
{
_
,
mount
:=
me
.
GetPath
(
header
.
NodeId
)
_
,
mount
:=
me
.
GetPath
(
header
.
NodeId
)
mount
.
openFiles
--
if
mount
!=
nil
{
mount
.
incOpenCount
(
-
1
)
}
}
}
func
(
me
*
PathFileSystemConnector
)
ReleaseDir
(
header
*
InHeader
,
f
RawFuseDir
)
{
func
(
me
*
PathFileSystemConnector
)
ReleaseDir
(
header
*
InHeader
,
f
RawFuseDir
)
{
_
,
mount
:=
me
.
GetPath
(
header
.
NodeId
)
_
,
mount
:=
me
.
GetPath
(
header
.
NodeId
)
mount
.
openDirs
--
if
mount
!=
nil
{
mount
.
incOpenCount
(
-
1
)
}
}
}
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
...
...
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