From 8de7154d2cd5e6abc2ff971e7fb15babd2030b22 Mon Sep 17 00:00:00 2001 From: Iain Macdonald Date: Tue, 25 Jun 2024 11:14:21 -0700 Subject: [PATCH] Add inode.Initialized() for checking if an inode has been initialized. --- fs/bridge_test.go | 33 +++++++++++++++++++++++++++++++++ fs/inode.go | 8 ++++++++ 2 files changed, 41 insertions(+) diff --git a/fs/bridge_test.go b/fs/bridge_test.go index 6a0d46efb..0fc8b041d 100644 --- a/fs/bridge_test.go +++ b/fs/bridge_test.go @@ -233,3 +233,36 @@ func (fn *testIno1) Lookup(ctx context.Context, name string, out *fuse.EntryOut) child := fn.NewInode(ctx, &testIno1{}, stable) return child, 0 } + +func TestForgottenIno(t *testing.T) { + rootNode := testForgottenIno{} + testMount(t, &rootNode, nil) + if rootNode.Initialized() && rootNode.Forgotten() { + t.Error("newly-created inode should not be forgotten") + } + ino, errno := rootNode.Lookup(context.TODO(), "test", nil) + if errno != syscall.F_OK { + t.Error("error creating new inode") + } + if ino.Initialized() && ino.Forgotten() { + t.Error("newly-created inode should not be forgotten") + } + ok := rootNode.AddChild("test", ino, false) + if !ok { + t.Error("error adding child inode to fs") + } + if ino.Initialized() && ino.Forgotten() { + t.Error("newly-mounted inode should not be forgotten") + } +} + +type testForgottenIno struct { + Inode +} + +func (n *testForgottenIno) Lookup(ctx context.Context, name string, out *fuse.EntryOut) (*Inode, syscall.Errno) { + childNode := &testForgottenIno{} + stable := StableAttr{Mode: syscall.S_IFREG, Ino: 999} + child := n.NewInode(ctx, childNode, stable) + return child, syscall.F_OK +} diff --git a/fs/inode.go b/fs/inode.go index c91e029d8..6d6b0e61f 100644 --- a/fs/inode.go +++ b/fs/inode.go @@ -248,6 +248,14 @@ func unlockNodes(ns ...*Inode) { } } +// Initialized returns true if this inode has been initialized and added to the +// filesystem tree. +func (n *Inode) Initialized() bool { + n.mu.Lock() + defer n.mu.Unlock() + return n.changeCounter > 0 +} + // Forgotten returns true if the kernel holds no references to this // inode. This can be used for background cleanup tasks, since the // kernel has no way of reviving forgotten nodes by its own