* 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:
@@ -1116,14 +1116,20 @@ BlockAllocator::StartChecking(check_control* control)
|
|||||||
if (!_IsValidCheckControl(control))
|
if (!_IsValidCheckControl(control))
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
fVolume->GetJournal(0)->Lock(NULL, true);
|
||||||
|
// Lock the volume's journal
|
||||||
|
|
||||||
status_t status = mutex_lock(&fLock);
|
status_t status = mutex_lock(&fLock);
|
||||||
if (status < B_OK)
|
if (status < B_OK) {
|
||||||
|
fVolume->GetJournal(0)->Unlock(NULL, true);
|
||||||
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) {
|
||||||
mutex_unlock(&fLock);
|
mutex_unlock(&fLock);
|
||||||
|
fVolume->GetJournal(0)->Unlock(NULL, true);
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1132,6 +1138,7 @@ BlockAllocator::StartChecking(check_control* control)
|
|||||||
free(fCheckBitmap);
|
free(fCheckBitmap);
|
||||||
fCheckBitmap = NULL;
|
fCheckBitmap = NULL;
|
||||||
mutex_unlock(&fLock);
|
mutex_unlock(&fLock);
|
||||||
|
fVolume->GetJournal(0)->Unlock(NULL, true);
|
||||||
|
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
}
|
}
|
||||||
@@ -1209,7 +1216,7 @@ BlockAllocator::StopChecking(check_control* control)
|
|||||||
= HOST_ENDIAN_TO_BFS_INT64(usedBlocks);
|
= HOST_ENDIAN_TO_BFS_INT64(usedBlocks);
|
||||||
|
|
||||||
int32 blocksInBitmap = fNumGroups * fBlocksPerGroup;
|
int32 blocksInBitmap = fNumGroups * fBlocksPerGroup;
|
||||||
int32 blockSize = fVolume->BlockSize();
|
size_t blockSize = fVolume->BlockSize();
|
||||||
|
|
||||||
for (int32 i = 0; i < blocksInBitmap; i += 512) {
|
for (int32 i = 0; i < blocksInBitmap; i += 512) {
|
||||||
Transaction transaction(fVolume, 1 + i);
|
Transaction transaction(fVolume, 1 + i);
|
||||||
@@ -1235,6 +1242,7 @@ BlockAllocator::StopChecking(check_control* control)
|
|||||||
fCheckCookie = NULL;
|
fCheckCookie = NULL;
|
||||||
delete cookie;
|
delete cookie;
|
||||||
mutex_unlock(&fLock);
|
mutex_unlock(&fLock);
|
||||||
|
fVolume->GetJournal(0)->Unlock(NULL, true);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -403,7 +403,8 @@ Journal::Journal(Volume* volume)
|
|||||||
fMaxTransactionSize(fLogSize / 2 - 5),
|
fMaxTransactionSize(fLogSize / 2 - 5),
|
||||||
fUsed(0),
|
fUsed(0),
|
||||||
fUnwrittenTransactions(0),
|
fUnwrittenTransactions(0),
|
||||||
fHasSubtransaction(false)
|
fHasSubtransaction(false),
|
||||||
|
fSeparateSubTransactions(false)
|
||||||
{
|
{
|
||||||
recursive_lock_init(&fLock, "bfs journal");
|
recursive_lock_init(&fLock, "bfs journal");
|
||||||
mutex_init(&fEntriesLock, "bfs journal entries");
|
mutex_init(&fEntriesLock, "bfs journal entries");
|
||||||
@@ -909,17 +910,20 @@ Journal::FlushLogAndBlocks()
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Journal::Lock(Transaction* owner)
|
Journal::Lock(Transaction* owner, bool separateSubTransactions)
|
||||||
{
|
{
|
||||||
status_t status = recursive_lock_lock(&fLock);
|
status_t status = recursive_lock_lock(&fLock);
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
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
|
// we'll just use the current transaction again
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (separateSubTransactions)
|
||||||
|
fSeparateSubTransactions = true;
|
||||||
|
|
||||||
fOwner = owner;
|
fOwner = owner;
|
||||||
|
|
||||||
// TODO: we need a way to find out how big the current transaction is;
|
// TODO: we need a way to find out how big the current transaction is;
|
||||||
@@ -951,13 +955,18 @@ Journal::Lock(Transaction* owner)
|
|||||||
void
|
void
|
||||||
Journal::Unlock(Transaction* owner, bool success)
|
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
|
// 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?
|
||||||
|
// (they must make the parent fail, too)
|
||||||
_TransactionDone(success);
|
_TransactionDone(success);
|
||||||
|
|
||||||
fTimestamp = system_time();
|
fTimestamp = system_time();
|
||||||
fOwner = NULL;
|
fOwner = NULL;
|
||||||
|
|
||||||
|
if (fSeparateSubTransactions
|
||||||
|
&& recursive_lock_get_recursion(&fLock) == 1)
|
||||||
|
fSeparateSubTransactions = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
recursive_lock_unlock(&fLock);
|
recursive_lock_unlock(&fLock);
|
||||||
@@ -1061,7 +1070,7 @@ Transaction::Start(Volume* volume, off_t refBlock)
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
fJournal = volume->GetJournal(refBlock);
|
fJournal = volume->GetJournal(refBlock);
|
||||||
if (fJournal != NULL && fJournal->Lock(this) == B_OK)
|
if (fJournal != NULL && fJournal->Lock(this, false) == B_OK)
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
fJournal = NULL;
|
fJournal = NULL;
|
||||||
|
|||||||
@@ -26,7 +26,8 @@ public:
|
|||||||
|
|
||||||
status_t InitCheck();
|
status_t InitCheck();
|
||||||
|
|
||||||
status_t Lock(Transaction* owner);
|
status_t Lock(Transaction* owner,
|
||||||
|
bool separateSubTransactions);
|
||||||
void Unlock(Transaction* owner, bool success);
|
void Unlock(Transaction* owner, bool success);
|
||||||
|
|
||||||
status_t ReplayLog();
|
status_t ReplayLog();
|
||||||
@@ -69,6 +70,7 @@ private:
|
|||||||
bigtime_t fTimestamp;
|
bigtime_t fTimestamp;
|
||||||
int32 fTransactionID;
|
int32 fTransactionID;
|
||||||
bool fHasSubtransaction;
|
bool fHasSubtransaction;
|
||||||
|
bool fSeparateSubTransactions;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user