RAMFS: Lock attribute iterators separate from entry iterators.

And clean up the code style while at it.
This commit is contained in:
Augustin Cavalier 2024-11-22 20:29:18 -05:00
parent e2e7d84d21
commit bab3f64413
4 changed files with 112 additions and 95 deletions

View File

@ -2,11 +2,15 @@
* Copyright 2007, Ingo Weinhold, ingo_weinhold@gmx.de. * Copyright 2007, Ingo Weinhold, ingo_weinhold@gmx.de.
* All rights reserved. Distributed under the terms of the MIT license. * All rights reserved. Distributed under the terms of the MIT license.
*/ */
#include "AttributeIterator.h" #include "AttributeIterator.h"
#include <util/AutoLock.h>
#include "Node.h" #include "Node.h"
#include "Volume.h" #include "Volume.h"
// constructor
AttributeIterator::AttributeIterator(Node *node) AttributeIterator::AttributeIterator(Node *node)
: fNode(node), : fNode(node),
fAttribute(NULL), fAttribute(NULL),
@ -16,34 +20,36 @@ AttributeIterator::AttributeIterator(Node *node)
{ {
} }
// destructor
AttributeIterator::~AttributeIterator() AttributeIterator::~AttributeIterator()
{ {
Unset(); Unset();
} }
// SetTo
status_t status_t
AttributeIterator::SetTo(Node *node) AttributeIterator::SetTo(Node *node)
{ {
Unset(); Unset();
status_t error = (node ? B_OK : B_BAD_VALUE);
if (error == B_OK) { if (node == NULL)
fNode = node; return B_BAD_VALUE;
fAttribute = NULL;
fSuspended = false; fNode = node;
fIsNext = false; fAttribute = NULL;
fDone = false; fSuspended = false;
} fIsNext = false;
return error; fDone = false;
return B_OK;
} }
// Unset
void void
AttributeIterator::Unset() AttributeIterator::Unset()
{ {
if (fNode && fSuspended) if (fNode && fSuspended)
Resume(); Resume();
fNode = NULL; fNode = NULL;
fAttribute = NULL; fAttribute = NULL;
fSuspended = false; fSuspended = false;
@ -51,51 +57,57 @@ AttributeIterator::Unset()
fDone = false; fDone = false;
} }
// Suspend
status_t status_t
AttributeIterator::Suspend() AttributeIterator::Suspend()
{ {
status_t error = (fNode ? B_OK : B_ERROR); if (fNode == NULL)
if (error == B_OK) { return B_ERROR;
if (fNode->GetVolume()->IteratorLock()) {
if (!fSuspended) { RecursiveLocker locker(fNode->GetVolume()->AttributeIteratorLocker());
if (fAttribute) if (!locker.IsLocked())
fAttribute->AttachAttributeIterator(this); return B_ERROR;
fNode->GetVolume()->IteratorUnlock();
fSuspended = true; if (fSuspended)
} else return B_ERROR;
error = B_ERROR;
} else if (fAttribute)
error = B_ERROR; fAttribute->AttachAttributeIterator(this);
} fSuspended = true;
return error;
return B_OK;
} }
// Resume
status_t status_t
AttributeIterator::Resume() AttributeIterator::Resume()
{ {
status_t error = (fNode ? B_OK : B_ERROR); if (fNode == NULL)
if (error == B_OK) { return B_ERROR;
if (fNode->GetVolume()->IteratorLock()) {
if (fSuspended) { RecursiveLocker locker(fNode->GetVolume()->AttributeIteratorLocker());
if (fAttribute) if (!locker.IsLocked())
fAttribute->DetachAttributeIterator(this); return B_ERROR;
fSuspended = false;
} if (!fSuspended)
fNode->GetVolume()->IteratorUnlock(); return B_ERROR;
} else
error = B_ERROR; if (fAttribute)
} fAttribute->DetachAttributeIterator(this);
return error; fSuspended = false;
return B_OK;
} }
// GetNext
status_t status_t
AttributeIterator::GetNext(Attribute **attribute) AttributeIterator::GetNext(Attribute **attribute)
{ {
if (attribute == NULL)
return B_BAD_VALUE;
status_t error = B_ENTRY_NOT_FOUND; status_t error = B_ENTRY_NOT_FOUND;
if (!fDone && fNode && attribute) { if (!fDone && fNode != NULL) {
if (fIsNext) { if (fIsNext) {
fIsNext = false; fIsNext = false;
if (fAttribute) if (fAttribute)
@ -108,26 +120,26 @@ AttributeIterator::GetNext(Attribute **attribute)
return error; return error;
} }
// Rewind
status_t status_t
AttributeIterator::Rewind() AttributeIterator::Rewind()
{ {
status_t error = (fNode ? B_OK : B_ERROR); if (fNode == NULL)
if (error == B_OK) { return B_ERROR;
if (fNode->GetVolume()->IteratorLock()) {
if (fSuspended && fAttribute) RecursiveLocker locker(fNode->GetVolume()->AttributeIteratorLocker());
fAttribute->DetachAttributeIterator(this); if (!locker.IsLocked())
fAttribute = NULL; return B_ERROR;
fIsNext = false;
fDone = false; if (fSuspended && fAttribute)
fNode->GetVolume()->IteratorUnlock(); fAttribute->DetachAttributeIterator(this);
} else fAttribute = NULL;
error = B_ERROR; fIsNext = false;
} fDone = false;
return error; return B_OK;
} }
// SetCurrent
void void
AttributeIterator::SetCurrent(Attribute *attribute, bool isNext) AttributeIterator::SetCurrent(Attribute *attribute, bool isNext)
{ {
@ -135,4 +147,3 @@ AttributeIterator::SetCurrent(Attribute *attribute, bool isNext)
fAttribute = attribute; fAttribute = attribute;
fDone = !fAttribute; fDone = !fAttribute;
} }

View File

@ -3,11 +3,14 @@
* All rights reserved. Distributed under the terms of the MIT license. * All rights reserved. Distributed under the terms of the MIT license.
*/ */
#include "Node.h"
#include <util/AutoLock.h>
#include "AllocationInfo.h" #include "AllocationInfo.h"
#include "DebugSupport.h" #include "DebugSupport.h"
#include "EntryIterator.h" #include "EntryIterator.h"
#include "LastModifiedIndex.h" #include "LastModifiedIndex.h"
#include "Node.h"
#include "Volume.h" #include "Volume.h"
@ -191,40 +194,39 @@ Node::AddAttribute(Attribute *attribute)
status_t status_t
Node::RemoveAttribute(Attribute *attribute) Node::RemoveAttribute(Attribute *attribute)
{ {
status_t error = (attribute && attribute->GetNode() == this if (attribute == NULL || attribute->GetNode() != this)
? B_OK : B_BAD_VALUE); return B_BAD_VALUE;
RecursiveLocker locker(GetVolume()->AttributeIteratorLocker());
if (!locker.IsLocked())
return B_ERROR;
// move all iterators pointing to the attribute to the next attribute
Attribute *nextAttr = fAttributes.GetNext(attribute);
DoublyLinkedList<AttributeIterator> *iterators
= attribute->GetAttributeIteratorList();
for (AttributeIterator *iterator = iterators->First();
iterator != NULL; iterator = iterators->GetNext(iterator)) {
iterator->SetCurrent(nextAttr, true);
}
// Move the iterators from one list to the other, or just remove
// them, if there is no next attribute.
if (nextAttr != NULL) {
DoublyLinkedList<AttributeIterator> *nextIterators
= nextAttr->GetAttributeIteratorList();
nextIterators->MoveFrom(iterators);
} else
iterators->RemoveAll();
locker.Unlock();
// remove the attribute
status_t error = GetVolume()->NodeAttributeRemoved(GetID(), attribute);
if (error == B_OK) { if (error == B_OK) {
// move all iterators pointing to the attribute to the next attribute fAttributes.Remove(attribute);
if (GetVolume()->IteratorLock()) { attribute->SetNode(NULL);
// set the iterators' current entry MarkModified(B_STAT_MODIFICATION_TIME);
Attribute *nextAttr = fAttributes.GetNext(attribute);
DoublyLinkedList<AttributeIterator> *iterators
= attribute->GetAttributeIteratorList();
for (AttributeIterator *iterator = iterators->First();
iterator;
iterator = iterators->GetNext(iterator)) {
iterator->SetCurrent(nextAttr, true);
}
// Move the iterators from one list to the other, or just remove
// them, if there is no next attribute.
if (nextAttr) {
DoublyLinkedList<AttributeIterator> *nextIterators
= nextAttr->GetAttributeIteratorList();
nextIterators->MoveFrom(iterators);
} else
iterators->RemoveAll();
GetVolume()->IteratorUnlock();
} else
error = B_ERROR;
// remove the attribute
if (error == B_OK) {
error = GetVolume()->NodeAttributeRemoved(GetID(), attribute);
if (error == B_OK) {
fAttributes.Remove(attribute);
attribute->SetNode(NULL);
MarkModified(B_STAT_MODIFICATION_TIME);
}
}
} }
return error; return error;
} }

View File

@ -141,6 +141,7 @@ Volume::Volume(fs_volume* volume)
{ {
rw_lock_init(&fLocker, "ramfs volume"); rw_lock_init(&fLocker, "ramfs volume");
recursive_lock_init(&fIteratorLocker, "ramfs iterators"); recursive_lock_init(&fIteratorLocker, "ramfs iterators");
recursive_lock_init(&fAttributeIteratorLocker, "ramfs attribute iterators");
recursive_lock_init(&fQueryLocker, "ramfs queries"); recursive_lock_init(&fQueryLocker, "ramfs queries");
} }
@ -149,6 +150,7 @@ Volume::~Volume()
{ {
Unmount(); Unmount();
recursive_lock_destroy(&fAttributeIteratorLocker);
recursive_lock_destroy(&fIteratorLocker); recursive_lock_destroy(&fIteratorLocker);
recursive_lock_destroy(&fQueryLocker); recursive_lock_destroy(&fQueryLocker);
rw_lock_destroy(&fLocker); rw_lock_destroy(&fLocker);
@ -777,4 +779,3 @@ Volume::IteratorUnlock()
{ {
recursive_lock_unlock(&fIteratorLocker); recursive_lock_unlock(&fIteratorLocker);
} }

View File

@ -167,6 +167,8 @@ public:
bool IteratorLock(); bool IteratorLock();
void IteratorUnlock(); void IteratorUnlock();
recursive_lock& AttributeIteratorLocker() { return fAttributeIteratorLocker; }
protected: protected:
fs_volume* fVolume; fs_volume* fVolume;
@ -186,6 +188,7 @@ private:
EntryListenerList fAnyEntryListeners; EntryListenerList fAnyEntryListeners;
recursive_lock fIteratorLocker; recursive_lock fIteratorLocker;
recursive_lock fAttributeIteratorLocker;
recursive_lock fQueryLocker; recursive_lock fQueryLocker;
QueryList fQueries; QueryList fQueries;