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.
This commit is contained in:
@@ -66,6 +66,8 @@ Node::Node(Volume *volume, uint8 type)
|
|||||||
// destructor
|
// destructor
|
||||||
Node::~Node()
|
Node::~Node()
|
||||||
{
|
{
|
||||||
|
ASSERT(fRefCount == 0);
|
||||||
|
|
||||||
// delete all attributes
|
// delete all attributes
|
||||||
while (Attribute *attribute = fAttributes.First()) {
|
while (Attribute *attribute = fAttributes.First()) {
|
||||||
status_t error = DeleteAttribute(attribute);
|
status_t error = DeleteAttribute(attribute);
|
||||||
@@ -104,9 +106,10 @@ Node::AddReference()
|
|||||||
void
|
void
|
||||||
Node::RemoveReference()
|
Node::RemoveReference()
|
||||||
{
|
{
|
||||||
|
ASSERT(fRefCount > 0);
|
||||||
if (--fRefCount == 0) {
|
if (--fRefCount == 0) {
|
||||||
GetVolume()->RemoveVNode(this);
|
GetVolume()->RemoveVNode(this);
|
||||||
fRefCount++;
|
// RemoveVNode can potentially delete us immediately!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,7 +117,7 @@ Node::RemoveReference()
|
|||||||
status_t
|
status_t
|
||||||
Node::Link(Entry *entry)
|
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);
|
fReferrers.Insert(entry);
|
||||||
|
|
||||||
status_t error = AddReference();
|
status_t error = AddReference();
|
||||||
@@ -128,10 +131,10 @@ PRINT("Node[%Ld]::Link(): %" B_PRId32 " ->...\n", fID, fRefCount);
|
|||||||
status_t
|
status_t
|
||||||
Node::Unlink(Entry *entry)
|
Node::Unlink(Entry *entry)
|
||||||
{
|
{
|
||||||
PRINT("Node[%Ld]::Unlink(): %" B_PRId32 " ->...\n", fID, fRefCount);
|
PRINT("Node[%" B_PRIdINO "]::Unlink(): %" B_PRId32 " ->...\n", fID, fRefCount);
|
||||||
RemoveReference();
|
|
||||||
fReferrers.Remove(entry);
|
fReferrers.Remove(entry);
|
||||||
|
|
||||||
|
RemoveReference();
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -358,4 +361,3 @@ Node::GetAllocationInfo(AllocationInfo &info)
|
|||||||
while (GetNextAttribute(&attribute) == B_OK)
|
while (GetNextAttribute(&attribute) == B_OK)
|
||||||
attribute->GetAllocationInfo(info);
|
attribute->GetAllocationInfo(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -205,7 +205,7 @@ Volume::Mount(uint32 flags)
|
|||||||
// set permissions: -rwxr-xr-x
|
// set permissions: -rwxr-xr-x
|
||||||
fRootDirectory->SetMode(
|
fRootDirectory->SetMode(
|
||||||
S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
|
S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
|
||||||
error = fRootDirectory->Link(NULL);
|
error = PublishVNode(fRootDirectory);
|
||||||
} else
|
} else
|
||||||
SET_ERROR(error, B_NO_MEMORY);
|
SET_ERROR(error, B_NO_MEMORY);
|
||||||
}
|
}
|
||||||
@@ -357,6 +357,7 @@ Volume::RemoveVNode(Node *node)
|
|||||||
{
|
{
|
||||||
if (fMounted)
|
if (fMounted)
|
||||||
return remove_vnode(FSVolume(), node->GetID());
|
return remove_vnode(FSVolume(), node->GetID());
|
||||||
|
|
||||||
status_t error = NodeRemoved(node);
|
status_t error = NodeRemoved(node);
|
||||||
if (error == B_OK)
|
if (error == B_OK)
|
||||||
delete node;
|
delete node;
|
||||||
|
|||||||
Reference in New Issue
Block a user