diff --git a/src/add-ons/kernel/file_systems/bfs/Journal.cpp b/src/add-ons/kernel/file_systems/bfs/Journal.cpp index 306f6c4e64..5577c77984 100644 --- a/src/add-ons/kernel/file_systems/bfs/Journal.cpp +++ b/src/add-ons/kernel/file_systems/bfs/Journal.cpp @@ -531,8 +531,8 @@ Journal::ReplayLog() the log start pointer as needed. Note, the transactions may not be completed in the order they were written. */ -void -Journal::_TransactionNotify(int32 transactionID, int32 event, void *_logEntry) +/*static*/ void +Journal::_TransactionWritten(int32 transactionID, int32 event, void *_logEntry) { LogEntry *logEntry = (LogEntry *)_logEntry; @@ -577,13 +577,27 @@ Journal::_TransactionNotify(int32 transactionID, int32 event, void *_logEntry) status_t status = journal->fVolume->WriteSuperBlock(); if (status != B_OK) { - FATAL(("_BlockNotify: could not write back super block: %s\n", + FATAL(("_TransactionWritten: could not write back super block: %s\n", strerror(status))); } } } +/*! Listens to TRANSACTION_IDLE events, and flushes the log when that happens */ +/*static*/ void +Journal::_TransactionListener(int32 transactionID, int32 event, void *_journal) +{ + if (event != TRANSACTION_IDLE) + return; + + // The current transaction seems to be idle - flush it + + Journal *journal = (Journal *)_journal; + journal->_FlushLog(); +} + + /*! Writes the blocks that are part of current transaction into the log, and ends the current transaction. If the current transaction is too large to fit into the log, it will @@ -763,11 +777,11 @@ Journal::_WriteTransactionToLog() if (detached) { fTransactionID = cache_detach_sub_transaction(fVolume->BlockCache(), - fTransactionID, _TransactionNotify, logEntry); + fTransactionID, _TransactionWritten, logEntry); fUnwrittenTransactions = 1; } else { cache_end_transaction(fVolume->BlockCache(), fTransactionID, - _TransactionNotify, logEntry); + _TransactionWritten, logEntry); fUnwrittenTransactions = 0; } @@ -775,8 +789,11 @@ 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. +*/ status_t -Journal::FlushLogAndBlocks() +Journal::_FlushLog(bool flushBlocks) { status_t status = fLock.Lock(); if (status != B_OK) @@ -796,13 +813,24 @@ Journal::FlushLogAndBlocks() FATAL(("writing current log entry failed: %s\n", strerror(status))); } - status = fVolume->FlushDevice(); + if (flushBlocks) + status = fVolume->FlushDevice(); fLock.Unlock(); return status; } +/*! Flushes the current log entry to disk, and also writes back all dirty + blocks for this volume (completing all open transactions). +*/ +status_t +Journal::FlushLogAndBlocks() +{ + return _FlushLog(true); +} + + status_t Journal::Lock(Transaction *owner) { @@ -810,12 +838,6 @@ Journal::Lock(Transaction *owner) if (status != B_OK) return status; -/* ToDo: - // if the last transaction is older than 2 secs, start a new one - if (fTransactionsInEntry != 0 && system_time() - fTimestamp > 2000000L) - WriteLogEntry(); -*/ - if (fLock.OwnerCount() > 1) { // we'll just use the current transaction again return B_OK; @@ -842,6 +864,9 @@ Journal::Lock(Transaction *owner) return fTransactionID; } + cache_add_transaction_listener(fVolume->BlockCache(), fTransactionID, + _TransactionListener, this); + return B_OK; } @@ -867,7 +892,7 @@ Journal::_TransactionSize() const { int32 count = cache_blocks_in_transaction(fVolume->BlockCache(), fTransactionID); - if (count < 0) + if (count <= 0) return 0; // take the number of array blocks in this transaction into account diff --git a/src/add-ons/kernel/file_systems/bfs/Journal.h b/src/add-ons/kernel/file_systems/bfs/Journal.h index 827acd2b6e..4cb91db07b 100644 --- a/src/add-ons/kernel/file_systems/bfs/Journal.h +++ b/src/add-ons/kernel/file_systems/bfs/Journal.h @@ -52,13 +52,17 @@ class Journal { private: bool _HasSubTransaction() { return fHasSubtransaction; } + status_t _FlushLog(bool flushBlocks = false); uint32 _TransactionSize() const; status_t _WriteTransactionToLog(); status_t _CheckRunArray(const run_array *array); status_t _ReplayRunArray(int32 *start); status_t _TransactionDone(bool success); - static void _TransactionNotify(int32 transactionID, int32 event, + + static void _TransactionWritten(int32 transactionID, int32 event, void *_logEntry); + static void _TransactionListener(int32 transactionID, int32 event, + void *_journal); Volume *fVolume; RecursiveLock fLock;