Commit bedd3b65 authored by Kirill Smelkov's avatar Kirill Smelkov

X incomplete review of newapi 2

many things from na1.patch still not yet integrated back.
parent 48be1a10
This diff is collapsed.
......@@ -36,6 +36,9 @@
// automatically builds new index node and links it in the filesystem tree.
// InodeOf can be used to get particular Inode associated with a Node.
//
// XXX once can also create new subtrees via linking nodes explicitly, and
// return such subtree on lookup.
//
// XXX ^^^ inodes cleaned on cache clean (FORGET).
//
// XXX describe how to mount.
......@@ -57,8 +60,11 @@ import (
//
// The identity of the Inode does not change over the lifetime of
// the node object.
//
// Returned Inode is always !nil - if node was not yet associated with inode, a
// new inode is atomically created and associated with the node.
func InodeOf(node Node) *Inode {
return node.inode()
return inodeOf(node)
}
/*
......@@ -81,21 +87,32 @@ type Node interface {
inode() *Inode
setInode(*Inode)
// NodeID() should return filesystem-wide ID of the node.
//
// If the node has such ID it will be used as the base for corresponding inode ID.
// If the node does not have such ID - 0 must be returned and
// automatically allocated inode ID will be used.
//
// The ID, if given, must be unique throughout filesystem.
//
// XXX range of allowed ID = ?
NodeID() uint64
// Lookup should find a direct child of the node by child name.
//
// VFS makes sure to call Lookup only once for particular (node, name)
// pair.
Lookup(ctx context.Context, name string, out *fuse.EntryOut) (*Inode, fuse.Status)
Lookup(ctx context.Context, name string, out *fuse.EntryOut) (Node, fuse.Status)
Mkdir(ctx context.Context, name string, mode uint32, out *fuse.EntryOut) (*Inode, fuse.Status)
Mknod(ctx context.Context, name string, mode uint32, dev uint32, out *fuse.EntryOut) (*Inode, fuse.Status)
Mkdir(ctx context.Context, name string, mode uint32, out *fuse.EntryOut) (Node, fuse.Status)
Mknod(ctx context.Context, name string, mode uint32, dev uint32, out *fuse.EntryOut) (Node, fuse.Status)
Rmdir(ctx context.Context, name string) fuse.Status
Unlink(ctx context.Context, name string) fuse.Status
Rename(ctx context.Context, name string, newParent Node, newName string, flags uint32) fuse.Status
Open(ctx context.Context, flags uint32) (fh File, fuseFlags uint32, code fuse.Status)
Create(ctx context.Context, name string, flags uint32, mode uint32) (node *Inode, fh File, fuseFlags uint32, code fuse.Status)
Create(ctx context.Context, name string, flags uint32, mode uint32) (node Node, fh File, fuseFlags uint32, code fuse.Status)
Read(ctx context.Context, f File, dest []byte, off int64) (fuse.ReadResult, fuse.Status)
......@@ -137,6 +154,7 @@ type Node interface {
Allocate(ctx context.Context, f File, off uint64, size uint64, mode uint32) (code fuse.Status)
}
// XXX -> Handle? FileHandle? (better Handle as handle could be used not only for leaves)
type File interface {
Read(ctx context.Context, dest []byte, off int64) (fuse.ReadResult, fuse.Status)
Write(ctx context.Context, data []byte, off int64) (written uint32, code fuse.Status)
......
......@@ -20,6 +20,7 @@ type fileEntry struct {
// space to hold directory stuff
}
// rawBridge interconnects nodefs tree structure with raw FUSE exchange.
type rawBridge struct {
fuse.RawFileSystem
......@@ -36,7 +37,7 @@ type rawBridge struct {
freeFiles []uint64
}
// newInode creates creates new inode pointing to node.
// newInode creates new inode pointing to node.
// XXX - should store the Ino number we expose in GetAttr too ?
func (b *rawBridge) newInode(node Node, mode uint32, id FileID, persistent bool) *Inode {
b.mu.Lock()
......@@ -46,6 +47,8 @@ func (b *rawBridge) newInode(node Node, mode uint32, id FileID, persistent bool)
log.Panicf("using reserved ID %d for inode number", id.Ino)
}
// FIXME with automatic IDs this can create 2 inodes for 1 node if
// there are 2 concurrent lookups via different paths.
if id.Ino == 0 {
id.Ino = b.automaticIno
b.automaticIno++
......@@ -153,7 +156,6 @@ func (b *rawBridge) Rmdir(header *fuse.InHeader, name string) fuse.Status {
parent.RmChild(name)
}
return code
}
func (b *rawBridge) Unlink(header *fuse.InHeader, name string) fuse.Status {
......@@ -425,6 +427,9 @@ func (b *rawBridge) Open(input *fuse.OpenIn, out *fuse.OpenOut) (status fuse.Sta
//
// XXX is it allowed to return the same Fh from two different Open
// calls on the same inode?
// XXX -> absolutely no, 2 different opens should result in 2 diffrerent Fh.
// an example when not doing so would break badly is e.g. socket-like file-handles,
// where IO on different handle is completey separate from the rest.
func (b *rawBridge) registerFile(f File) uint64 {
var fh uint64
if len(b.freeFiles) > 0 {
......
......@@ -18,6 +18,10 @@ type DefaultNode struct {
inode_ *Inode
}
// XXX why we dropped atomics here?
// -> moved rawBridge.newInode() ?
// text: "set/retrieve inode" in na1.patch
func (dn *DefaultNode) setInode(inode *Inode) {
dn.inode_ = inode
}
......@@ -26,6 +30,12 @@ func (dn *DefaultNode) inode() *Inode {
return dn.inode_
}
func inodeOf(node Node) *Inode {
// XXX .inode = nil -> atomically create new
// XXX requires that we move atomic stuff back to setInode/inode/inodeOf
return node.inode()
}
func (n *DefaultNode) Read(ctx context.Context, f File, dest []byte, off int64) (fuse.ReadResult, fuse.Status) {
if f != nil {
return f.Read(ctx, dest, off)
......
......@@ -37,7 +37,7 @@ type FileID struct {
Gen uint64
}
// Zero returns if the FileID is zeroed out
// Reserved returns if the FileID is reserved and should not be used ... XXX
func (i *FileID) Reserved() bool {
return i.Ino == 0 || i.Ino == 1 || i.Ino == ^uint64(0)
}
......@@ -117,11 +117,12 @@ func nodeLess(a, b *Inode) bool {
// It also avoids locking an inode more than once, if it was specified multiple times.
// An example when an inode might be given multiple times is if dir/a and dir/b
// are hardlinked to the same inode and the caller needs to take locks on dir children.
//
// It is valid to give nil nodes - those are simply ignored.
func lockNodes(ns ...*Inode) {
sortNodes(ns)
// The default value nil prevents trying to lock nil nodes.
var nprev *Inode
var nprev *Inode = nil // initial nil + sort/dedup makes us ignore nil nodes
for _, n := range ns {
if n != nprev {
n.mu.Lock()
......@@ -133,22 +134,30 @@ func lockNodes(ns ...*Inode) {
// lockNode2 locks a and b in order consistent with lockNodes.
func lockNode2(a, b *Inode) {
if a == b {
b = nil
}
if !nodeLess(a, b) {
b, a = a, b
}
if a != nil {
a.mu.Lock()
} else if nodeLess(a, b) {
a.mu.Lock()
b.mu.Lock()
} else {
}
if b != nil {
b.mu.Lock()
a.mu.Lock()
}
}
// unlockNode2 unlocks a and b
// unlockNode2 unlocks a and b loced by lockNode2.
func unlockNode2(a, b *Inode) {
if a == b {
b = nil
}
// there is no deadlock if we unlock nodes in different compared to
// order they were locked.
if a != nil {
a.mu.Unlock()
} else {
a.mu.Unlock()
}
if b != nil {
b.mu.Unlock()
}
}
......@@ -159,7 +168,7 @@ func unlockNodes(ns ...*Inode) {
// however it still helps to have nodes sorted to avoid duplicates.
sortNodes(ns)
var nprev *Inode
var nprev *Inode = nil // initial nil + sort/dedup makes us ignore nil nodes
for _, n := range ns {
if n != nprev {
n.mu.Unlock()
......@@ -351,7 +360,7 @@ retry:
// RmChild removes multiple children. Returns whether the removal
// succeeded and whether the node is still live afterward. The removal
// is transactional: it only succeeds if all names are children, and
// is transactional: it only succeeds if all names are in children, and
// if they all were removed successfully. If the removal was
// successful, and there are no children left, the node may be removed
// from the FS tree. In that case, RmChild returns live==false.
......
......@@ -62,7 +62,7 @@ func (n *loopbackNode) path() string {
return filepath.Join(n.rootNode.root, path)
}
func (n *loopbackNode) Lookup(ctx context.Context, name string, out *fuse.EntryOut) (*Inode, fuse.Status) {
func (n *loopbackNode) Lookup(ctx context.Context, name string, out *fuse.EntryOut) (Node, fuse.Status) {
p := filepath.Join(n.path(), name)
st := syscall.Stat_t{}
......@@ -73,11 +73,12 @@ func (n *loopbackNode) Lookup(ctx context.Context, name string, out *fuse.EntryO
out.Attr.FromStat(&st)
node := n.rootNode.newLoopbackNode()
ch := n.inode().NewInode(node, out.Attr.Mode, idFromStat(&st))
return ch, fuse.OK
return node, fuse.OK
//ch := n.inode().NewInode(node, out.Attr.Mode, idFromStat(&st))
//return ch, fuse.OK
}
func (n *loopbackNode) Mknod(ctx context.Context, name string, mode, rdev uint32, out *fuse.EntryOut) (*Inode, fuse.Status) {
func (n *loopbackNode) Mknod(ctx context.Context, name string, mode, rdev uint32, out *fuse.EntryOut) (Node, fuse.Status) {
p := filepath.Join(n.path(), name)
err := syscall.Mknod(p, mode, int(rdev))
if err != nil {
......@@ -92,9 +93,10 @@ func (n *loopbackNode) Mknod(ctx context.Context, name string, mode, rdev uint32
out.Attr.FromStat(&st)
node := n.rootNode.newLoopbackNode()
ch := n.inode().NewInode(node, out.Attr.Mode, idFromStat(&st))
return node, fuse.OK
return ch, fuse.OK
//ch := n.inode().NewInode(node, out.Attr.Mode, idFromStat(&st))
//return ch, fuse.OK
}
func (n *loopbackNode) Mkdir(ctx context.Context, name string, mode uint32, out *fuse.EntryOut) (*Inode, fuse.Status) {
......
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