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
6fad53e3
Commit
6fad53e3
authored
Mar 09, 2019
by
Han-Wen Nienhuys
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
nodefs: move open file administration into Inode
This is necessary to provide a file handle to GetAttr.
parent
e32d0aa0
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
46 additions
and
61 deletions
+46
-61
nodefs/bridge.go
nodefs/bridge.go
+39
-20
nodefs/inode.go
nodefs/inode.go
+6
-0
nodefs/loopback.go
nodefs/loopback.go
+1
-41
No files found.
nodefs/bridge.go
View file @
6fad53e3
...
@@ -7,6 +7,7 @@ package nodefs
...
@@ -7,6 +7,7 @@ package nodefs
import
(
import
(
"log"
"log"
"sync"
"sync"
"syscall"
"time"
"time"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse"
...
@@ -74,6 +75,7 @@ func (b *rawBridge) newInode(node Operations, mode uint32, id FileID, persistent
...
@@ -74,6 +75,7 @@ func (b *rawBridge) newInode(node Operations, mode uint32, id FileID, persistent
bridge
:
b
,
bridge
:
b
,
persistent
:
persistent
,
persistent
:
persistent
,
parents
:
make
(
map
[
parentData
]
struct
{}),
parents
:
make
(
map
[
parentData
]
struct
{}),
openFiles
:
make
(
map
[
FileHandle
]
uint32
),
}
}
if
mode
==
fuse
.
S_IFDIR
{
if
mode
==
fuse
.
S_IFDIR
{
inode
.
children
=
make
(
map
[
string
]
*
Inode
)
inode
.
children
=
make
(
map
[
string
]
*
Inode
)
...
@@ -141,7 +143,7 @@ func (b *rawBridge) Lookup(cancel <-chan struct{}, header *fuse.InHeader, name s
...
@@ -141,7 +143,7 @@ func (b *rawBridge) Lookup(cancel <-chan struct{}, header *fuse.InHeader, name s
return
status
return
status
}
}
b
.
addNewChild
(
parent
,
name
,
child
,
nil
,
out
)
b
.
addNewChild
(
parent
,
name
,
child
,
nil
,
0
,
out
)
b
.
setEntryOutTimeout
(
out
)
b
.
setEntryOutTimeout
(
out
)
out
.
Mode
=
child
.
mode
|
(
out
.
Mode
&
07777
)
out
.
Mode
=
child
.
mode
|
(
out
.
Mode
&
07777
)
...
@@ -179,7 +181,7 @@ func (b *rawBridge) Mkdir(cancel <-chan struct{}, input *fuse.MkdirIn, name stri
...
@@ -179,7 +181,7 @@ func (b *rawBridge) Mkdir(cancel <-chan struct{}, input *fuse.MkdirIn, name stri
log
.
Panicf
(
"Mkdir: mode must be S_IFDIR (%o), got %o"
,
fuse
.
S_IFDIR
,
out
.
Attr
.
Mode
)
log
.
Panicf
(
"Mkdir: mode must be S_IFDIR (%o), got %o"
,
fuse
.
S_IFDIR
,
out
.
Attr
.
Mode
)
}
}
b
.
addNewChild
(
parent
,
name
,
child
,
nil
,
out
)
b
.
addNewChild
(
parent
,
name
,
child
,
nil
,
0
,
out
)
b
.
setEntryOutTimeout
(
out
)
b
.
setEntryOutTimeout
(
out
)
return
fuse
.
OK
return
fuse
.
OK
}
}
...
@@ -192,13 +194,13 @@ func (b *rawBridge) Mknod(cancel <-chan struct{}, input *fuse.MknodIn, name stri
...
@@ -192,13 +194,13 @@ func (b *rawBridge) Mknod(cancel <-chan struct{}, input *fuse.MknodIn, name stri
return
status
return
status
}
}
b
.
addNewChild
(
parent
,
name
,
child
,
nil
,
out
)
b
.
addNewChild
(
parent
,
name
,
child
,
nil
,
0
,
out
)
b
.
setEntryOutTimeout
(
out
)
b
.
setEntryOutTimeout
(
out
)
return
fuse
.
OK
return
fuse
.
OK
}
}
// addNewChild inserts the child into the tree. Returns file handle if file != nil.
// addNewChild inserts the child into the tree. Returns file handle if file != nil.
func
(
b
*
rawBridge
)
addNewChild
(
parent
*
Inode
,
name
string
,
child
*
Inode
,
file
FileHandle
,
out
*
fuse
.
EntryOut
)
uint64
{
func
(
b
*
rawBridge
)
addNewChild
(
parent
*
Inode
,
name
string
,
child
*
Inode
,
file
FileHandle
,
fileFlags
uint32
,
out
*
fuse
.
EntryOut
)
uint64
{
lockNodes
(
parent
,
child
)
lockNodes
(
parent
,
child
)
parent
.
setEntry
(
name
,
child
)
parent
.
setEntry
(
name
,
child
)
b
.
mu
.
Lock
()
b
.
mu
.
Lock
()
...
@@ -207,7 +209,7 @@ func (b *rawBridge) addNewChild(parent *Inode, name string, child *Inode, file F
...
@@ -207,7 +209,7 @@ func (b *rawBridge) addNewChild(parent *Inode, name string, child *Inode, file F
var
fh
uint64
var
fh
uint64
if
file
!=
nil
{
if
file
!=
nil
{
fh
=
b
.
registerFile
(
file
)
fh
=
b
.
registerFile
(
child
,
file
,
fileFlags
)
}
}
out
.
NodeId
=
child
.
nodeID
.
Ino
out
.
NodeId
=
child
.
nodeID
.
Ino
...
@@ -239,7 +241,7 @@ func (b *rawBridge) Create(cancel <-chan struct{}, input *fuse.CreateIn, name st
...
@@ -239,7 +241,7 @@ func (b *rawBridge) Create(cancel <-chan struct{}, input *fuse.CreateIn, name st
return
status
return
status
}
}
out
.
Fh
=
b
.
addNewChild
(
parent
,
name
,
child
,
f
,
&
out
.
EntryOut
)
out
.
Fh
=
b
.
addNewChild
(
parent
,
name
,
child
,
f
,
input
.
Flags
|
syscall
.
O_CREAT
,
&
out
.
EntryOut
)
b
.
setEntryOutTimeout
(
&
out
.
EntryOut
)
b
.
setEntryOutTimeout
(
&
out
.
EntryOut
)
out
.
OpenFlags
=
flags
out
.
OpenFlags
=
flags
...
@@ -270,7 +272,16 @@ func (b *rawBridge) GetAttr(cancel <-chan struct{}, input *fuse.GetAttrIn, out *
...
@@ -270,7 +272,16 @@ func (b *rawBridge) GetAttr(cancel <-chan struct{}, input *fuse.GetAttrIn, out *
f
:=
fEntry
.
file
f
:=
fEntry
.
file
if
input
.
Flags
()
&
fuse
.
FUSE_GETATTR_FH
==
0
{
if
input
.
Flags
()
&
fuse
.
FUSE_GETATTR_FH
==
0
{
f
=
nil
// The linux kernel doesnt pass along the file
// descriptor, so we have to fake it here.
// See https://github.com/libfuse/libfuse/issues/62
b
.
mu
.
Lock
()
// TODO: synchronize to avoid closing F while GetAttr runs.
for
openF
:=
range
n
.
openFiles
{
f
=
openF
break
}
b
.
mu
.
Unlock
()
}
}
status
:=
n
.
node
.
GetAttr
(
&
fuse
.
Context
{
Caller
:
input
.
Caller
,
Cancel
:
cancel
},
f
,
out
)
status
:=
n
.
node
.
GetAttr
(
&
fuse
.
Context
{
Caller
:
input
.
Caller
,
Cancel
:
cancel
},
f
,
out
)
...
@@ -380,7 +391,7 @@ func (b *rawBridge) Link(cancel <-chan struct{}, input *fuse.LinkIn, name string
...
@@ -380,7 +391,7 @@ func (b *rawBridge) Link(cancel <-chan struct{}, input *fuse.LinkIn, name string
return
status
return
status
}
}
b
.
addNewChild
(
parent
,
name
,
child
,
nil
,
out
)
b
.
addNewChild
(
parent
,
name
,
child
,
nil
,
0
,
out
)
b
.
setEntryOutTimeout
(
out
)
b
.
setEntryOutTimeout
(
out
)
return
fuse
.
OK
return
fuse
.
OK
}
}
...
@@ -392,7 +403,7 @@ func (b *rawBridge) Symlink(cancel <-chan struct{}, header *fuse.InHeader, targe
...
@@ -392,7 +403,7 @@ func (b *rawBridge) Symlink(cancel <-chan struct{}, header *fuse.InHeader, targe
return
status
return
status
}
}
b
.
addNewChild
(
parent
,
name
,
child
,
nil
,
out
)
b
.
addNewChild
(
parent
,
name
,
child
,
nil
,
0
,
out
)
b
.
setEntryOutTimeout
(
out
)
b
.
setEntryOutTimeout
(
out
)
return
fuse
.
OK
return
fuse
.
OK
}
}
...
@@ -445,13 +456,13 @@ func (b *rawBridge) Open(cancel <-chan struct{}, input *fuse.OpenIn, out *fuse.O
...
@@ -445,13 +456,13 @@ func (b *rawBridge) Open(cancel <-chan struct{}, input *fuse.OpenIn, out *fuse.O
b
.
mu
.
Lock
()
b
.
mu
.
Lock
()
defer
b
.
mu
.
Unlock
()
defer
b
.
mu
.
Unlock
()
out
.
Fh
=
b
.
registerFile
(
f
)
out
.
Fh
=
b
.
registerFile
(
n
,
f
,
input
.
Flags
)
out
.
OpenFlags
=
flags
out
.
OpenFlags
=
flags
return
fuse
.
OK
return
fuse
.
OK
}
}
// registerFile hands out a file handle. Must have bridge.mu
// registerFile hands out a file handle. Must have bridge.mu
func
(
b
*
rawBridge
)
registerFile
(
f
FileHandle
)
uint64
{
func
(
b
*
rawBridge
)
registerFile
(
n
*
Inode
,
f
FileHandle
,
flags
uint32
)
uint64
{
var
fh
uint64
var
fh
uint64
if
len
(
b
.
freeFiles
)
>
0
{
if
len
(
b
.
freeFiles
)
>
0
{
last
:=
uint64
(
len
(
b
.
freeFiles
)
-
1
)
last
:=
uint64
(
len
(
b
.
freeFiles
)
-
1
)
...
@@ -461,8 +472,10 @@ func (b *rawBridge) registerFile(f FileHandle) uint64 {
...
@@ -461,8 +472,10 @@ func (b *rawBridge) registerFile(f FileHandle) uint64 {
fh
=
uint64
(
len
(
b
.
files
))
fh
=
uint64
(
len
(
b
.
files
))
b
.
files
=
append
(
b
.
files
,
&
fileEntry
{})
b
.
files
=
append
(
b
.
files
,
&
fileEntry
{})
}
}
if
f
!=
nil
{
n
.
openFiles
[
f
]
=
flags
b
.
files
[
fh
]
.
file
=
f
b
.
files
[
fh
]
.
file
=
f
}
return
fh
return
fh
}
}
...
@@ -490,23 +503,29 @@ func (b *rawBridge) Release(input *fuse.ReleaseIn) {
...
@@ -490,23 +503,29 @@ func (b *rawBridge) Release(input *fuse.ReleaseIn) {
n
,
f
:=
b
.
inode
(
input
.
NodeId
,
input
.
Fh
)
n
,
f
:=
b
.
inode
(
input
.
NodeId
,
input
.
Fh
)
n
.
node
.
Release
(
f
.
file
)
n
.
node
.
Release
(
f
.
file
)
b
.
releaseFileEntry
(
input
.
Fh
)
b
.
releaseFileEntry
(
n
,
input
.
Fh
)
}
}
func
(
b
*
rawBridge
)
ReleaseDir
(
input
*
fuse
.
ReleaseIn
)
{
func
(
b
*
rawBridge
)
ReleaseDir
(
input
*
fuse
.
ReleaseIn
)
{
_
,
f
:=
b
.
inode
(
input
.
NodeId
,
input
.
Fh
)
n
,
f
:=
b
.
inode
(
input
.
NodeId
,
input
.
Fh
)
if
f
.
dirStream
!=
nil
{
if
f
.
dirStream
!=
nil
{
f
.
dirStream
.
Close
()
f
.
dirStream
.
Close
()
}
}
b
.
releaseFileEntry
(
input
.
Fh
)
b
.
releaseFileEntry
(
n
,
input
.
Fh
)
}
}
func
(
b
*
rawBridge
)
releaseFileEntry
(
fh
uint64
)
{
func
(
b
*
rawBridge
)
releaseFileEntry
(
n
*
Inode
,
fh
uint64
)
{
if
fh
>
0
{
if
fh
>
0
{
b
.
mu
.
Lock
()
b
.
mu
.
Lock
()
defer
b
.
mu
.
Unlock
()
defer
b
.
mu
.
Unlock
()
b
.
files
[
fh
]
.
file
=
nil
entry
:=
b
.
files
[
fh
]
if
entry
.
file
!=
nil
{
delete
(
n
.
openFiles
,
entry
.
file
)
}
entry
.
dirStream
=
nil
entry
.
file
=
nil
b
.
freeFiles
=
append
(
b
.
freeFiles
,
fh
)
b
.
freeFiles
=
append
(
b
.
freeFiles
,
fh
)
}
}
}
}
...
@@ -539,7 +558,7 @@ func (b *rawBridge) OpenDir(cancel <-chan struct{}, input *fuse.OpenIn, out *fus
...
@@ -539,7 +558,7 @@ func (b *rawBridge) OpenDir(cancel <-chan struct{}, input *fuse.OpenIn, out *fus
}
}
b
.
mu
.
Lock
()
b
.
mu
.
Lock
()
defer
b
.
mu
.
Unlock
()
defer
b
.
mu
.
Unlock
()
out
.
Fh
=
b
.
registerFile
(
n
il
)
out
.
Fh
=
b
.
registerFile
(
n
,
nil
,
0
)
return
fuse
.
OK
return
fuse
.
OK
}
}
...
@@ -625,7 +644,7 @@ func (b *rawBridge) ReadDirPlus(cancel <-chan struct{}, input *fuse.ReadIn, out
...
@@ -625,7 +644,7 @@ func (b *rawBridge) ReadDirPlus(cancel <-chan struct{}, input *fuse.ReadIn, out
entryOut
.
SetEntryTimeout
(
*
b
.
options
.
NegativeTimeout
)
entryOut
.
SetEntryTimeout
(
*
b
.
options
.
NegativeTimeout
)
}
}
}
else
{
}
else
{
b
.
addNewChild
(
n
,
e
.
Name
,
child
,
nil
,
entryOut
)
b
.
addNewChild
(
n
,
e
.
Name
,
child
,
nil
,
0
,
entryOut
)
b
.
setEntryOutTimeout
(
entryOut
)
b
.
setEntryOutTimeout
(
entryOut
)
if
(
e
.
Mode
&^
07777
)
!=
(
child
.
mode
&^
07777
)
{
if
(
e
.
Mode
&^
07777
)
!=
(
child
.
mode
&^
07777
)
{
// XXX should go back and change the
// XXX should go back and change the
...
...
nodefs/inode.go
View file @
6fad53e3
...
@@ -59,6 +59,12 @@ type Inode struct {
...
@@ -59,6 +59,12 @@ type Inode struct {
// Following data is mutable.
// Following data is mutable.
// protected by bridge.mu
// TODO: store using an array and a per-inode handle; the map
// is fairly heavyweight.
openFiles
map
[
FileHandle
]
uint32
// mu protects the following mutable fields. When locking
// mu protects the following mutable fields. When locking
// multiple Inodes, locks must be acquired using
// multiple Inodes, locks must be acquired using
// lockNodes/unlockNodes
// lockNodes/unlockNodes
...
...
nodefs/loopback.go
View file @
6fad53e3
...
@@ -8,7 +8,6 @@ import (
...
@@ -8,7 +8,6 @@ import (
"context"
"context"
"os"
"os"
"path/filepath"
"path/filepath"
"sync"
"syscall"
"syscall"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse"
...
@@ -25,7 +24,6 @@ type loopbackRoot struct {
...
@@ -25,7 +24,6 @@ type loopbackRoot struct {
func
(
n
*
loopbackRoot
)
newLoopbackNode
()
*
loopbackNode
{
func
(
n
*
loopbackRoot
)
newLoopbackNode
()
*
loopbackNode
{
return
&
loopbackNode
{
return
&
loopbackNode
{
rootNode
:
n
,
rootNode
:
n
,
openFiles
:
map
[
*
loopbackFile
]
uint32
{},
}
}
}
}
...
@@ -54,21 +52,6 @@ type loopbackNode struct {
...
@@ -54,21 +52,6 @@ type loopbackNode struct {
DefaultOperations
DefaultOperations
rootNode
*
loopbackRoot
rootNode
*
loopbackRoot
mu
sync
.
Mutex
// file => openflags
openFiles
map
[
*
loopbackFile
]
uint32
}
func
(
n
*
loopbackNode
)
Release
(
f
FileHandle
)
{
if
f
!=
nil
{
n
.
mu
.
Lock
()
defer
n
.
mu
.
Unlock
()
lf
:=
f
.
(
*
loopbackFile
)
delete
(
n
.
openFiles
,
lf
)
f
.
Release
()
}
}
}
func
(
n
*
loopbackNode
)
path
()
string
{
func
(
n
*
loopbackNode
)
path
()
string
{
...
@@ -190,9 +173,6 @@ func (n *loopbackNode) Create(ctx context.Context, name string, flags uint32, mo
...
@@ -190,9 +173,6 @@ func (n *loopbackNode) Create(ctx context.Context, name string, flags uint32, mo
node
:=
n
.
rootNode
.
newLoopbackNode
()
node
:=
n
.
rootNode
.
newLoopbackNode
()
ch
:=
n
.
inode
()
.
NewInode
(
node
,
uint32
(
st
.
Mode
),
idFromStat
(
&
st
))
ch
:=
n
.
inode
()
.
NewInode
(
node
,
uint32
(
st
.
Mode
),
idFromStat
(
&
st
))
lf
:=
newLoopbackFile
(
fd
)
lf
:=
newLoopbackFile
(
fd
)
n
.
mu
.
Lock
()
defer
n
.
mu
.
Unlock
()
n
.
openFiles
[
lf
]
=
flags
|
syscall
.
O_CREAT
return
ch
,
lf
,
0
,
fuse
.
OK
return
ch
,
lf
,
0
,
fuse
.
OK
}
}
...
@@ -256,10 +236,7 @@ func (n *loopbackNode) Open(ctx context.Context, flags uint32) (fh FileHandle, f
...
@@ -256,10 +236,7 @@ func (n *loopbackNode) Open(ctx context.Context, flags uint32) (fh FileHandle, f
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
0
,
fuse
.
ToStatus
(
err
)
return
nil
,
0
,
fuse
.
ToStatus
(
err
)
}
}
n
.
mu
.
Lock
()
defer
n
.
mu
.
Unlock
()
lf
:=
newLoopbackFile
(
f
)
lf
:=
newLoopbackFile
(
f
)
n
.
openFiles
[
lf
]
=
flags
return
lf
,
0
,
fuse
.
OK
return
lf
,
0
,
fuse
.
OK
}
}
...
@@ -276,25 +253,9 @@ func (n *loopbackNode) ReadDir(ctx context.Context) (DirStream, fuse.Status) {
...
@@ -276,25 +253,9 @@ func (n *loopbackNode) ReadDir(ctx context.Context) (DirStream, fuse.Status) {
return
NewLoopbackDirStream
(
n
.
path
())
return
NewLoopbackDirStream
(
n
.
path
())
}
}
func
(
n
*
loopbackNode
)
fGetAttr
(
ctx
context
.
Context
,
out
*
fuse
.
AttrOut
)
(
fuse
.
Status
,
bool
)
{
n
.
mu
.
Lock
()
defer
n
.
mu
.
Unlock
()
for
f
:=
range
n
.
openFiles
{
if
f
!=
nil
{
return
f
.
GetAttr
(
ctx
,
out
),
true
}
}
return
fuse
.
EBADF
,
false
}
func
(
n
*
loopbackNode
)
GetAttr
(
ctx
context
.
Context
,
f
FileHandle
,
out
*
fuse
.
AttrOut
)
fuse
.
Status
{
func
(
n
*
loopbackNode
)
GetAttr
(
ctx
context
.
Context
,
f
FileHandle
,
out
*
fuse
.
AttrOut
)
fuse
.
Status
{
if
f
!=
nil
{
if
f
!=
nil
{
// this never happens because the kernel never sends FH on getattr.
return
f
.
GetAttr
(
ctx
,
out
)
return
f
.
GetAttr
(
ctx
,
out
)
}
if
status
,
ok
:=
n
.
fGetAttr
(
ctx
,
out
);
ok
{
return
status
}
}
p
:=
n
.
path
()
p
:=
n
.
path
()
...
@@ -314,7 +275,6 @@ func NewLoopback(root string) Operations {
...
@@ -314,7 +275,6 @@ func NewLoopback(root string) Operations {
root
:
root
,
root
:
root
,
}
}
n
.
rootNode
=
n
n
.
rootNode
=
n
n
.
openFiles
=
map
[
*
loopbackFile
]
uint32
{}
return
n
return
n
}
}
...
...
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