Commit 0c1f5aa9 authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

nodefs: move bridge.mu section under Inode critical section

parent 1433ae4f
...@@ -29,6 +29,8 @@ type rawBridge struct { ...@@ -29,6 +29,8 @@ type rawBridge struct {
options Options options Options
root *Inode root *Inode
// mu protects the following data. Locks for inodes must be
// taken before rawBridge.mu
mu sync.Mutex mu sync.Mutex
nodes []mapEntry nodes []mapEntry
free []uint64 free []uint64
...@@ -89,16 +91,14 @@ func (b *rawBridge) Lookup(header *fuse.InHeader, name string, out *fuse.EntryOu ...@@ -89,16 +91,14 @@ func (b *rawBridge) Lookup(header *fuse.InHeader, name string, out *fuse.EntryOu
lockNodes(parent, child) lockNodes(parent, child)
parent.setEntry(name, child) parent.setEntry(name, child)
unlockNodes(parent, child)
b.mu.Lock() b.mu.Lock()
if child.nodeID == 0 { if child.nodeID == 0 {
b.registerInode(child) b.registerInode(child)
} }
out.NodeId = child.nodeID out.NodeId = child.nodeID
b.mu.Unlock()
out.Generation = b.nodes[out.NodeId].generation out.Generation = b.nodes[out.NodeId].generation
b.mu.Unlock()
unlockNodes(parent, child)
if b.options.AttrTimeout != nil { if b.options.AttrTimeout != nil {
out.SetAttrTimeout(*b.options.AttrTimeout) out.SetAttrTimeout(*b.options.AttrTimeout)
...@@ -110,7 +110,8 @@ func (b *rawBridge) Lookup(header *fuse.InHeader, name string, out *fuse.EntryOu ...@@ -110,7 +110,8 @@ func (b *rawBridge) Lookup(header *fuse.InHeader, name string, out *fuse.EntryOu
return fuse.OK return fuse.OK
} }
// registerInode sets an inode number in the child. Must have bridge.mu // registerInode sets an nodeID in the child. Must have bridge.mu and
// child.mu
func (b *rawBridge) registerInode(child *Inode) { func (b *rawBridge) registerInode(child *Inode) {
if l := len(b.free); l > 0 { if l := len(b.free); l > 0 {
last := b.free[l-1] last := b.free[l-1]
...@@ -141,17 +142,15 @@ func (b *rawBridge) Create(input *fuse.CreateIn, name string, out *fuse.CreateOu ...@@ -141,17 +142,15 @@ func (b *rawBridge) Create(input *fuse.CreateIn, name string, out *fuse.CreateOu
lockNodes(parent, child) lockNodes(parent, child)
parent.setEntry(name, child) parent.setEntry(name, child)
unlockNodes(parent, child)
b.mu.Lock() b.mu.Lock()
if child.nodeID == 0 { if child.nodeID == 0 {
b.registerInode(child) b.registerInode(child)
} }
out.Fh = b.registerFile(f) out.Fh = b.registerFile(f)
b.mu.Unlock()
out.NodeId = child.nodeID out.NodeId = child.nodeID
out.Generation = b.nodes[child.nodeID].generation out.Generation = b.nodes[child.nodeID].generation
b.mu.Unlock()
unlockNodes(parent, child)
if b.options.AttrTimeout != nil { if b.options.AttrTimeout != nil {
out.SetAttrTimeout(*b.options.AttrTimeout) out.SetAttrTimeout(*b.options.AttrTimeout)
...@@ -171,10 +170,12 @@ func (b *rawBridge) Forget(nodeid, nlookup uint64) { ...@@ -171,10 +170,12 @@ func (b *rawBridge) Forget(nodeid, nlookup uint64) {
n := b.nodes[nodeid].inode n := b.nodes[nodeid].inode
b.mu.Unlock() b.mu.Unlock()
if forgotten, _ := n.removeRef(nlookup, false); forgotten { n.removeRef(nlookup, false)
b.free = append(b.free, nodeid) }
b.nodes[nodeid].inode = nil
} func (b *rawBridge) unregisterNode(nodeid uint64) {
b.free = append(b.free, nodeid)
b.nodes[nodeid].inode = nil
} }
func (b *rawBridge) SetDebug(debug bool) {} func (b *rawBridge) SetDebug(debug bool) {}
......
...@@ -77,15 +77,15 @@ func (f *loopbackFile) Fsync(ctx context.Context, flags int) (code fuse.Status) ...@@ -77,15 +77,15 @@ func (f *loopbackFile) Fsync(ctx context.Context, flags int) (code fuse.Status)
} }
const ( const (
F_OFD_GETLK = 36 _OFD_GETLK = 36
F_OFD_SETLK = 37 _OFD_SETLK = 37
F_OFD_SETLKW = 38 _OFD_SETLKW = 38
) )
func (f *loopbackFile) GetLk(ctx context.Context, owner uint64, lk *fuse.FileLock, flags uint32, out *fuse.FileLock) (code fuse.Status) { func (f *loopbackFile) GetLk(ctx context.Context, owner uint64, lk *fuse.FileLock, flags uint32, out *fuse.FileLock) (code fuse.Status) {
flk := syscall.Flock_t{} flk := syscall.Flock_t{}
lk.ToFlockT(&flk) lk.ToFlockT(&flk)
code = fuse.ToStatus(syscall.FcntlFlock(f.File.Fd(), F_OFD_GETLK, &flk)) code = fuse.ToStatus(syscall.FcntlFlock(f.File.Fd(), _OFD_GETLK, &flk))
out.FromFlockT(&flk) out.FromFlockT(&flk)
return return
} }
...@@ -120,9 +120,9 @@ func (f *loopbackFile) setLock(ctx context.Context, owner uint64, lk *fuse.FileL ...@@ -120,9 +120,9 @@ func (f *loopbackFile) setLock(ctx context.Context, owner uint64, lk *fuse.FileL
lk.ToFlockT(&flk) lk.ToFlockT(&flk)
var op int var op int
if blocking { if blocking {
op = F_OFD_SETLKW op = _OFD_SETLKW
} else { } else {
op = F_OFD_SETLK op = _OFD_SETLK
} }
return fuse.ToStatus(syscall.FcntlFlock(f.File.Fd(), op, &flk)) return fuse.ToStatus(syscall.FcntlFlock(f.File.Fd(), op, &flk))
} }
......
...@@ -34,7 +34,10 @@ type Inode struct { ...@@ -34,7 +34,10 @@ type Inode struct {
// Following data is mutable. // Following data is mutable.
// the following fields protected by bridge.mu // mu protects the following mutable fields. When locking
// multiple Inodes, locks must be acquired using
// lockNodes/unlockNodes
mu sync.Mutex
// ID of the inode; 0 if inode was forgotten. Forgotten // ID of the inode; 0 if inode was forgotten. Forgotten
// inodes could be persistent, not yet are unlinked from // inodes could be persistent, not yet are unlinked from
...@@ -42,11 +45,6 @@ type Inode struct { ...@@ -42,11 +45,6 @@ type Inode struct {
// from bridge.nodes . // from bridge.nodes .
nodeID uint64 nodeID uint64
// mu protects the following mutable fields. When locking
// multiple Inodes, locks must be acquired using
// lockNodes/unlockNodes
mu sync.Mutex
// persistent indicates that this node should not be removed // persistent indicates that this node should not be removed
// from the tree, even if there are no live references. This // from the tree, even if there are no live references. This
// must be set on creation, and can only be changed to false // must be set on creation, and can only be changed to false
...@@ -272,7 +270,7 @@ func (n *Inode) NewPersistentInode(node Node, mode uint32, opaque uint64) *Inode ...@@ -272,7 +270,7 @@ func (n *Inode) NewPersistentInode(node Node, mode uint32, opaque uint64) *Inode
// it has no children, and if the kernel as no references, the nodes // it has no children, and if the kernel as no references, the nodes
// gets removed from the tree. // gets removed from the tree.
func (n *Inode) ForgetPersistent() { func (n *Inode) ForgetPersistent() {
return n.removeRef(0, true) n.removeRef(0, true)
} }
// NewInode returns an inode for the given Node. The mode should be // NewInode returns an inode for the given Node. The mode should be
...@@ -350,6 +348,18 @@ retry: ...@@ -350,6 +348,18 @@ retry:
} }
n.parents = map[parentData]struct{}{} n.parents = map[parentData]struct{}{}
n.changeCounter++ n.changeCounter++
if n.lookupCount != 0 {
panic("lookupCount changed")
}
if n.nodeID != 0 {
n.bridge.mu.Lock()
n.bridge.unregisterNode(n.nodeID)
n.bridge.mu.Unlock()
n.nodeID = 0
}
unlockNodes(lockme...) unlockNodes(lockme...)
break break
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment