* The check mechanism in the block allocator now locks the journal as well to
fix a potential deadlock. * Journal::Lock() now accepts another parameter that specified whether child transactions should be split - this is nothing you would want in normal operation unless the parent transaction is only there to prevent others from writing (such as with the block allocator check stuff). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@28438 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
d9810e04cf
commit
6c3348f1cd
@ -1116,14 +1116,20 @@ BlockAllocator::StartChecking(check_control* control)
|
||||
if (!_IsValidCheckControl(control))
|
||||
return B_BAD_VALUE;
|
||||
|
||||
fVolume->GetJournal(0)->Lock(NULL, true);
|
||||
// Lock the volume's journal
|
||||
|
||||
status_t status = mutex_lock(&fLock);
|
||||
if (status < B_OK)
|
||||
if (status < B_OK) {
|
||||
fVolume->GetJournal(0)->Unlock(NULL, true);
|
||||
return status;
|
||||
}
|
||||
|
||||
size_t size = BitmapSize();
|
||||
fCheckBitmap = (uint32*)malloc(size);
|
||||
if (fCheckBitmap == NULL) {
|
||||
mutex_unlock(&fLock);
|
||||
fVolume->GetJournal(0)->Unlock(NULL, true);
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
@ -1132,6 +1138,7 @@ BlockAllocator::StartChecking(check_control* control)
|
||||
free(fCheckBitmap);
|
||||
fCheckBitmap = NULL;
|
||||
mutex_unlock(&fLock);
|
||||
fVolume->GetJournal(0)->Unlock(NULL, true);
|
||||
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
@ -1209,7 +1216,7 @@ BlockAllocator::StopChecking(check_control* control)
|
||||
= HOST_ENDIAN_TO_BFS_INT64(usedBlocks);
|
||||
|
||||
int32 blocksInBitmap = fNumGroups * fBlocksPerGroup;
|
||||
int32 blockSize = fVolume->BlockSize();
|
||||
size_t blockSize = fVolume->BlockSize();
|
||||
|
||||
for (int32 i = 0; i < blocksInBitmap; i += 512) {
|
||||
Transaction transaction(fVolume, 1 + i);
|
||||
@ -1235,6 +1242,7 @@ BlockAllocator::StopChecking(check_control* control)
|
||||
fCheckCookie = NULL;
|
||||
delete cookie;
|
||||
mutex_unlock(&fLock);
|
||||
fVolume->GetJournal(0)->Unlock(NULL, true);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
@ -403,7 +403,8 @@ Journal::Journal(Volume* volume)
|
||||
fMaxTransactionSize(fLogSize / 2 - 5),
|
||||
fUsed(0),
|
||||
fUnwrittenTransactions(0),
|
||||
fHasSubtransaction(false)
|
||||
fHasSubtransaction(false),
|
||||
fSeparateSubTransactions(false)
|
||||
{
|
||||
recursive_lock_init(&fLock, "bfs journal");
|
||||
mutex_init(&fEntriesLock, "bfs journal entries");
|
||||
@ -909,17 +910,20 @@ Journal::FlushLogAndBlocks()
|
||||
|
||||
|
||||
status_t
|
||||
Journal::Lock(Transaction* owner)
|
||||
Journal::Lock(Transaction* owner, bool separateSubTransactions)
|
||||
{
|
||||
status_t status = recursive_lock_lock(&fLock);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
if (recursive_lock_get_recursion(&fLock) > 1) {
|
||||
if (!fSeparateSubTransactions && recursive_lock_get_recursion(&fLock) > 1) {
|
||||
// we'll just use the current transaction again
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
if (separateSubTransactions)
|
||||
fSeparateSubTransactions = true;
|
||||
|
||||
fOwner = owner;
|
||||
|
||||
// TODO: we need a way to find out how big the current transaction is;
|
||||
@ -951,13 +955,18 @@ Journal::Lock(Transaction* owner)
|
||||
void
|
||||
Journal::Unlock(Transaction* owner, bool success)
|
||||
{
|
||||
if (recursive_lock_get_recursion(&fLock) == 1) {
|
||||
if (fSeparateSubTransactions || recursive_lock_get_recursion(&fLock) == 1) {
|
||||
// we only end the transaction if we would really unlock it
|
||||
// TODO: what about failing transactions that do not unlock?
|
||||
// (they must make the parent fail, too)
|
||||
_TransactionDone(success);
|
||||
|
||||
fTimestamp = system_time();
|
||||
fOwner = NULL;
|
||||
|
||||
if (fSeparateSubTransactions
|
||||
&& recursive_lock_get_recursion(&fLock) == 1)
|
||||
fSeparateSubTransactions = false;
|
||||
}
|
||||
|
||||
recursive_lock_unlock(&fLock);
|
||||
@ -1061,7 +1070,7 @@ Transaction::Start(Volume* volume, off_t refBlock)
|
||||
return B_OK;
|
||||
|
||||
fJournal = volume->GetJournal(refBlock);
|
||||
if (fJournal != NULL && fJournal->Lock(this) == B_OK)
|
||||
if (fJournal != NULL && fJournal->Lock(this, false) == B_OK)
|
||||
return B_OK;
|
||||
|
||||
fJournal = NULL;
|
||||
|
@ -26,7 +26,8 @@ public:
|
||||
|
||||
status_t InitCheck();
|
||||
|
||||
status_t Lock(Transaction* owner);
|
||||
status_t Lock(Transaction* owner,
|
||||
bool separateSubTransactions);
|
||||
void Unlock(Transaction* owner, bool success);
|
||||
|
||||
status_t ReplayLog();
|
||||
@ -69,6 +70,7 @@ private:
|
||||
bigtime_t fTimestamp;
|
||||
int32 fTransactionID;
|
||||
bool fHasSubtransaction;
|
||||
bool fSeparateSubTransactions;
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user