* Removed the home-brewn locking classes in BFS besides the read/write lock
(for now). * Inode::fSmallDataLock is now a recursive_lock, Journal::fLock is now a recursive_lock, too, Journal::fEntriesLock is now a mutex, as is BPlusTree::fIteratorLock. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26298 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,8 +1,7 @@
|
|||||||
SubDir HAIKU_TOP src add-ons disk_systems bfs ;
|
SubDir HAIKU_TOP src add-ons disk_systems bfs ;
|
||||||
|
|
||||||
UsePrivateHeaders kernel ;
|
UsePrivateKernelHeaders ;
|
||||||
UsePrivateHeaders shared ;
|
UsePrivateHeaders shared storage ;
|
||||||
UsePrivateHeaders storage ;
|
|
||||||
|
|
||||||
SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src add-ons kernel file_systems bfs ] ;
|
SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src add-ons kernel file_systems bfs ] ;
|
||||||
|
|
||||||
|
|||||||
@@ -79,13 +79,13 @@ Attribute::Get(const char *name)
|
|||||||
fName = name;
|
fName = name;
|
||||||
|
|
||||||
// try to find it in the small data region
|
// try to find it in the small data region
|
||||||
if (fInode->SmallDataLock().Lock() == B_OK) {
|
if (recursive_lock_lock(&fInode->SmallDataLock()) == B_OK) {
|
||||||
fNodeGetter.SetToNode(fInode);
|
fNodeGetter.SetToNode(fInode);
|
||||||
fSmall = fInode->FindSmallData(fNodeGetter.Node(), (const char *)name);
|
fSmall = fInode->FindSmallData(fNodeGetter.Node(), (const char *)name);
|
||||||
if (fSmall != NULL)
|
if (fSmall != NULL)
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
fInode->SmallDataLock().Unlock();
|
recursive_lock_unlock(&fInode->SmallDataLock());
|
||||||
fNodeGetter.Unset();
|
fNodeGetter.Unset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,7 +98,7 @@ void
|
|||||||
Attribute::Put()
|
Attribute::Put()
|
||||||
{
|
{
|
||||||
if (fSmall != NULL) {
|
if (fSmall != NULL) {
|
||||||
fInode->SmallDataLock().Unlock();
|
recursive_lock_unlock(&fInode->SmallDataLock());
|
||||||
fNodeGetter.Unset();
|
fNodeGetter.Unset();
|
||||||
fSmall = NULL;
|
fSmall = NULL;
|
||||||
}
|
}
|
||||||
@@ -195,7 +195,7 @@ Attribute::Read(attr_cookie *cookie, off_t pos, uint8 *buffer, size_t *_length)
|
|||||||
if (fSmall == NULL && fAttribute == NULL)
|
if (fSmall == NULL && fAttribute == NULL)
|
||||||
return B_NO_INIT;
|
return B_NO_INIT;
|
||||||
|
|
||||||
// ToDo: move small_data logic from Inode::ReadAttribute() over to here!
|
// TODO: move small_data logic from Inode::ReadAttribute() over to here!
|
||||||
return fInode->ReadAttribute(cookie->name, 0, pos, buffer, _length);
|
return fInode->ReadAttribute(cookie->name, 0, pos, buffer, _length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -341,6 +341,7 @@ BPlusTree::BPlusTree(Transaction &transaction, Inode *stream, int32 nodeSize)
|
|||||||
fHeader(NULL),
|
fHeader(NULL),
|
||||||
fCachedHeader(this)
|
fCachedHeader(this)
|
||||||
{
|
{
|
||||||
|
mutex_init(&fIteratorLock, "bfs b+tree iterator");
|
||||||
SetTo(transaction, stream);
|
SetTo(transaction, stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -351,6 +352,7 @@ BPlusTree::BPlusTree(Inode *stream)
|
|||||||
fHeader(NULL),
|
fHeader(NULL),
|
||||||
fCachedHeader(this)
|
fCachedHeader(this)
|
||||||
{
|
{
|
||||||
|
mutex_init(&fIteratorLock, "bfs b+tree iterator");
|
||||||
SetTo(stream);
|
SetTo(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -364,6 +366,7 @@ BPlusTree::BPlusTree()
|
|||||||
fAllowDuplicates(true),
|
fAllowDuplicates(true),
|
||||||
fStatus(B_NO_INIT)
|
fStatus(B_NO_INIT)
|
||||||
{
|
{
|
||||||
|
mutex_init(&fIteratorLock, "bfs b+tree iterator");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -372,14 +375,13 @@ BPlusTree::~BPlusTree()
|
|||||||
// if there are any TreeIterators left, we need to stop them
|
// if there are any TreeIterators left, we need to stop them
|
||||||
// (can happen when the tree's inode gets deleted while
|
// (can happen when the tree's inode gets deleted while
|
||||||
// traversing the tree - a TreeIterator doesn't lock the inode)
|
// traversing the tree - a TreeIterator doesn't lock the inode)
|
||||||
if (fIteratorLock.Lock() < B_OK)
|
mutex_lock(&fIteratorLock);
|
||||||
return;
|
|
||||||
|
|
||||||
TreeIterator *iterator = NULL;
|
TreeIterator *iterator = NULL;
|
||||||
while ((iterator = fIterators.Next(iterator)) != NULL)
|
while ((iterator = fIterators.Next(iterator)) != NULL)
|
||||||
iterator->Stop();
|
iterator->Stop();
|
||||||
|
|
||||||
fIteratorLock.Unlock();
|
mutex_destroy(&fIteratorLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -565,38 +567,27 @@ BPlusTree::_UpdateIterators(off_t offset, off_t nextOffset, uint16 keyIndex,
|
|||||||
// Although every iterator which is affected by this update currently
|
// Although every iterator which is affected by this update currently
|
||||||
// waits on a semaphore, other iterators could be added/removed at
|
// waits on a semaphore, other iterators could be added/removed at
|
||||||
// any time, so we need to protect this loop
|
// any time, so we need to protect this loop
|
||||||
if (fIteratorLock.Lock() < B_OK)
|
MutexLocker _(fIteratorLock);
|
||||||
return;
|
|
||||||
|
|
||||||
TreeIterator *iterator = NULL;
|
TreeIterator *iterator = NULL;
|
||||||
while ((iterator = fIterators.Next(iterator)) != NULL)
|
while ((iterator = fIterators.Next(iterator)) != NULL)
|
||||||
iterator->Update(offset, nextOffset, keyIndex, splitAt, change);
|
iterator->Update(offset, nextOffset, keyIndex, splitAt, change);
|
||||||
|
|
||||||
fIteratorLock.Unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BPlusTree::_AddIterator(TreeIterator *iterator)
|
BPlusTree::_AddIterator(TreeIterator *iterator)
|
||||||
{
|
{
|
||||||
if (fIteratorLock.Lock() < B_OK)
|
MutexLocker _(fIteratorLock);
|
||||||
return;
|
|
||||||
|
|
||||||
fIterators.Add(iterator);
|
fIterators.Add(iterator);
|
||||||
|
|
||||||
fIteratorLock.Unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BPlusTree::_RemoveIterator(TreeIterator *iterator)
|
BPlusTree::_RemoveIterator(TreeIterator *iterator)
|
||||||
{
|
{
|
||||||
if (fIteratorLock.Lock() < B_OK)
|
MutexLocker _(fIteratorLock);
|
||||||
return;
|
|
||||||
|
|
||||||
fIterators.Remove(iterator);
|
fIterators.Remove(iterator);
|
||||||
|
|
||||||
fIteratorLock.Unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2139,7 +2130,8 @@ TreeIterator::SkipDuplicates()
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
TreeIterator::Update(off_t offset, off_t nextOffset, uint16 keyIndex, uint16 splitAt, int8 change)
|
TreeIterator::Update(off_t offset, off_t nextOffset, uint16 keyIndex,
|
||||||
|
uint16 splitAt, int8 change)
|
||||||
{
|
{
|
||||||
if (offset != fCurrentNodeOffset)
|
if (offset != fCurrentNodeOffset)
|
||||||
return;
|
return;
|
||||||
@@ -2158,7 +2150,7 @@ TreeIterator::Update(off_t offset, off_t nextOffset, uint16 keyIndex, uint16 spl
|
|||||||
if (keyIndex <= fCurrentKey)
|
if (keyIndex <= fCurrentKey)
|
||||||
fCurrentKey += change;
|
fCurrentKey += change;
|
||||||
|
|
||||||
// ToDo: duplicate handling!
|
// TODO: duplicate handling!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -273,7 +273,7 @@ class BPlusTree {
|
|||||||
int32 fNodeSize;
|
int32 fNodeSize;
|
||||||
bool fAllowDuplicates;
|
bool fAllowDuplicates;
|
||||||
status_t fStatus;
|
status_t fStatus;
|
||||||
SimpleLock fIteratorLock;
|
mutex fIteratorLock;
|
||||||
Chain<TreeIterator> fIterators;
|
Chain<TreeIterator> fIterators;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -441,15 +441,16 @@ AllocationGroup::Free(Transaction &transaction, uint16 start, int32 length)
|
|||||||
BlockAllocator::BlockAllocator(Volume *volume)
|
BlockAllocator::BlockAllocator(Volume *volume)
|
||||||
:
|
:
|
||||||
fVolume(volume),
|
fVolume(volume),
|
||||||
fLock("bfs allocator"),
|
|
||||||
fGroups(NULL),
|
fGroups(NULL),
|
||||||
fCheckBitmap(NULL)
|
fCheckBitmap(NULL)
|
||||||
{
|
{
|
||||||
|
mutex_init(&fLock, "bfs allocator");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BlockAllocator::~BlockAllocator()
|
BlockAllocator::~BlockAllocator()
|
||||||
{
|
{
|
||||||
|
mutex_destroy(&fLock);
|
||||||
delete[] fGroups;
|
delete[] fGroups;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -457,9 +458,6 @@ BlockAllocator::~BlockAllocator()
|
|||||||
status_t
|
status_t
|
||||||
BlockAllocator::Initialize(bool full)
|
BlockAllocator::Initialize(bool full)
|
||||||
{
|
{
|
||||||
if (fLock.InitCheck() < B_OK)
|
|
||||||
return B_ERROR;
|
|
||||||
|
|
||||||
fNumGroups = fVolume->AllocationGroups();
|
fNumGroups = fVolume->AllocationGroups();
|
||||||
fBlocksPerGroup = fVolume->SuperBlock().BlocksPerAllocationGroup();
|
fBlocksPerGroup = fVolume->SuperBlock().BlocksPerAllocationGroup();
|
||||||
fGroups = new AllocationGroup[fNumGroups];
|
fGroups = new AllocationGroup[fNumGroups];
|
||||||
@@ -469,8 +467,8 @@ BlockAllocator::Initialize(bool full)
|
|||||||
if (!full)
|
if (!full)
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
fLock.Lock();
|
mutex_lock(&fLock);
|
||||||
// the lock will be released by the initialize() function
|
// the lock will be released by the _Initialize() method
|
||||||
|
|
||||||
thread_id id = spawn_kernel_thread((thread_func)BlockAllocator::_Initialize,
|
thread_id id = spawn_kernel_thread((thread_func)BlockAllocator::_Initialize,
|
||||||
"bfs block allocator", B_LOW_PRIORITY, (void *)this);
|
"bfs block allocator", B_LOW_PRIORITY, (void *)this);
|
||||||
@@ -547,7 +545,7 @@ BlockAllocator::_Initialize(BlockAllocator *allocator)
|
|||||||
|
|
||||||
uint32 *buffer = (uint32 *)malloc(blocks << blockShift);
|
uint32 *buffer = (uint32 *)malloc(blocks << blockShift);
|
||||||
if (buffer == NULL) {
|
if (buffer == NULL) {
|
||||||
allocator->fLock.Unlock();
|
mutex_unlock(&allocator->fLock);
|
||||||
RETURN_ERROR(B_NO_MEMORY);
|
RETURN_ERROR(B_NO_MEMORY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -621,7 +619,7 @@ BlockAllocator::_Initialize(BlockAllocator *allocator)
|
|||||||
volume->SuperBlock().used_blocks = HOST_ENDIAN_TO_BFS_INT64(usedBlocks);
|
volume->SuperBlock().used_blocks = HOST_ENDIAN_TO_BFS_INT64(usedBlocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
allocator->fLock.Unlock();
|
mutex_unlock(&allocator->fLock);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -636,7 +634,7 @@ BlockAllocator::AllocateBlocks(Transaction &transaction, int32 group,
|
|||||||
FUNCTION_START(("group = %ld, start = %u, maximum = %u, minimum = %u\n", group, start, maximum, minimum));
|
FUNCTION_START(("group = %ld, start = %u, maximum = %u, minimum = %u\n", group, start, maximum, minimum));
|
||||||
|
|
||||||
AllocationBlock cached(fVolume);
|
AllocationBlock cached(fVolume);
|
||||||
Locker lock(fLock);
|
MutexLocker lock(fLock);
|
||||||
|
|
||||||
// The first scan through all allocation groups will look for the
|
// The first scan through all allocation groups will look for the
|
||||||
// wanted maximum of blocks, the second scan will just look to
|
// wanted maximum of blocks, the second scan will just look to
|
||||||
@@ -821,7 +819,7 @@ BlockAllocator::Allocate(Transaction &transaction, Inode *inode, off_t numBlocks
|
|||||||
status_t
|
status_t
|
||||||
BlockAllocator::Free(Transaction &transaction, block_run run)
|
BlockAllocator::Free(Transaction &transaction, block_run run)
|
||||||
{
|
{
|
||||||
Locker lock(fLock);
|
MutexLocker lock(fLock);
|
||||||
|
|
||||||
int32 group = run.AllocationGroup();
|
int32 group = run.AllocationGroup();
|
||||||
uint16 start = run.Start();
|
uint16 start = run.Start();
|
||||||
@@ -896,14 +894,14 @@ BlockAllocator::StartChecking(check_control *control)
|
|||||||
if (!_IsValidCheckControl(control))
|
if (!_IsValidCheckControl(control))
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
status_t status = fLock.Lock();
|
status_t status = mutex_lock(&fLock);
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
size_t size = BitmapSize();
|
size_t size = BitmapSize();
|
||||||
fCheckBitmap = (uint32 *)malloc(size);
|
fCheckBitmap = (uint32 *)malloc(size);
|
||||||
if (fCheckBitmap == NULL) {
|
if (fCheckBitmap == NULL) {
|
||||||
fLock.Unlock();
|
mutex_unlock(&fLock);
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -911,7 +909,7 @@ BlockAllocator::StartChecking(check_control *control)
|
|||||||
if (cookie == NULL) {
|
if (cookie == NULL) {
|
||||||
free(fCheckBitmap);
|
free(fCheckBitmap);
|
||||||
fCheckBitmap = NULL;
|
fCheckBitmap = NULL;
|
||||||
fLock.Unlock();
|
mutex_unlock(&fLock);
|
||||||
|
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
}
|
}
|
||||||
@@ -1013,7 +1011,7 @@ BlockAllocator::StopChecking(check_control *control)
|
|||||||
fCheckBitmap = NULL;
|
fCheckBitmap = NULL;
|
||||||
fCheckCookie = NULL;
|
fCheckCookie = NULL;
|
||||||
delete cookie;
|
delete cookie;
|
||||||
fLock.Unlock();
|
mutex_unlock(&fLock);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -1113,7 +1111,7 @@ BlockAllocator::CheckNextNode(check_control *control)
|
|||||||
|
|
||||||
// check if the inode's name is the same as in the b+tree
|
// check if the inode's name is the same as in the b+tree
|
||||||
if (inode->IsRegularNode()) {
|
if (inode->IsRegularNode()) {
|
||||||
SimpleLocker locker(inode->SmallDataLock());
|
RecursiveLocker locker(inode->SmallDataLock());
|
||||||
NodeGetter node(fVolume, inode);
|
NodeGetter node(fVolume, inode);
|
||||||
|
|
||||||
const char *localName = inode->Name(node.Node());
|
const char *localName = inode->Name(node.Node());
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
#define BLOCK_ALLOCATOR_H
|
#define BLOCK_ALLOCATOR_H
|
||||||
|
|
||||||
|
|
||||||
#include "Lock.h"
|
#include "system_dependencies.h"
|
||||||
|
|
||||||
|
|
||||||
class AllocationGroup;
|
class AllocationGroup;
|
||||||
@@ -57,7 +57,7 @@ class BlockAllocator {
|
|||||||
static status_t _Initialize(BlockAllocator *);
|
static status_t _Initialize(BlockAllocator *);
|
||||||
|
|
||||||
Volume *fVolume;
|
Volume *fVolume;
|
||||||
Semaphore fLock;
|
mutex fLock;
|
||||||
AllocationGroup *fGroups;
|
AllocationGroup *fGroups;
|
||||||
int32 fNumGroups;
|
int32 fNumGroups;
|
||||||
uint32 fBlocksPerGroup;
|
uint32 fBlocksPerGroup;
|
||||||
|
|||||||
@@ -330,6 +330,8 @@ Inode::Inode(Volume *volume, ino_t id)
|
|||||||
(int)BlockRun().AllocationGroup(), BlockRun().Start());
|
(int)BlockRun().AllocationGroup(), BlockRun().Start());
|
||||||
fLock.Initialize(lockName);
|
fLock.Initialize(lockName);
|
||||||
|
|
||||||
|
recursive_lock_init(&fSmallDataLock, "bfs inode small data");
|
||||||
|
|
||||||
// these two will help to maintain the indices
|
// these two will help to maintain the indices
|
||||||
fOldSize = Size();
|
fOldSize = Size();
|
||||||
fOldLastModified = LastModified();
|
fOldLastModified = LastModified();
|
||||||
@@ -361,6 +363,8 @@ Inode::Inode(Volume *volume, Transaction &transaction, ino_t id, mode_t mode,
|
|||||||
(int)run.AllocationGroup(), run.Start());
|
(int)run.AllocationGroup(), run.Start());
|
||||||
fLock.Initialize(lockName);
|
fLock.Initialize(lockName);
|
||||||
|
|
||||||
|
recursive_lock_init(&fSmallDataLock, "bfs inode small data");
|
||||||
|
|
||||||
NodeGetter node(volume, transaction, this, true);
|
NodeGetter node(volume, transaction, this, true);
|
||||||
memset(&fNode, 0, sizeof(bfs_inode));
|
memset(&fNode, 0, sizeof(bfs_inode));
|
||||||
|
|
||||||
@@ -482,24 +486,16 @@ Inode::CheckPermissions(int accessMode) const
|
|||||||
void
|
void
|
||||||
Inode::_AddIterator(AttributeIterator *iterator)
|
Inode::_AddIterator(AttributeIterator *iterator)
|
||||||
{
|
{
|
||||||
if (fSmallDataLock.Lock() < B_OK)
|
RecursiveLocker _(fSmallDataLock);
|
||||||
return;
|
|
||||||
|
|
||||||
fIterators.Add(iterator);
|
fIterators.Add(iterator);
|
||||||
|
|
||||||
fSmallDataLock.Unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Inode::_RemoveIterator(AttributeIterator *iterator)
|
Inode::_RemoveIterator(AttributeIterator *iterator)
|
||||||
{
|
{
|
||||||
if (fSmallDataLock.Lock() < B_OK)
|
RecursiveLocker _(fSmallDataLock);
|
||||||
return;
|
|
||||||
|
|
||||||
fIterators.Remove(iterator);
|
fIterators.Remove(iterator);
|
||||||
|
|
||||||
fSmallDataLock.Unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -511,7 +507,7 @@ status_t
|
|||||||
Inode::_MakeSpaceForSmallData(Transaction &transaction, bfs_inode *node,
|
Inode::_MakeSpaceForSmallData(Transaction &transaction, bfs_inode *node,
|
||||||
const char *name, int32 bytes)
|
const char *name, int32 bytes)
|
||||||
{
|
{
|
||||||
ASSERT(fSmallDataLock.IsLocked());
|
ASSERT_LOCKED_RECURSIVE(&fSmallDataLock);
|
||||||
|
|
||||||
while (bytes > 0) {
|
while (bytes > 0) {
|
||||||
small_data *item = node->SmallDataStart(), *max = NULL;
|
small_data *item = node->SmallDataStart(), *max = NULL;
|
||||||
@@ -575,7 +571,7 @@ Inode::_MakeSpaceForSmallData(Transaction &transaction, bfs_inode *node,
|
|||||||
status_t
|
status_t
|
||||||
Inode::_RemoveSmallData(bfs_inode *node, small_data *item, int32 index)
|
Inode::_RemoveSmallData(bfs_inode *node, small_data *item, int32 index)
|
||||||
{
|
{
|
||||||
ASSERT(fSmallDataLock.IsLocked());
|
ASSERT_LOCKED_RECURSIVE(&fSmallDataLock);
|
||||||
|
|
||||||
small_data *next = item->Next();
|
small_data *next = item->Next();
|
||||||
if (!next->IsLast(node)) {
|
if (!next->IsLast(node)) {
|
||||||
@@ -617,7 +613,7 @@ Inode::_RemoveSmallData(Transaction &transaction, NodeGetter &nodeGetter,
|
|||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
bfs_inode *node = nodeGetter.WritableNode();
|
bfs_inode *node = nodeGetter.WritableNode();
|
||||||
SimpleLocker locker(fSmallDataLock);
|
RecursiveLocker locker(fSmallDataLock);
|
||||||
|
|
||||||
// search for the small_data item
|
// search for the small_data item
|
||||||
|
|
||||||
@@ -668,7 +664,7 @@ Inode::_AddSmallData(Transaction &transaction, NodeGetter &nodeGetter,
|
|||||||
return B_DEVICE_FULL;
|
return B_DEVICE_FULL;
|
||||||
|
|
||||||
nodeGetter.MakeWritable(transaction);
|
nodeGetter.MakeWritable(transaction);
|
||||||
SimpleLocker locker(fSmallDataLock);
|
RecursiveLocker locker(fSmallDataLock);
|
||||||
|
|
||||||
// Find the last item or one with the same name we have to add
|
// Find the last item or one with the same name we have to add
|
||||||
small_data *item = node->SmallDataStart();
|
small_data *item = node->SmallDataStart();
|
||||||
@@ -809,7 +805,7 @@ Inode::_GetNextSmallData(bfs_inode *node, small_data **_smallData) const
|
|||||||
if (node == NULL)
|
if (node == NULL)
|
||||||
RETURN_ERROR(B_BAD_VALUE);
|
RETURN_ERROR(B_BAD_VALUE);
|
||||||
|
|
||||||
ASSERT(fSmallDataLock.IsLocked());
|
ASSERT_LOCKED_RECURSIVE(&fSmallDataLock);
|
||||||
|
|
||||||
small_data *data = *_smallData;
|
small_data *data = *_smallData;
|
||||||
|
|
||||||
@@ -836,7 +832,7 @@ Inode::_GetNextSmallData(bfs_inode *node, small_data **_smallData) const
|
|||||||
small_data *
|
small_data *
|
||||||
Inode::FindSmallData(const bfs_inode *node, const char *name) const
|
Inode::FindSmallData(const bfs_inode *node, const char *name) const
|
||||||
{
|
{
|
||||||
ASSERT(fSmallDataLock.IsLocked());
|
ASSERT_LOCKED_RECURSIVE(&fSmallDataLock);
|
||||||
|
|
||||||
small_data *smallData = NULL;
|
small_data *smallData = NULL;
|
||||||
while (_GetNextSmallData(const_cast<bfs_inode *>(node), &smallData)
|
while (_GetNextSmallData(const_cast<bfs_inode *>(node), &smallData)
|
||||||
@@ -855,7 +851,7 @@ Inode::FindSmallData(const bfs_inode *node, const char *name) const
|
|||||||
const char *
|
const char *
|
||||||
Inode::Name(const bfs_inode *node) const
|
Inode::Name(const bfs_inode *node) const
|
||||||
{
|
{
|
||||||
ASSERT(fSmallDataLock.IsLocked());
|
ASSERT_LOCKED_RECURSIVE(&fSmallDataLock);
|
||||||
|
|
||||||
small_data *smallData = NULL;
|
small_data *smallData = NULL;
|
||||||
while (_GetNextSmallData((bfs_inode *)node, &smallData) == B_OK) {
|
while (_GetNextSmallData((bfs_inode *)node, &smallData) == B_OK) {
|
||||||
@@ -874,7 +870,7 @@ status_t
|
|||||||
Inode::GetName(char *buffer, size_t size) const
|
Inode::GetName(char *buffer, size_t size) const
|
||||||
{
|
{
|
||||||
NodeGetter node(fVolume, this);
|
NodeGetter node(fVolume, this);
|
||||||
SimpleLocker locker(fSmallDataLock);
|
RecursiveLocker locker(fSmallDataLock);
|
||||||
|
|
||||||
const char *name = Name(node.Node());
|
const char *name = Name(node.Node());
|
||||||
if (name == NULL)
|
if (name == NULL)
|
||||||
@@ -966,7 +962,7 @@ Inode::ReadAttribute(const char *name, int32 type, off_t pos, uint8 *buffer,
|
|||||||
// search in the small_data section (which has to be locked first)
|
// search in the small_data section (which has to be locked first)
|
||||||
{
|
{
|
||||||
NodeGetter node(fVolume, this);
|
NodeGetter node(fVolume, this);
|
||||||
SimpleLocker locker(fSmallDataLock);
|
RecursiveLocker locker(fSmallDataLock);
|
||||||
|
|
||||||
small_data *smallData = FindSmallData(node.Node(), name);
|
small_data *smallData = FindSmallData(node.Node(), name);
|
||||||
if (smallData != NULL) {
|
if (smallData != NULL) {
|
||||||
@@ -1025,7 +1021,7 @@ Inode::WriteAttribute(Transaction &transaction, const char *name, int32 type,
|
|||||||
if (GetAttribute(name, &attribute) < B_OK) {
|
if (GetAttribute(name, &attribute) < B_OK) {
|
||||||
// save the old attribute data
|
// save the old attribute data
|
||||||
NodeGetter node(fVolume, transaction, this);
|
NodeGetter node(fVolume, transaction, this);
|
||||||
fSmallDataLock.Lock();
|
recursive_lock_lock(&fSmallDataLock);
|
||||||
|
|
||||||
small_data *smallData = FindSmallData(node.Node(), name);
|
small_data *smallData = FindSmallData(node.Node(), name);
|
||||||
if (smallData != NULL) {
|
if (smallData != NULL) {
|
||||||
@@ -1036,7 +1032,7 @@ Inode::WriteAttribute(Transaction &transaction, const char *name, int32 type,
|
|||||||
memcpy(oldData = oldBuffer, smallData->Data(), oldLength);
|
memcpy(oldData = oldBuffer, smallData->Data(), oldLength);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fSmallDataLock.Unlock();
|
recursive_lock_unlock(&fSmallDataLock);
|
||||||
|
|
||||||
// if the attribute doesn't exist yet (as a file), try to put it in the
|
// if the attribute doesn't exist yet (as a file), try to put it in the
|
||||||
// small_data section first - if that fails (due to insufficent space),
|
// small_data section first - if that fails (due to insufficent space),
|
||||||
@@ -1128,7 +1124,7 @@ Inode::RemoveAttribute(Transaction &transaction, const char *name)
|
|||||||
|
|
||||||
// update index for attributes in the small_data section
|
// update index for attributes in the small_data section
|
||||||
{
|
{
|
||||||
fSmallDataLock.Lock();
|
RecursiveLocker _(fSmallDataLock);
|
||||||
|
|
||||||
small_data *smallData = FindSmallData(node.Node(), name);
|
small_data *smallData = FindSmallData(node.Node(), name);
|
||||||
if (smallData != NULL) {
|
if (smallData != NULL) {
|
||||||
@@ -1138,7 +1134,6 @@ Inode::RemoveAttribute(Transaction &transaction, const char *name)
|
|||||||
index.Update(transaction, name, smallData->Type(),
|
index.Update(transaction, name, smallData->Type(),
|
||||||
smallData->Data(), length, NULL, 0, this);
|
smallData->Data(), length, NULL, 0, this);
|
||||||
}
|
}
|
||||||
fSmallDataLock.Unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t status = _RemoveSmallData(transaction, node, name);
|
status_t status = _RemoveSmallData(transaction, node, name);
|
||||||
@@ -2561,7 +2556,7 @@ AttributeIterator::GetNext(char *name, size_t *_length, uint32 *_type,
|
|||||||
const bfs_inode *node = nodeGetter.Node();
|
const bfs_inode *node = nodeGetter.Node();
|
||||||
const small_data *item = ((bfs_inode *)node)->SmallDataStart();
|
const small_data *item = ((bfs_inode *)node)->SmallDataStart();
|
||||||
|
|
||||||
fInode->SmallDataLock().Lock();
|
RecursiveLocker _(&fInode->SmallDataLock());
|
||||||
|
|
||||||
int32 i = 0;
|
int32 i = 0;
|
||||||
for (;;item = item->Next()) {
|
for (;;item = item->Next()) {
|
||||||
@@ -2589,8 +2584,6 @@ AttributeIterator::GetNext(char *name, size_t *_length, uint32 *_type,
|
|||||||
fCurrentSmallData = -1;
|
fCurrentSmallData = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fInode->SmallDataLock().Unlock();
|
|
||||||
|
|
||||||
if (fCurrentSmallData != -1)
|
if (fCurrentSmallData != -1)
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ class Inode {
|
|||||||
off_t BlockNumber() const { return fVolume->VnodeToBlock(fID); }
|
off_t BlockNumber() const { return fVolume->VnodeToBlock(fID); }
|
||||||
|
|
||||||
ReadWriteLock &Lock() { return fLock; }
|
ReadWriteLock &Lock() { return fLock; }
|
||||||
SimpleLock &SmallDataLock() { return fSmallDataLock; }
|
recursive_lock &SmallDataLock() { return fSmallDataLock; }
|
||||||
status_t WriteBack(Transaction &transaction);
|
status_t WriteBack(Transaction &transaction);
|
||||||
|
|
||||||
bool IsContainer() const
|
bool IsContainer() const
|
||||||
@@ -207,7 +207,7 @@ class Inode {
|
|||||||
// we need those values to ensure we will remove
|
// we need those values to ensure we will remove
|
||||||
// the correct keys from the indices
|
// the correct keys from the indices
|
||||||
|
|
||||||
mutable SimpleLock fSmallDataLock;
|
mutable recursive_lock fSmallDataLock;
|
||||||
Chain<AttributeIterator> fIterators;
|
Chain<AttributeIterator> fIterators;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -24,10 +24,9 @@ SubDir HAIKU_TOP src add-ons kernel file_systems bfs ;
|
|||||||
SubDirC++Flags $(defines) -Wall -Wno-multichar ;
|
SubDirC++Flags $(defines) -Wall -Wno-multichar ;
|
||||||
}
|
}
|
||||||
|
|
||||||
UsePrivateHeaders [ FDirName kernel ] ; # For kernel_cpp.cpp
|
UsePrivateKernelHeaders ;
|
||||||
UsePrivateHeaders [ FDirName kernel disk_device_manager ] ;
|
UsePrivateHeaders [ FDirName kernel disk_device_manager ] ;
|
||||||
UsePrivateHeaders [ FDirName shared ] ;
|
UsePrivateHeaders shared storage ;
|
||||||
UsePrivateHeaders [ FDirName storage ] ;
|
|
||||||
|
|
||||||
KernelAddon bfs :
|
KernelAddon bfs :
|
||||||
bfs_disk_system.cpp
|
bfs_disk_system.cpp
|
||||||
|
|||||||
@@ -395,7 +395,6 @@ RunArrays::MaxArrayLength()
|
|||||||
Journal::Journal(Volume *volume)
|
Journal::Journal(Volume *volume)
|
||||||
:
|
:
|
||||||
fVolume(volume),
|
fVolume(volume),
|
||||||
fLock("bfs journal"),
|
|
||||||
fOwner(NULL),
|
fOwner(NULL),
|
||||||
fLogSize(volume->Log().Length()),
|
fLogSize(volume->Log().Length()),
|
||||||
fMaxTransactionSize(fLogSize / 2 - 5),
|
fMaxTransactionSize(fLogSize / 2 - 5),
|
||||||
@@ -403,19 +402,24 @@ Journal::Journal(Volume *volume)
|
|||||||
fUnwrittenTransactions(0),
|
fUnwrittenTransactions(0),
|
||||||
fHasSubtransaction(false)
|
fHasSubtransaction(false)
|
||||||
{
|
{
|
||||||
|
recursive_lock_init(&fLock, "bfs journal");
|
||||||
|
mutex_init(&fEntriesLock, "bfs journal entries");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Journal::~Journal()
|
Journal::~Journal()
|
||||||
{
|
{
|
||||||
FlushLogAndBlocks();
|
FlushLogAndBlocks();
|
||||||
|
|
||||||
|
recursive_lock_destroy(&fLock);
|
||||||
|
mutex_destroy(&fEntriesLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Journal::InitCheck()
|
Journal::InitCheck()
|
||||||
{
|
{
|
||||||
return fLock.InitCheck();
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -605,7 +609,7 @@ Journal::_TransactionWritten(int32 transactionID, int32 event, void *_logEntry)
|
|||||||
|
|
||||||
// Set log_start pointer if possible...
|
// Set log_start pointer if possible...
|
||||||
|
|
||||||
journal->fEntriesLock.Lock();
|
mutex_lock(&journal->fEntriesLock);
|
||||||
|
|
||||||
if (logEntry == journal->fEntries.First()) {
|
if (logEntry == journal->fEntries.First()) {
|
||||||
LogEntry *next = journal->fEntries.GetNext(logEntry);
|
LogEntry *next = journal->fEntries.GetNext(logEntry);
|
||||||
@@ -624,7 +628,7 @@ Journal::_TransactionWritten(int32 transactionID, int32 event, void *_logEntry)
|
|||||||
|
|
||||||
journal->fUsed -= logEntry->Length();
|
journal->fUsed -= logEntry->Length();
|
||||||
journal->fEntries.Remove(logEntry);
|
journal->fEntries.Remove(logEntry);
|
||||||
journal->fEntriesLock.Unlock();
|
mutex_unlock(&journal->fEntriesLock);
|
||||||
|
|
||||||
delete logEntry;
|
delete logEntry;
|
||||||
|
|
||||||
@@ -839,10 +843,10 @@ Journal::_WriteTransactionToLog()
|
|||||||
// at this point, we can finally end the transaction - we're in
|
// at this point, we can finally end the transaction - we're in
|
||||||
// a guaranteed valid state
|
// a guaranteed valid state
|
||||||
|
|
||||||
fEntriesLock.Lock();
|
mutex_lock(&fEntriesLock);
|
||||||
fEntries.Add(logEntry);
|
fEntries.Add(logEntry);
|
||||||
fUsed += logEntry->Length();
|
fUsed += logEntry->Length();
|
||||||
fEntriesLock.Unlock();
|
mutex_unlock(&fEntriesLock);
|
||||||
|
|
||||||
if (detached) {
|
if (detached) {
|
||||||
fTransactionID = cache_detach_sub_transaction(fVolume->BlockCache(),
|
fTransactionID = cache_detach_sub_transaction(fVolume->BlockCache(),
|
||||||
@@ -864,13 +868,14 @@ Journal::_WriteTransactionToLog()
|
|||||||
status_t
|
status_t
|
||||||
Journal::_FlushLog(bool canWait, bool flushBlocks)
|
Journal::_FlushLog(bool canWait, bool flushBlocks)
|
||||||
{
|
{
|
||||||
status_t status = canWait ? fLock.Lock() : fLock.LockWithTimeout(0);
|
status_t status = canWait ? recursive_lock_lock(&fLock)
|
||||||
|
: recursive_lock_trylock(&fLock);
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
if (fLock.OwnerCount() > 1) {
|
if (recursive_lock_get_recursion(&fLock) > 1) {
|
||||||
// whoa, FlushLogAndBlocks() was called from inside a transaction
|
// whoa, FlushLogAndBlocks() was called from inside a transaction
|
||||||
fLock.Unlock();
|
recursive_lock_unlock(&fLock);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -885,7 +890,7 @@ Journal::_FlushLog(bool canWait, bool flushBlocks)
|
|||||||
if (flushBlocks)
|
if (flushBlocks)
|
||||||
status = fVolume->FlushDevice();
|
status = fVolume->FlushDevice();
|
||||||
|
|
||||||
fLock.Unlock();
|
recursive_lock_unlock(&fLock);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -903,11 +908,11 @@ Journal::FlushLogAndBlocks()
|
|||||||
status_t
|
status_t
|
||||||
Journal::Lock(Transaction *owner)
|
Journal::Lock(Transaction *owner)
|
||||||
{
|
{
|
||||||
status_t status = fLock.Lock();
|
status_t status = recursive_lock_lock(&fLock);
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
if (fLock.OwnerCount() > 1) {
|
if (recursive_lock_get_recursion(&fLock) > 1) {
|
||||||
// we'll just use the current transaction again
|
// we'll just use the current transaction again
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -929,7 +934,7 @@ Journal::Lock(Transaction *owner)
|
|||||||
fTransactionID = cache_start_transaction(fVolume->BlockCache());
|
fTransactionID = cache_start_transaction(fVolume->BlockCache());
|
||||||
|
|
||||||
if (fTransactionID < B_OK) {
|
if (fTransactionID < B_OK) {
|
||||||
fLock.Unlock();
|
recursive_lock_unlock(&fLock);
|
||||||
return fTransactionID;
|
return fTransactionID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -943,7 +948,7 @@ Journal::Lock(Transaction *owner)
|
|||||||
void
|
void
|
||||||
Journal::Unlock(Transaction *owner, bool success)
|
Journal::Unlock(Transaction *owner, bool success)
|
||||||
{
|
{
|
||||||
if (fLock.OwnerCount() == 1) {
|
if (recursive_lock_get_recursion(&fLock) == 1) {
|
||||||
// we only end the transaction if we would really unlock it
|
// we only end the transaction if we would really unlock it
|
||||||
// ToDo: what about failing transactions that do not unlock?
|
// ToDo: what about failing transactions that do not unlock?
|
||||||
_TransactionDone(success);
|
_TransactionDone(success);
|
||||||
@@ -952,7 +957,7 @@ Journal::Unlock(Transaction *owner, bool success)
|
|||||||
fOwner = NULL;
|
fOwner = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
fLock.Unlock();
|
recursive_lock_unlock(&fLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
#include "Volume.h"
|
#include "Volume.h"
|
||||||
#include "Chain.h"
|
#include "Chain.h"
|
||||||
|
#include "Lock.h"
|
||||||
#include "Utility.h"
|
#include "Utility.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -69,11 +70,11 @@ class Journal {
|
|||||||
void *_journal);
|
void *_journal);
|
||||||
|
|
||||||
Volume *fVolume;
|
Volume *fVolume;
|
||||||
RecursiveLock fLock;
|
recursive_lock fLock;
|
||||||
Transaction *fOwner;
|
Transaction *fOwner;
|
||||||
uint32 fLogSize, fMaxTransactionSize, fUsed;
|
uint32 fLogSize, fMaxTransactionSize, fUsed;
|
||||||
int32 fUnwrittenTransactions;
|
int32 fUnwrittenTransactions;
|
||||||
SimpleLock fEntriesLock;
|
mutex fEntriesLock;
|
||||||
LogEntryList fEntries;
|
LogEntryList fEntries;
|
||||||
bigtime_t fTimestamp;
|
bigtime_t fTimestamp;
|
||||||
int32 fTransactionID;
|
int32 fTransactionID;
|
||||||
|
|||||||
@@ -26,201 +26,7 @@
|
|||||||
# error implement recursive write locking first
|
# error implement recursive write locking first
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class Semaphore {
|
// #pragma mark - Many Reader/Single Writer Lock
|
||||||
public:
|
|
||||||
Semaphore(const char *name)
|
|
||||||
:
|
|
||||||
#ifdef USE_BENAPHORE
|
|
||||||
fSemaphore(create_sem(0, name)),
|
|
||||||
fCount(1)
|
|
||||||
#else
|
|
||||||
fSemaphore(create_sem(1, name))
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~Semaphore()
|
|
||||||
{
|
|
||||||
delete_sem(fSemaphore);
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t InitCheck()
|
|
||||||
{
|
|
||||||
if (fSemaphore < B_OK)
|
|
||||||
return fSemaphore;
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t Lock()
|
|
||||||
{
|
|
||||||
#ifdef USE_BENAPHORE
|
|
||||||
if (atomic_add(&fCount, -1) <= 0)
|
|
||||||
#endif
|
|
||||||
return acquire_sem(fSemaphore);
|
|
||||||
#ifdef USE_BENAPHORE
|
|
||||||
return B_OK;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t Unlock()
|
|
||||||
{
|
|
||||||
#ifdef USE_BENAPHORE
|
|
||||||
if (atomic_add(&fCount, 1) < 0)
|
|
||||||
#endif
|
|
||||||
return release_sem(fSemaphore);
|
|
||||||
#ifdef USE_BENAPHORE
|
|
||||||
return B_OK;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
sem_id fSemaphore;
|
|
||||||
#ifdef USE_BENAPHORE
|
|
||||||
vint32 fCount;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
// a convenience class to lock a Semaphore object
|
|
||||||
|
|
||||||
class Locker {
|
|
||||||
public:
|
|
||||||
Locker(Semaphore &lock)
|
|
||||||
: fLock(lock)
|
|
||||||
{
|
|
||||||
fStatus = lock.Lock();
|
|
||||||
ASSERT(fStatus == B_OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
~Locker()
|
|
||||||
{
|
|
||||||
if (fStatus == B_OK)
|
|
||||||
fLock.Unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t Status() const
|
|
||||||
{
|
|
||||||
return fStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Semaphore &fLock;
|
|
||||||
status_t fStatus;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - Recursive Lock
|
|
||||||
|
|
||||||
class RecursiveLock {
|
|
||||||
public:
|
|
||||||
RecursiveLock(const char *name)
|
|
||||||
:
|
|
||||||
#ifdef USE_BENAPHORE
|
|
||||||
fSemaphore(create_sem(0, name)),
|
|
||||||
fCount(1),
|
|
||||||
#else
|
|
||||||
fSemaphore(create_sem(1, name)),
|
|
||||||
#endif
|
|
||||||
fOwner(-1)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t InitCheck() const
|
|
||||||
{
|
|
||||||
if (fSemaphore < B_OK)
|
|
||||||
return fSemaphore;
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t LockWithTimeout(bigtime_t timeout)
|
|
||||||
{
|
|
||||||
thread_id thread = find_thread(NULL);
|
|
||||||
if (thread == fOwner) {
|
|
||||||
fOwnerCount++;
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t status;
|
|
||||||
#ifdef USE_BENAPHORE
|
|
||||||
if (atomic_add(&fCount, -1) > 0)
|
|
||||||
status = B_OK;
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
status = acquire_sem_etc(fSemaphore, 1, B_RELATIVE_TIMEOUT, timeout);
|
|
||||||
|
|
||||||
if (status == B_OK) {
|
|
||||||
fOwner = thread;
|
|
||||||
fOwnerCount = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t Lock()
|
|
||||||
{
|
|
||||||
return LockWithTimeout(B_INFINITE_TIMEOUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t Unlock()
|
|
||||||
{
|
|
||||||
thread_id thread = find_thread(NULL);
|
|
||||||
if (thread != fOwner) {
|
|
||||||
panic("RecursiveLock unlocked by %d, owned by %d\n", (int)thread, (int)fOwner);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (--fOwnerCount == 0) {
|
|
||||||
fOwner = -1;
|
|
||||||
#ifdef USE_BENAPHORE
|
|
||||||
if (atomic_add(&fCount, 1) < 0)
|
|
||||||
#endif
|
|
||||||
return release_sem(fSemaphore);
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
thread_id Owner() const { return fOwner; }
|
|
||||||
int32 OwnerCount() const { return fOwnerCount; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
sem_id fSemaphore;
|
|
||||||
#ifdef USE_BENAPHORE
|
|
||||||
vint32 fCount;
|
|
||||||
#endif
|
|
||||||
thread_id fOwner;
|
|
||||||
int32 fOwnerCount;
|
|
||||||
};
|
|
||||||
|
|
||||||
// a convenience class to lock an RecursiveLock object
|
|
||||||
|
|
||||||
class RecursiveLocker {
|
|
||||||
public:
|
|
||||||
RecursiveLocker(RecursiveLock &lock)
|
|
||||||
: fLock(lock)
|
|
||||||
{
|
|
||||||
fStatus = lock.Lock();
|
|
||||||
ASSERT(fStatus == B_OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
~RecursiveLocker()
|
|
||||||
{
|
|
||||||
if (fStatus == B_OK)
|
|
||||||
fLock.Unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t Status() const
|
|
||||||
{
|
|
||||||
return fStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
RecursiveLock &fLock;
|
|
||||||
status_t fStatus;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//**** Many Reader/Single Writer Lock
|
|
||||||
|
|
||||||
// This is a "fast" implementation of a single writer/many reader
|
// This is a "fast" implementation of a single writer/many reader
|
||||||
// locking scheme. It's fast because it uses the benaphore idea
|
// locking scheme. It's fast because it uses the benaphore idea
|
||||||
@@ -523,78 +329,4 @@ class WriteLocked {
|
|||||||
status_t fStatus;
|
status_t fStatus;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// A simple locking structure that doesn't use a semaphore - it's useful
|
|
||||||
// if you have to protect critical parts with a short runtime.
|
|
||||||
// It also allows to nest several locks for the same thread.
|
|
||||||
|
|
||||||
class SimpleLock {
|
|
||||||
public:
|
|
||||||
SimpleLock()
|
|
||||||
:
|
|
||||||
fHolder(-1),
|
|
||||||
fCount(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t Lock(bigtime_t time = 500)
|
|
||||||
{
|
|
||||||
int32 thisThread = find_thread(NULL);
|
|
||||||
int32 current;
|
|
||||||
while (1) {
|
|
||||||
/*if (fHolder == -1) {
|
|
||||||
current = fHolder;
|
|
||||||
fHolder = thisThread;
|
|
||||||
}*/
|
|
||||||
current = atomic_test_and_set(&fHolder, thisThread, -1);
|
|
||||||
if (current == -1)
|
|
||||||
break;
|
|
||||||
if (current == thisThread)
|
|
||||||
break;
|
|
||||||
|
|
||||||
snooze(time);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToDo: the lock cannot fail currently! We may want
|
|
||||||
// to change this
|
|
||||||
atomic_add(&fCount, 1);
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Unlock()
|
|
||||||
{
|
|
||||||
if (atomic_add(&fCount, -1) == 1)
|
|
||||||
atomic_set(&fHolder, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsLocked() const
|
|
||||||
{
|
|
||||||
return fHolder == find_thread(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
vint32 fHolder;
|
|
||||||
vint32 fCount;
|
|
||||||
};
|
|
||||||
|
|
||||||
// A convenience class to lock the SimpleLock, note the
|
|
||||||
// different timing compared to the direct call
|
|
||||||
|
|
||||||
class SimpleLocker {
|
|
||||||
public:
|
|
||||||
SimpleLocker(SimpleLock &lock,bigtime_t time = 1000)
|
|
||||||
: fLock(lock)
|
|
||||||
{
|
|
||||||
lock.Lock(time);
|
|
||||||
}
|
|
||||||
|
|
||||||
~SimpleLocker()
|
|
||||||
{
|
|
||||||
fLock.Unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
SimpleLock &fLock;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* LOCK_H */
|
#endif /* LOCK_H */
|
||||||
|
|||||||
@@ -805,13 +805,13 @@ Equation::Match(Inode *inode, const char *attributeName, int32 type, const uint8
|
|||||||
// we need to lock before accessing Inode::Name()
|
// we need to lock before accessing Inode::Name()
|
||||||
nodeGetter.SetToNode(inode);
|
nodeGetter.SetToNode(inode);
|
||||||
|
|
||||||
inode->SmallDataLock().Lock();
|
recursive_lock_lock(&inode->SmallDataLock());
|
||||||
locked = true;
|
locked = true;
|
||||||
|
|
||||||
// if not, check for "fake" attributes, "name", "size", "last_modified",
|
// if not, check for "fake" attributes, "name", "size", "last_modified",
|
||||||
buffer = (uint8 *)inode->Name(nodeGetter.Node());
|
buffer = (uint8 *)inode->Name(nodeGetter.Node());
|
||||||
if (buffer == NULL) {
|
if (buffer == NULL) {
|
||||||
inode->SmallDataLock().Unlock();
|
recursive_lock_unlock(&inode->SmallDataLock());
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -837,7 +837,7 @@ Equation::Match(Inode *inode, const char *attributeName, int32 type, const uint8
|
|||||||
nodeGetter.SetToNode(inode);
|
nodeGetter.SetToNode(inode);
|
||||||
Inode *attribute;
|
Inode *attribute;
|
||||||
|
|
||||||
inode->SmallDataLock().Lock();
|
recursive_lock_lock(&inode->SmallDataLock());
|
||||||
small_data *smallData = inode->FindSmallData(nodeGetter.Node(), fAttribute);
|
small_data *smallData = inode->FindSmallData(nodeGetter.Node(), fAttribute);
|
||||||
if (smallData != NULL) {
|
if (smallData != NULL) {
|
||||||
buffer = smallData->Data();
|
buffer = smallData->Data();
|
||||||
@@ -846,7 +846,7 @@ Equation::Match(Inode *inode, const char *attributeName, int32 type, const uint8
|
|||||||
locked = true;
|
locked = true;
|
||||||
} else {
|
} else {
|
||||||
// needed to unlock the small_data section as fast as possible
|
// needed to unlock the small_data section as fast as possible
|
||||||
inode->SmallDataLock().Unlock();
|
recursive_lock_unlock(&inode->SmallDataLock());
|
||||||
nodeGetter.Unset();
|
nodeGetter.Unset();
|
||||||
|
|
||||||
if (inode->GetAttribute(fAttribute, &attribute) == B_OK) {
|
if (inode->GetAttribute(fAttribute, &attribute) == B_OK) {
|
||||||
@@ -872,7 +872,7 @@ Equation::Match(Inode *inode, const char *attributeName, int32 type, const uint8
|
|||||||
status = CompareTo(buffer, size) ? MATCH_OK : NO_MATCH;
|
status = CompareTo(buffer, size) ? MATCH_OK : NO_MATCH;
|
||||||
|
|
||||||
if (locked)
|
if (locked)
|
||||||
inode->SmallDataLock().Unlock();
|
recursive_lock_unlock(&inode->SmallDataLock());
|
||||||
|
|
||||||
RETURN_ERROR(status);
|
RETURN_ERROR(status);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -276,18 +276,20 @@ Volume::Volume(fs_volume *volume)
|
|||||||
:
|
:
|
||||||
fVolume(volume),
|
fVolume(volume),
|
||||||
fBlockAllocator(this),
|
fBlockAllocator(this),
|
||||||
fLock("bfs volume"),
|
|
||||||
fRootNode(NULL),
|
fRootNode(NULL),
|
||||||
fIndicesNode(NULL),
|
fIndicesNode(NULL),
|
||||||
fDirtyCachedBlocks(0),
|
fDirtyCachedBlocks(0),
|
||||||
fUniqueID(0),
|
fUniqueID(0),
|
||||||
fFlags(0)
|
fFlags(0)
|
||||||
{
|
{
|
||||||
|
mutex_init(&fLock, "bfs volume");
|
||||||
|
mutex_init(&fQueryLock, "bfs queries");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Volume::~Volume()
|
Volume::~Volume()
|
||||||
{
|
{
|
||||||
|
mutex_destroy(&fLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -516,16 +518,13 @@ Volume::UpdateLiveQueries(Inode *inode, const char *attribute, int32 type,
|
|||||||
const uint8 *oldKey, size_t oldLength, const uint8 *newKey,
|
const uint8 *oldKey, size_t oldLength, const uint8 *newKey,
|
||||||
size_t newLength)
|
size_t newLength)
|
||||||
{
|
{
|
||||||
if (fQueryLock.Lock() < B_OK)
|
MutexLocker _(fQueryLock);
|
||||||
return;
|
|
||||||
|
|
||||||
Query *query = NULL;
|
Query *query = NULL;
|
||||||
while ((query = fQueries.Next(query)) != NULL) {
|
while ((query = fQueries.Next(query)) != NULL) {
|
||||||
query->LiveUpdate(inode, attribute, type, oldKey, oldLength, newKey,
|
query->LiveUpdate(inode, attribute, type, oldKey, oldLength, newKey,
|
||||||
newLength);
|
newLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
fQueryLock.Unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -545,24 +544,16 @@ Volume::CheckForLiveQuery(const char *attribute)
|
|||||||
void
|
void
|
||||||
Volume::AddQuery(Query *query)
|
Volume::AddQuery(Query *query)
|
||||||
{
|
{
|
||||||
if (fQueryLock.Lock() < B_OK)
|
MutexLocker _(fQueryLock);
|
||||||
return;
|
|
||||||
|
|
||||||
fQueries.Add(query);
|
fQueries.Add(query);
|
||||||
|
|
||||||
fQueryLock.Unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Volume::RemoveQuery(Query *query)
|
Volume::RemoveQuery(Query *query)
|
||||||
{
|
{
|
||||||
if (fQueryLock.Lock() < B_OK)
|
MutexLocker _(fQueryLock);
|
||||||
return;
|
|
||||||
|
|
||||||
fQueries.Remove(query);
|
fQueries.Remove(query);
|
||||||
|
|
||||||
fQueryLock.Unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2001-2007, Axel Dörfler, axeld@pinc-software.de.
|
* Copyright 2001-2008, Axel Dörfler, axeld@pinc-software.de.
|
||||||
* This file may be used under the terms of the MIT License.
|
* This file may be used under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef VOLUME_H
|
#ifndef VOLUME_H
|
||||||
@@ -37,7 +37,7 @@ class Volume {
|
|||||||
bool IsValidSuperBlock();
|
bool IsValidSuperBlock();
|
||||||
bool IsReadOnly() const;
|
bool IsReadOnly() const;
|
||||||
void Panic();
|
void Panic();
|
||||||
RecursiveLock &Lock();
|
mutex &Lock();
|
||||||
|
|
||||||
block_run Root() const { return fSuperBlock.root_dir; }
|
block_run Root() const { return fSuperBlock.root_dir; }
|
||||||
Inode *RootNode() const { return fRootNode; }
|
Inode *RootNode() const { return fRootNode; }
|
||||||
@@ -117,7 +117,7 @@ class Volume {
|
|||||||
uint32 fAllocationGroupShift;
|
uint32 fAllocationGroupShift;
|
||||||
|
|
||||||
BlockAllocator fBlockAllocator;
|
BlockAllocator fBlockAllocator;
|
||||||
RecursiveLock fLock;
|
mutex fLock;
|
||||||
Journal *fJournal;
|
Journal *fJournal;
|
||||||
vint32 fLogStart, fLogEnd;
|
vint32 fLogStart, fLogEnd;
|
||||||
|
|
||||||
@@ -126,7 +126,7 @@ class Volume {
|
|||||||
|
|
||||||
vint32 fDirtyCachedBlocks;
|
vint32 fDirtyCachedBlocks;
|
||||||
|
|
||||||
SimpleLock fQueryLock;
|
mutex fQueryLock;
|
||||||
Chain<Query> fQueries;
|
Chain<Query> fQueries;
|
||||||
|
|
||||||
int32 fUniqueID;
|
int32 fUniqueID;
|
||||||
@@ -145,7 +145,7 @@ Volume::IsReadOnly() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline RecursiveLock &
|
inline mutex &
|
||||||
Volume::Lock()
|
Volume::Lock()
|
||||||
{
|
{
|
||||||
return fLock;
|
return fLock;
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ bfs_read_fs_stat(fs_volume *_volume, struct fs_info *info)
|
|||||||
FUNCTION();
|
FUNCTION();
|
||||||
|
|
||||||
Volume *volume = (Volume *)_volume->private_volume;
|
Volume *volume = (Volume *)_volume->private_volume;
|
||||||
RecursiveLocker locker(volume->Lock());
|
MutexLocker locker(volume->Lock());
|
||||||
|
|
||||||
// File system flags.
|
// File system flags.
|
||||||
info->flags = B_FS_IS_PERSISTENT | B_FS_HAS_ATTR | B_FS_HAS_MIME
|
info->flags = B_FS_IS_PERSISTENT | B_FS_HAS_ATTR | B_FS_HAS_MIME
|
||||||
@@ -181,7 +181,7 @@ bfs_write_fs_stat(fs_volume *_volume, const struct fs_info *info, uint32 mask)
|
|||||||
if (volume->IsReadOnly())
|
if (volume->IsReadOnly())
|
||||||
return B_READ_ONLY_DEVICE;
|
return B_READ_ONLY_DEVICE;
|
||||||
|
|
||||||
RecursiveLocker locker(volume->Lock());
|
MutexLocker locker(volume->Lock());
|
||||||
|
|
||||||
status_t status = B_BAD_VALUE;
|
status_t status = B_BAD_VALUE;
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#else // !BFS_SHELL
|
#else // !BFS_SHELL
|
||||||
|
|
||||||
|
#include <util/AutoLock.h>
|
||||||
#include <util/DoublyLinkedList.h>
|
#include <util/DoublyLinkedList.h>
|
||||||
#include <util/kernel_cpp.h>
|
#include <util/kernel_cpp.h>
|
||||||
#include <util/Stack.h>
|
#include <util/Stack.h>
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
SubDir HAIKU_TOP src system boot loader file_systems bfs ;
|
SubDir HAIKU_TOP src system boot loader file_systems bfs ;
|
||||||
|
|
||||||
UsePrivateHeaders [ FDirName kernel boot platform $(TARGET_BOOT_PLATFORM) ] ;
|
UsePrivateKernelHeaders ;
|
||||||
UsePrivateHeaders [ FDirName kernel disk_device_manager ] ;
|
UsePrivateHeaders shared storage ;
|
||||||
UsePrivateHeaders kernel shared storage ;
|
|
||||||
|
|
||||||
SubDirHdrs $(HAIKU_TOP) src add-ons kernel file_systems bfs ;
|
SubDirHdrs $(HAIKU_TOP) src add-ons kernel file_systems bfs ;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user