Made fLock a recursive lock instead of a mutex.
* This should fix bug #8069.
This commit is contained in:
@@ -520,13 +520,13 @@ BlockAllocator::BlockAllocator(Volume* volume)
|
|||||||
fCheckBitmap(NULL),
|
fCheckBitmap(NULL),
|
||||||
fCheckCookie(NULL)
|
fCheckCookie(NULL)
|
||||||
{
|
{
|
||||||
mutex_init(&fLock, "bfs allocator");
|
recursive_lock_init(&fLock, "bfs allocator");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BlockAllocator::~BlockAllocator()
|
BlockAllocator::~BlockAllocator()
|
||||||
{
|
{
|
||||||
mutex_destroy(&fLock);
|
recursive_lock_destroy(&fLock);
|
||||||
delete[] fGroups;
|
delete[] fGroups;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -546,7 +546,7 @@ BlockAllocator::Initialize(bool full)
|
|||||||
if (!full)
|
if (!full)
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
mutex_lock(&fLock);
|
recursive_lock_lock(&fLock);
|
||||||
// the lock will be released by the _Initialize() method
|
// 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,
|
||||||
@@ -554,7 +554,7 @@ BlockAllocator::Initialize(bool full)
|
|||||||
if (id < B_OK)
|
if (id < B_OK)
|
||||||
return _Initialize(this);
|
return _Initialize(this);
|
||||||
|
|
||||||
mutex_transfer_lock(&fLock, id);
|
recursive_lock_transfer_lock(&fLock, id);
|
||||||
|
|
||||||
return resume_thread(id);
|
return resume_thread(id);
|
||||||
}
|
}
|
||||||
@@ -624,6 +624,7 @@ status_t
|
|||||||
BlockAllocator::_Initialize(BlockAllocator* allocator)
|
BlockAllocator::_Initialize(BlockAllocator* allocator)
|
||||||
{
|
{
|
||||||
// The lock must already be held at this point
|
// The lock must already be held at this point
|
||||||
|
RecursiveLocker locker(allocator->fLock, true);
|
||||||
|
|
||||||
Volume* volume = allocator->fVolume;
|
Volume* volume = allocator->fVolume;
|
||||||
uint32 blocks = allocator->fBlocksPerGroup;
|
uint32 blocks = allocator->fBlocksPerGroup;
|
||||||
@@ -631,10 +632,8 @@ BlockAllocator::_Initialize(BlockAllocator* allocator)
|
|||||||
off_t freeBlocks = 0;
|
off_t freeBlocks = 0;
|
||||||
|
|
||||||
uint32* buffer = (uint32*)malloc(blocks << blockShift);
|
uint32* buffer = (uint32*)malloc(blocks << blockShift);
|
||||||
if (buffer == NULL) {
|
if (buffer == NULL)
|
||||||
mutex_unlock(&allocator->fLock);
|
|
||||||
RETURN_ERROR(B_NO_MEMORY);
|
RETURN_ERROR(B_NO_MEMORY);
|
||||||
}
|
|
||||||
|
|
||||||
AllocationGroup* groups = allocator->fGroups;
|
AllocationGroup* groups = allocator->fGroups;
|
||||||
off_t offset = 1;
|
off_t offset = 1;
|
||||||
@@ -715,7 +714,6 @@ BlockAllocator::_Initialize(BlockAllocator* allocator)
|
|||||||
volume->SuperBlock().used_blocks = HOST_ENDIAN_TO_BFS_INT64(usedBlocks);
|
volume->SuperBlock().used_blocks = HOST_ENDIAN_TO_BFS_INT64(usedBlocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&allocator->fLock);
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -725,7 +723,7 @@ BlockAllocator::Uninitialize()
|
|||||||
{
|
{
|
||||||
// We only have to make sure that the initializer thread isn't running
|
// We only have to make sure that the initializer thread isn't running
|
||||||
// anymore.
|
// anymore.
|
||||||
mutex_lock(&fLock);
|
recursive_lock_lock(&fLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -747,7 +745,7 @@ BlockAllocator::AllocateBlocks(Transaction& transaction, int32 groupIndex,
|
|||||||
groupIndex, start, maximum, minimum));
|
groupIndex, start, maximum, minimum));
|
||||||
|
|
||||||
AllocationBlock cached(fVolume);
|
AllocationBlock cached(fVolume);
|
||||||
MutexLocker lock(fLock);
|
RecursiveLocker lock(fLock);
|
||||||
|
|
||||||
uint32 bitsPerFullBlock = fVolume->BlockSize() << 3;
|
uint32 bitsPerFullBlock = fVolume->BlockSize() << 3;
|
||||||
|
|
||||||
@@ -1005,7 +1003,7 @@ BlockAllocator::Allocate(Transaction& transaction, Inode* inode,
|
|||||||
status_t
|
status_t
|
||||||
BlockAllocator::Free(Transaction& transaction, block_run run)
|
BlockAllocator::Free(Transaction& transaction, block_run run)
|
||||||
{
|
{
|
||||||
MutexLocker lock(fLock);
|
RecursiveLocker lock(fLock);
|
||||||
|
|
||||||
int32 group = run.AllocationGroup();
|
int32 group = run.AllocationGroup();
|
||||||
uint16 start = run.Start();
|
uint16 start = run.Start();
|
||||||
@@ -1072,7 +1070,7 @@ void
|
|||||||
BlockAllocator::Fragment()
|
BlockAllocator::Fragment()
|
||||||
{
|
{
|
||||||
AllocationBlock cached(fVolume);
|
AllocationBlock cached(fVolume);
|
||||||
MutexLocker lock(fLock);
|
RecursiveLocker lock(fLock);
|
||||||
|
|
||||||
// only leave 4 block holes
|
// only leave 4 block holes
|
||||||
static const uint32 kMask = 0x0f0f0f0f;
|
static const uint32 kMask = 0x0f0f0f0f;
|
||||||
@@ -1103,7 +1101,7 @@ void
|
|||||||
BlockAllocator::_CheckGroup(int32 groupIndex) const
|
BlockAllocator::_CheckGroup(int32 groupIndex) const
|
||||||
{
|
{
|
||||||
AllocationBlock cached(fVolume);
|
AllocationBlock cached(fVolume);
|
||||||
ASSERT_LOCKED_MUTEX(&fLock);
|
ASSERT_LOCKED_RECURSIVE(&fLock);
|
||||||
|
|
||||||
AllocationGroup& group = fGroups[groupIndex];
|
AllocationGroup& group = fGroups[groupIndex];
|
||||||
|
|
||||||
@@ -1202,16 +1200,12 @@ BlockAllocator::StartChecking(const check_control* control)
|
|||||||
fVolume->GetJournal(0)->Lock(NULL, true);
|
fVolume->GetJournal(0)->Lock(NULL, true);
|
||||||
// Lock the volume's journal
|
// Lock the volume's journal
|
||||||
|
|
||||||
status_t status = mutex_lock(&fLock);
|
recursive_lock_lock(&fLock);
|
||||||
if (status != B_OK) {
|
|
||||||
fVolume->GetJournal(0)->Unlock(NULL, true);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t size = BitmapSize();
|
size_t size = BitmapSize();
|
||||||
fCheckBitmap = (uint32*)malloc(size);
|
fCheckBitmap = (uint32*)malloc(size);
|
||||||
if (fCheckBitmap == NULL) {
|
if (fCheckBitmap == NULL) {
|
||||||
mutex_unlock(&fLock);
|
recursive_lock_unlock(&fLock);
|
||||||
fVolume->GetJournal(0)->Unlock(NULL, true);
|
fVolume->GetJournal(0)->Unlock(NULL, true);
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
}
|
}
|
||||||
@@ -1220,7 +1214,7 @@ BlockAllocator::StartChecking(const check_control* control)
|
|||||||
if (fCheckCookie == NULL) {
|
if (fCheckCookie == NULL) {
|
||||||
free(fCheckBitmap);
|
free(fCheckBitmap);
|
||||||
fCheckBitmap = NULL;
|
fCheckBitmap = NULL;
|
||||||
mutex_unlock(&fLock);
|
recursive_lock_unlock(&fLock);
|
||||||
fVolume->GetJournal(0)->Unlock(NULL, true);
|
fVolume->GetJournal(0)->Unlock(NULL, true);
|
||||||
|
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
@@ -1354,7 +1348,7 @@ BlockAllocator::StopChecking(check_control* control)
|
|||||||
fCheckBitmap = NULL;
|
fCheckBitmap = NULL;
|
||||||
delete fCheckCookie;
|
delete fCheckCookie;
|
||||||
fCheckCookie = NULL;
|
fCheckCookie = NULL;
|
||||||
mutex_unlock(&fLock);
|
recursive_lock_unlock(&fLock);
|
||||||
fVolume->GetJournal(0)->Unlock(NULL, true);
|
fVolume->GetJournal(0)->Unlock(NULL, true);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -1518,7 +1512,8 @@ BlockAllocator::CheckNextNode(check_control* control)
|
|||||||
// Rename the inode
|
// Rename the inode
|
||||||
Transaction transaction(fVolume, inode->BlockNumber());
|
Transaction transaction(fVolume, inode->BlockNumber());
|
||||||
|
|
||||||
// TODO: this may potentially need new blocks!
|
// Note, this may need extra blocks, but the inode will
|
||||||
|
// only be checked afterwards, so that it won't be lost
|
||||||
status = inode->SetName(transaction, name);
|
status = inode->SetName(transaction, name);
|
||||||
if (status == B_OK)
|
if (status == B_OK)
|
||||||
status = inode->WriteBack(transaction);
|
status = inode->WriteBack(transaction);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2001-2010, Axel Dörfler, axeld@pinc-software.de.
|
* Copyright 2001-2012, 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 BLOCK_ALLOCATOR_H
|
#ifndef BLOCK_ALLOCATOR_H
|
||||||
@@ -78,8 +78,9 @@ private:
|
|||||||
|
|
||||||
static status_t _Initialize(BlockAllocator* self);
|
static status_t _Initialize(BlockAllocator* self);
|
||||||
|
|
||||||
|
private:
|
||||||
Volume* fVolume;
|
Volume* fVolume;
|
||||||
mutex fLock;
|
recursive_lock fLock;
|
||||||
AllocationGroup* fGroups;
|
AllocationGroup* fGroups;
|
||||||
int32 fNumGroups;
|
int32 fNumGroups;
|
||||||
uint32 fBlocksPerGroup;
|
uint32 fBlocksPerGroup;
|
||||||
|
|||||||
Reference in New Issue
Block a user