From 3c78c04589c6c37a6ec71adbf127ad3056b23a44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Wed, 2 Apr 2008 09:46:34 +0000 Subject: [PATCH] Resolved a TODO in Journal::Lock() that Urias reminded me about: * BFS now uses a transaction listener that flushes the current transaction in case it is idle; before, transactions would always be kept open when they weren't large, so that the block writer could not write back the blocks (they were busy from its POV). * This solves the described problem of the screen resolution not being written back even after minutes of inactivity. * Renamed _TransactionNotify() to _TransactionWritten() to differentiate it a bit more from the new _TransactionListener(). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24738 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../kernel/file_systems/bfs/Journal.cpp | 53 ++++++++++++++----- src/add-ons/kernel/file_systems/bfs/Journal.h | 6 ++- 2 files changed, 44 insertions(+), 15 deletions(-) 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;