ramfs: Correct "reference" (link) counting of Node objects.
* RemoveReference() could delete us immediately, thus we must do
all important work before invoking it.
* Add assertions about fRefCount and remove a spurious add.
* Do not use Link but PublishVNode on the root, as we manually manage
when this object is published/deleted.
Fixes #18032.
(cherry picked from commit 605ecac1ee396134c11050ef031c0b88414d5613)
Change-Id: I696e652bc4094baacb5336b1180d8b90f3f0f864
Reviewed-on: https://review.haiku-os.org/c/haiku/+/5847
Reviewed-by: waddlesplash <waddlesplash@gmail.com>
Diff
src/add-ons/kernel/file_systems/ramfs/Node.cpp | 12 ++++++++----
src/add-ons/kernel/file_systems/ramfs/Volume.cpp | 3 ++-
2 files changed, 9 insertions(+), 6 deletions(-)
@@ -66,6 +66,8 @@
Node::~Node()
{
ASSERT(fRefCount == 0);
while (Attribute *attribute = fAttributes.First()) {
status_t error = DeleteAttribute(attribute);
@@ -104,9 +106,10 @@
void
Node::RemoveReference()
{
ASSERT(fRefCount > 0);
if (--fRefCount == 0) {
GetVolume()->RemoveVNode(this);
fRefCount++;
}
}
@@ -114,7 +117,7 @@
status_t
Node::Link(Entry *entry)
{
PRINT("Node[%Ld]::Link(): %" B_PRId32 " ->...\n", fID, fRefCount);
PRINT("Node[%" B_PRIdINO "]::Link(): %" B_PRId32 " ->...\n", fID, fRefCount);
fReferrers.Insert(entry);
status_t error = AddReference();
@@ -128,10 +131,10 @@
status_t
Node::Unlink(Entry *entry)
{
PRINT("Node[%Ld]::Unlink(): %" B_PRId32 " ->...\n", fID, fRefCount);
RemoveReference();
PRINT("Node[%" B_PRIdINO "]::Unlink(): %" B_PRId32 " ->...\n", fID, fRefCount);
fReferrers.Remove(entry);
RemoveReference();
return B_OK;
}
@@ -358,4 +361,3 @@
while (GetNextAttribute(&attribute) == B_OK)
attribute->GetAllocationInfo(info);
}
@@ -205,7 +205,7 @@
fRootDirectory->SetMode(
S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
error = fRootDirectory->Link(NULL);
error = PublishVNode(fRootDirectory);
} else
SET_ERROR(error, B_NO_MEMORY);
}
@@ -357,6 +357,7 @@
{
if (fMounted)
return remove_vnode(FSVolume(), node->GetID());
status_t error = NodeRemoved(node);
if (error == B_OK)
delete node;