Commit c4872d49 authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

nodefs: various fixes

* Fix deadlock with OnAdd

* return EROFS for missing Create

* Fill Mode using Inode.setEntryOut in all namespace operations
parent c7cf8409
......@@ -450,4 +450,8 @@ type Options struct {
// Automatic inode numbers are handed out sequentially
// starting from this number. If unset, use 2^63.
FirstAutomaticIno uint64
// OnAdd is an alternative way to specify the OnAdd
// functionality of the root node.
OnAdd func(ctx context.Context, root InodeEmbedder)
}
......@@ -49,7 +49,7 @@ type rawBridge struct {
}
// newInode creates creates new inode pointing to ops.
func (b *rawBridge) newInode(ctx context.Context, ops InodeEmbedder, id NodeAttr, persistent bool) *Inode {
func (b *rawBridge) newInodeUnlocked(ops InodeEmbedder, id NodeAttr, persistent bool) *Inode {
b.mu.Lock()
defer b.mu.Unlock()
......@@ -96,10 +96,19 @@ func (b *rawBridge) newInode(ctx context.Context, ops InodeEmbedder, id NodeAttr
b.nodes[id.Ino] = ops.embed()
initInode(ops.embed(), ops, id, b, persistent)
return ops.embed()
}
func (b *rawBridge) newInode(ctx context.Context, ops InodeEmbedder, id NodeAttr, persistent bool) *Inode {
ch := b.newInodeUnlocked(ops, id, persistent)
if ch != ops.embed() {
return ch
}
if oa, ok := ops.(OnAdder); ok {
oa.OnAdd(ctx)
}
return ops.embed()
return ch
}
// addNewChild inserts the child into the tree. Returns file handle if file != nil.
......@@ -178,7 +187,9 @@ func NewNodeFS(root InodeEmbedder, opts *Options) fuse.RawFileSystem {
// Fh 0 means no file handle.
bridge.files = []*fileEntry{{}}
if oa, ok := root.(OnAdder); ok {
if opts.OnAdd != nil {
opts.OnAdd(context.Background(), root)
} else if oa, ok := root.(OnAdder); ok {
oa.OnAdd(context.Background())
}
......@@ -303,6 +314,7 @@ func (b *rawBridge) Mknod(cancel <-chan struct{}, input *fuse.MknodIn, name stri
b.addNewChild(parent, name, child, nil, 0, out)
b.setEntryOutTimeout(out)
child.setEntryOut(out)
return fuse.OK
}
......@@ -316,6 +328,8 @@ func (b *rawBridge) Create(cancel <-chan struct{}, input *fuse.CreateIn, name st
var flags uint32
if mops, ok := parent.ops.(Creater); ok {
child, f, flags, errno = mops.Create(ctx, name, input.Flags, input.Mode)
} else {
return fuse.EROFS
}
if errno != 0 {
......@@ -336,8 +350,8 @@ func (b *rawBridge) Create(cancel <-chan struct{}, input *fuse.CreateIn, name st
out.AttrValidNsec = temp.AttrValidNsec
b.setEntryOutTimeout(&out.EntryOut)
out.NodeId = child.nodeAttr.Ino
out.Mode = (out.Attr.Mode & 07777) | child.nodeAttr.Mode
child.setEntryOut(&out.EntryOut)
return fuse.OK
}
......@@ -442,6 +456,7 @@ func (b *rawBridge) Link(cancel <-chan struct{}, input *fuse.LinkIn, name string
b.addNewChild(parent, name, child, nil, 0, out)
b.setEntryOutTimeout(out)
child.setEntryOut(out)
return fuse.OK
}
return fuse.ENOTSUP
......@@ -458,6 +473,7 @@ func (b *rawBridge) Symlink(cancel <-chan struct{}, header *fuse.InHeader, targe
b.addNewChild(parent, name, child, nil, 0, out)
b.setEntryOutTimeout(out)
child.setEntryOut(out)
return fuse.OK
}
return fuse.ENOTSUP
......
......@@ -115,6 +115,13 @@ func initInode(n *Inode, ops InodeEmbedder, attr NodeAttr, bridge *rawBridge, pe
}
}
// Set node ID and mode in EntryOut
func (n *Inode) setEntryOut(out *fuse.EntryOut) {
out.NodeId = n.nodeAttr.Ino
out.Ino = n.nodeAttr.Ino
out.Mode = (out.Attr.Mode & 07777) | n.nodeAttr.Mode
}
// NodeAttr returns the (Ino, Gen) tuple for this node.
func (n *Inode) NodeAttr() NodeAttr {
return n.nodeAttr
......
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