diff --git a/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp b/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp index 10149149e7..78758c5edd 100644 --- a/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp +++ b/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp @@ -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; } diff --git a/src/add-ons/kernel/file_systems/bfs/Journal.cpp b/src/add-ons/kernel/file_systems/bfs/Journal.cpp index 9b6f9c5a50..157b30fab1 100644 --- a/src/add-ons/kernel/file_systems/bfs/Journal.cpp +++ b/src/add-ons/kernel/file_systems/bfs/Journal.cpp @@ -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; diff --git a/src/add-ons/kernel/file_systems/bfs/Journal.h b/src/add-ons/kernel/file_systems/bfs/Journal.h index 5ebf1ccb2a..d6bc01cede 100644 --- a/src/add-ons/kernel/file_systems/bfs/Journal.h +++ b/src/add-ons/kernel/file_systems/bfs/Journal.h @@ -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; };