⛏️ index : haiku.git

author Augustin Cavalier <waddlesplash@gmail.com> 2022-11-30 0:23:47.0 -05:00:00
committer waddlesplash <waddlesplash@gmail.com> 2022-11-30 5:26:28.0 +00:00:00
commit
6c771e473a3af67bbe8f97eb3731e019c7d6da33 [patch]
tree
674bc138868120e1464aa718a476f066b9cb92d2
parent
11956b660f1d589e817b8014558b396e9dd91779
download
6c771e473a3af67bbe8f97eb3731e019c7d6da33.tar.gz

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(-)

diff --git a/src/add-ons/kernel/file_systems/ramfs/Node.cpp b/src/add-ons/kernel/file_systems/ramfs/Node.cpp
index 20d2610..7af652e 100644
--- a/src/add-ons/kernel/file_systems/ramfs/Node.cpp
+++ b/src/add-ons/kernel/file_systems/ramfs/Node.cpp
@@ -66,6 +66,8 @@
// destructor
Node::~Node()
{
	ASSERT(fRefCount == 0);

	// delete all attributes
	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++;
			// RemoveVNode can potentially delete us immediately!
	}
}

@@ -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);
}

diff --git a/src/add-ons/kernel/file_systems/ramfs/Volume.cpp b/src/add-ons/kernel/file_systems/ramfs/Volume.cpp
index 474be66..6320ba0 100644
--- a/src/add-ons/kernel/file_systems/ramfs/Volume.cpp
+++ b/src/add-ons/kernel/file_systems/ramfs/Volume.cpp
@@ -205,7 +205,7 @@
			// set permissions: -rwxr-xr-x
			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;