bfs: Add Journal::FlushLogAndLockJournal

Change-Id: Ic239fd31c99e8c59925ffea2b3b17d9ad5ae802b
Reviewed-on: https://review.haiku-os.org/c/haiku/+/10058
Reviewed-by: Adrien Destugues <[email protected]>
Tested-by: Commit checker robot <[email protected]>
This commit is contained in:
Adrien Destugues
2026-01-22 16:57:47 +00:00
committed by Axel Dörfler
parent 2f76872b8e
commit 2d902e5c6b
2 changed files with 31 additions and 9 deletions
@@ -924,18 +924,18 @@ Journal::_WriteTransactionToLog()
/*! Flushes the current log entry to disk. If \a flushBlocks is \c true it will
also write back all dirty blocks for this volume. If \a movingLog is \c
also write back all dirty blocks for this volume. If \a alreadyLocked is \c
true, we allow the lock to be held when the function is called.
*/
status_t
Journal::_FlushLog(bool canWait, bool flushBlocks, bool movingLog)
Journal::_FlushLog(bool canWait, bool flushBlocks, bool alreadyLocked)
{
status_t status = canWait ? recursive_lock_lock(&fLock)
: recursive_lock_trylock(&fLock);
if (status != B_OK)
return status;
int32 allowedLocks = movingLog ? 2 : 1;
int32 allowedLocks = alreadyLocked ? 2 : 1;
if (recursive_lock_get_recursion(&fLock) > allowedLocks) {
// whoa, FlushLogAndBlocks() was called from inside a transaction
recursive_lock_unlock(&fLock);
@@ -968,6 +968,26 @@ Journal::FlushLogAndBlocks()
}
/*! Locks the journal, in addition to flushing the log and blocks. A return
value of \c B_OK indicates that the operation was successful, and that
the journal is locked.
*/
status_t
Journal::FlushLogAndLockJournal()
{
status_t status = Lock(NULL, true);
if (status != B_OK)
return status;
status = _FlushLog(true, true, true);
if (status != B_OK)
recursive_lock_unlock(&fLock);
return status;
}
status_t
Journal::Lock(Transaction* owner, bool separateSubTransactions)
{
@@ -1147,20 +1167,20 @@ Journal::MoveLog(block_run newLog)
return status;
}
RecursiveLocker locker(fLock);
MutexLocker volumeLock(fVolume->Lock());
status = _FlushLog(true, true, true);
status = FlushLogAndLockJournal();
if (status != B_OK)
return status;
MutexLocker volumeLock(fVolume->Lock());
// update references to the log location and size
fVolume->SuperBlock().log_blocks = newLog;
status = fVolume->WriteSuperBlock();
if (status != B_OK) {
fVolume->SuperBlock().log_blocks = oldLog;
Unlock(NULL, true);
// if we had to allocate some blocks, try to free them
if (!allocatedRun.IsZero()) {
Transaction transaction(fVolume, 0);
@@ -1179,8 +1199,8 @@ Journal::MoveLog(block_run newLog)
fLogSize = newLog.Length();
fMaxTransactionSize = fLogSize / 2 - 5;
Unlock(NULL, true);
volumeLock.Unlock();
locker.Unlock();
// at this point, the log is moved and functional in its new location
@@ -36,6 +36,8 @@ public:
bool CurrentTransactionTooLarge() const;
status_t FlushLogAndBlocks();
status_t FlushLogAndLockJournal();
Volume* GetVolume() const { return fVolume; }
int32 TransactionID() const { return fTransactionID; }
@@ -52,7 +54,7 @@ private:
{ return fHasSubtransaction; }
status_t _FlushLog(bool canWait, bool flushBlocks,
bool movingLog = false);
bool alreadyLocked = false);
uint32 _TransactionSize() const;
status_t _WriteTransactionToLog();
status_t _CheckRunArray(const run_array* array);