Commit 2b18dfc1 authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent 8b60658b
...@@ -112,11 +112,17 @@ func asctx(fctx *fuse.Context) context.Context { ...@@ -112,11 +112,17 @@ func asctx(fctx *fuse.Context) context.Context {
// In wcfs we have dynamic files (e.g. /head/watch) and this way we have to // In wcfs we have dynamic files (e.g. /head/watch) and this way we have to
// avoid returning ENOSYS on nodes, that do not need file handles. // avoid returning ENOSYS on nodes, that do not need file handles.
// //
// fsNode is like nodefs.defaultNode, but Open returns to kernel fh=0 and // fsNode is like nodefs.defaultNode, but by default Open returns to kernel
// FOPEN_KEEP_CACHE - similarly how openless case is handled there. // fh=0 and FOPEN_KEEP_CACHE - similarly how openless case is handled there.
type fsNode struct{ //
// fsNode behaviour can be additionally controlled via fsOptions.
//
// fsNode should be created via newFSNode.
type fsNode struct {
nodefs.Node nodefs.Node
opt *fsOptions
// cache for path // cache for path
// we don't use hardlinks / don't want to pay locks + traversal price every time. // we don't use hardlinks / don't want to pay locks + traversal price every time.
xpath atomic.Value xpath atomic.Value
...@@ -129,9 +135,23 @@ func (n *fsNode) Open(flags uint32, fctx *fuse.Context) (nodefs.File, fuse.Statu ...@@ -129,9 +135,23 @@ func (n *fsNode) Open(flags uint32, fctx *fuse.Context) (nodefs.File, fuse.Statu
}, fuse.OK }, fuse.OK
} }
func newFSNode() fsNode { // NOTE not pointer // fsOptions allows to tune fsNode behaviour.
type fsOptions struct {
// Sticky nodes are not removed from inode tree on FORGET.
// Correspondingly OnForget is never called on a sticky node.
Sticky bool
}
var fSticky = &fsOptions{Sticky: true} // frequently used shortcut XXX -> newFSticky?
func (n *fsNode) Deletable() bool {
return !n.opt.Sticky
}
func newFSNode(opt *fsOptions) fsNode { // NOTE not pointer
return fsNode{ return fsNode{
Node: nodefs.NewDefaultNode(), Node: nodefs.NewDefaultNode(),
opt: opt,
} }
} }
...@@ -161,6 +181,8 @@ func (n *fsNode) path() string { ...@@ -161,6 +181,8 @@ func (n *fsNode) path() string {
// NewStaticFile creates nodefs.Node for file with static data. // NewStaticFile creates nodefs.Node for file with static data.
//
// Created file is sticky.
func NewStaticFile(data []byte) *SmallFile { func NewStaticFile(data []byte) *SmallFile {
return newSmallFile(func() []byte { return newSmallFile(func() []byte {
return data return data
...@@ -178,13 +200,15 @@ type SmallFile struct { ...@@ -178,13 +200,15 @@ type SmallFile struct {
func newSmallFile(readData func() []byte, fuseFlags uint32) *SmallFile { func newSmallFile(readData func() []byte, fuseFlags uint32) *SmallFile {
return &SmallFile{ return &SmallFile{
fsNode: newFSNode(), fsNode: newFSNode(&fsOptions{Sticky: true}),
fuseFlags: fuseFlags, fuseFlags: fuseFlags,
readData: readData, readData: readData,
} }
} }
// NewSmallFile creates nodefs.Node for file with dynamic, but always small, data. // NewSmallFile creates nodefs.Node for file with dynamic, but always small, data.
//
// Created file is sticky.
func NewSmallFile(readData func() []byte) *SmallFile { func NewSmallFile(readData func() []byte) *SmallFile {
return newSmallFile(readData, fuse.FOPEN_DIRECT_IO) return newSmallFile(readData, fuse.FOPEN_DIRECT_IO)
} }
......
...@@ -1078,13 +1078,13 @@ func (root *Root) lookup(name string, fctx *fuse.Context) (_ *Head, err error) { ...@@ -1078,13 +1078,13 @@ func (root *Root) lookup(name string, fctx *fuse.Context) (_ *Head, err error) {
// XXX -> newHead() // XXX -> newHead()
revDir = &Head{ revDir = &Head{
fsNode: newFSNode(), fsNode: newFSNode(&fsOptions{Sticky: false}), // XXX + Head.OnForget() -> del root.revTab[]
rev: rev, rev: rev,
zconn: zconnRev, zconn: zconnRev,
} }
bfdir := &BigFileDir{ bfdir := &BigFileDir{
fsNode: newFSNode(), fsNode: newFSNode(&fsOptions{Sticky: false}), // XXX + BigFileDir.OnForget()
head: revDir, head: revDir,
fileTab: make(map[zodb.Oid]*BigFile), fileTab: make(map[zodb.Oid]*BigFile),
indexLooked: nil, // δbtree index not needed/used for @revX/ indexLooked: nil, // δbtree index not needed/used for @revX/
...@@ -1151,7 +1151,7 @@ func (head *Head) bigopen(ctx context.Context, oid zodb.Oid) (_ *BigFile, err er ...@@ -1151,7 +1151,7 @@ func (head *Head) bigopen(ctx context.Context, oid zodb.Oid) (_ *BigFile, err er
// zconn.Incref() // zconn.Incref()
f := &BigFile{ f := &BigFile{
fsNode: newFSNode(), fsNode: newFSNode(&fsOptions{Sticky: false}), // XXX + BigFile.OnForget -> del .head.bfdir.fileTab[]
head: head, head: head,
zbf: zbf, zbf: zbf,
zbfSize: zbfSize, zbfSize: zbfSize,
...@@ -1548,12 +1548,12 @@ func main() { ...@@ -1548,12 +1548,12 @@ func main() {
// mount root + head/ // mount root + head/
// XXX -> newHead() // XXX -> newHead()
head := &Head{ head := &Head{
fsNode: newFSNode(), fsNode: newFSNode(fSticky),
rev: 0, rev: 0,
zconn: zhead, zconn: zhead,
} }
bfdir := &BigFileDir{ bfdir := &BigFileDir{
fsNode: newFSNode(), fsNode: newFSNode(fSticky),
head: head, head: head,
fileTab: make(map[zodb.Oid]*BigFile), fileTab: make(map[zodb.Oid]*BigFile),
indexLooked: δbtree.NewPathSet(), indexLooked: δbtree.NewPathSet(),
...@@ -1561,7 +1561,7 @@ func main() { ...@@ -1561,7 +1561,7 @@ func main() {
head.bfdir = bfdir head.bfdir = bfdir
root := &Root{ root := &Root{
fsNode: newFSNode(), fsNode: newFSNode(fSticky),
zstor: zstor, zstor: zstor,
zdb: zdb, zdb: zdb,
head: head, head: head,
...@@ -1601,7 +1601,7 @@ func main() { ...@@ -1601,7 +1601,7 @@ func main() {
mkfile(head, "at", NewSmallFile(head.readAt)) // TODO mtime(at) = tidtime(at) mkfile(head, "at", NewSmallFile(head.readAt)) // TODO mtime(at) = tidtime(at)
// for debugging/testing // for debugging/testing
_wcfs := newFSNode() _wcfs := newFSNode(fSticky)
mkdir(root, ".wcfs", &_wcfs) mkdir(root, ".wcfs", &_wcfs)
mkfile(&_wcfs, "zurl", NewStaticFile([]byte(zurl))) mkfile(&_wcfs, "zurl", NewStaticFile([]byte(zurl)))
...@@ -1612,7 +1612,7 @@ func main() { ...@@ -1612,7 +1612,7 @@ func main() {
// There can be multiple openers. Once opened, the file must be read, // There can be multiple openers. Once opened, the file must be read,
// as wcfs blocks waiting for data to be read before XXX. // as wcfs blocks waiting for data to be read before XXX.
mkfile(&_wcfs, "zhead", &_wcfs_Zhead{ mkfile(&_wcfs, "zhead", &_wcfs_Zhead{
fsNode: newFSNode(), fsNode: newFSNode(fSticky),
}) })
// XXX place = ok? // XXX place = ok?
......
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