diff --git a/src/add-ons/kernel/file_systems/bfs/Journal.cpp b/src/add-ons/kernel/file_systems/bfs/Journal.cpp index 5585af54fd..2590ff7faa 100644 --- a/src/add-ons/kernel/file_systems/bfs/Journal.cpp +++ b/src/add-ons/kernel/file_systems/bfs/Journal.cpp @@ -14,6 +14,14 @@ #include +struct log_entry : public DoublyLinkedListLinkImpl { + uint16 start; + uint16 length; + uint32 cached_blocks; + Journal *journal; +}; + + Journal::Journal(Volume *volume) : fVolume(volume), @@ -189,19 +197,20 @@ Journal::blockNotify(int32 transactionID, void *arg) // Set log_start pointer if possible... - if (logEntry == journal->fEntries.head) { - if (logEntry->Next() != NULL) { - int32 length = logEntry->next->start - logEntry->start; + if (logEntry == journal->fEntries.First()) { + log_entry *next = journal->fEntries.GetNext(logEntry); + if (next != NULL) { + int32 length = next->start - logEntry->start; superBlock.log_start = (superBlock.log_start + length) % journal->fLogSize; } else superBlock.log_start = journal->fVolume->LogEnd(); update = true; } - journal->fUsed -= logEntry->length; journal->fEntriesLock.Lock(); - logEntry->Remove(); + journal->fUsed -= logEntry->length; + journal->fEntries.Remove(logEntry); journal->fEntriesLock.Unlock(); free(logEntry); @@ -214,7 +223,11 @@ Journal::blockNotify(int32 transactionID, void *arg) if (superBlock.log_start == superBlock.log_end) superBlock.flags = SUPER_BLOCK_DISK_CLEAN; - journal->fVolume->WriteSuperBlock(); + status_t status = journal->fVolume->WriteSuperBlock(); + if (status != B_OK) { + FATAL(("blockNotify: could not write back super block: %s\n", + strerror(status))); + } } } @@ -290,21 +303,40 @@ Journal::WriteLogEntry() logPosition = (logPosition + 1) % fLogSize; } + // create and add log entry + log_entry *logEntry = (log_entry *)malloc(sizeof(log_entry)); - if (logEntry != NULL) { - logEntry->start = logStart; - logEntry->length = TransactionSize(); - logEntry->journal = this; - - fEntriesLock.Lock(); - fEntries.Add(logEntry); - fEntriesLock.Unlock(); - - fCurrent = logEntry; - fUsed += logEntry->length; + if (logEntry == NULL) { + DIE(("Could not create next log entry (out of memory)\n")); + return B_NO_MEMORY; } - cache_end_transaction(fVolume->BlockCache(), fTransactionID, blockNotify, fCurrent); + logEntry->start = logStart; + logEntry->length = TransactionSize(); + logEntry->journal = this; + + fEntriesLock.Lock(); + fEntries.Add(logEntry); + fUsed += logEntry->length; + fEntriesLock.Unlock(); + + // Update the log end pointer in the super block + + fVolume->SuperBlock().flags = SUPER_BLOCK_DISK_DIRTY; + fVolume->SuperBlock().log_end = logPosition; + fVolume->LogEnd() = logPosition; + + status_t status = fVolume->WriteSuperBlock(); + + // We need to flush the drives own cache here to ensure + // disk consistency. + // If that call fails, we can't do anything about it anyway + ioctl(fVolume->Device(), B_FLUSH_DRIVE_CACHE); + + // at this point, we can finally end the transaction - we're in + // a guaranteed valid state + cache_end_transaction(fVolume->BlockCache(), fTransactionID, blockNotify, logEntry); + fArray.MakeEmpty(); // If the log goes to the next round (the log is written as a // circular buffer), all blocks will be flushed out which is @@ -313,19 +345,7 @@ Journal::WriteLogEntry() if (logPosition < logStart) fVolume->FlushDevice(); - // We need to flush the drives own cache here to ensure - // disk consistency. - // If that call fails, we can't do anything about it anyway - ioctl(fVolume->Device(), B_FLUSH_DRIVE_CACHE); - - fArray.MakeEmpty(); - - // Update the log end pointer in the super block - fVolume->SuperBlock().flags = SUPER_BLOCK_DISK_DIRTY; - fVolume->SuperBlock().log_end = logPosition; - fVolume->LogEnd() = logPosition; - - return fVolume->WriteSuperBlock(); + return status; } diff --git a/src/add-ons/kernel/file_systems/bfs/Journal.h b/src/add-ons/kernel/file_systems/bfs/Journal.h index 022fd7cf12..c8544e77fc 100644 --- a/src/add-ons/kernel/file_systems/bfs/Journal.h +++ b/src/add-ons/kernel/file_systems/bfs/Journal.h @@ -8,6 +8,7 @@ #include +#include #ifdef USER # include "myfs.h" @@ -23,12 +24,8 @@ #include "Utility.h" -struct log_entry : node { - uint16 start; - uint16 length; - uint32 cached_blocks; - Journal *journal; -}; +struct log_entry; +typedef DoublyLinkedList LogEntryList; // Locking policy in BFS: if you need both, the volume lock and the @@ -71,18 +68,17 @@ class Journal { static void blockNotify(int32 transactionID, void *arg); status_t TransactionDone(bool success); - Volume *fVolume; + Volume *fVolume; RecursiveLock fLock; - Transaction *fOwner; - BlockArray fArray; - uint32 fLogSize, fMaxTransactionSize, fUsed; - int32 fTransactionsInEntry; - SimpleLock fEntriesLock; - list fEntries; - log_entry *fCurrent; - bool fHasChangedBlocks; - bigtime_t fTimestamp; - int32 fTransactionID; + Transaction *fOwner; + BlockArray fArray; + uint32 fLogSize, fMaxTransactionSize, fUsed; + int32 fTransactionsInEntry; + SimpleLock fEntriesLock; + LogEntryList fEntries; + bool fHasChangedBlocks; + bigtime_t fTimestamp; + int32 fTransactionID; }; diff --git a/src/add-ons/kernel/file_systems/bfs/Utility.h b/src/add-ons/kernel/file_systems/bfs/Utility.h index edf0c25f37..896b9e807d 100644 --- a/src/add-ons/kernel/file_systems/bfs/Utility.h +++ b/src/add-ons/kernel/file_systems/bfs/Utility.h @@ -1,6 +1,6 @@ /* Utility - some helper classes * - * Copyright 2001-2004, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2001-2005, Axel Dörfler, axeld@pinc-software.de. * This file may be used under the terms of the MIT License. */ #ifndef UTILITY_H @@ -63,47 +63,4 @@ class BlockArray { int32 fMaxBlocks; }; - -// Doubly linked list - -template struct node { - Node *next, *prev; - - void - Remove() - { - prev->next = next; - next->prev = prev; - } - - Node * - Next() - { - if (next && next->next != NULL) - return next; - - return NULL; - } -}; - -template struct list { - Node *head, *tail, *last; - - list() - { - head = (Node *)&tail; - tail = NULL; - last = (Node *)&head; - } - - void - Add(Node *entry) - { - entry->next = (Node *)&tail; - entry->prev = last; - last->next = entry; - last = entry; - } -}; - #endif /* UTILITY_H */