1 /* Journal - transaction and logging 2 * 3 * Copyright 2001-2005, Axel Dörfler, axeld@pinc-software.de. 4 * This file may be used under the terms of the MIT License. 5 */ 6 #ifndef JOURNAL_H 7 #define JOURNAL_H 8 9 10 #include <KernelExport.h> 11 #include <util/DoublyLinkedList.h> 12 13 #ifdef USER 14 # include "myfs.h" 15 # include <stdio.h> 16 #endif 17 18 #ifndef _IMPEXP_KERNEL 19 # define _IMPEXP_KERNEL 20 #endif 21 22 #include "Volume.h" 23 #include "Chain.h" 24 #include "Utility.h" 25 26 27 struct run_array; 28 class LogEntry; 29 typedef DoublyLinkedList<LogEntry> LogEntryList; 30 31 32 // Locking policy in BFS: if you need both, the volume lock and the 33 // journal lock, you must lock the volume first - or else you will 34 // end up in a deadlock. 35 // That is, if you start a transaction, and will need to lock the 36 // volume while the transaction is in progress (for the unsafe 37 // get_vnode() call, for example), you must lock the volume before 38 // starting the transaction. 39 40 class Journal { 41 public: 42 Journal(Volume *); 43 ~Journal(); 44 45 status_t InitCheck(); 46 47 status_t Lock(Transaction *owner); 48 void Unlock(Transaction *owner, bool success); 49 50 status_t ReplayLog(); 51 52 status_t LogBlocks(off_t blockNumber, const uint8 *buffer, size_t numBlocks); 53 54 Transaction *CurrentTransaction() const { return fOwner; } 55 56 status_t FlushLogAndBlocks(); 57 Volume *GetVolume() const { return fVolume; } 58 int32 TransactionID() const { return fTransactionID; } 59 60 inline uint32 FreeLogBlocks() const; 61 62 private: 63 bool _HasSubTransaction() { return fHasSubtransaction; } 64 uint32 _TransactionSize() const; 65 status_t _WriteTransactionToLog(); 66 status_t _CheckRunArray(const run_array *array); 67 status_t _ReplayRunArray(int32 *start); 68 status_t _TransactionDone(bool success); 69 static void _blockNotify(int32 transactionID, void *arg); 70 71 Volume *fVolume; 72 RecursiveLock fLock; 73 Transaction *fOwner; 74 uint32 fLogSize, fMaxTransactionSize, fUsed; 75 int32 fUnwrittenTransactions; 76 SimpleLock fEntriesLock; 77 LogEntryList fEntries; 78 bigtime_t fTimestamp; 79 int32 fTransactionID; 80 bool fHasSubtransaction; 81 }; 82 83 84 inline uint32 85 Journal::FreeLogBlocks() const 86 { 87 return fVolume->LogStart() <= fVolume->LogEnd() ? 88 fLogSize - fVolume->LogEnd() + fVolume->LogStart() 89 : fVolume->LogStart() - fVolume->LogEnd(); 90 } 91 92 93 // For now, that's only a dumb class that does more or less nothing 94 // else than writing the blocks directly to the real location. 95 // It doesn't yet use logging. 96 97 class Transaction { 98 public: 99 Transaction(Volume *volume, off_t refBlock) 100 : 101 fJournal(NULL) 102 { 103 Start(volume, refBlock); 104 } 105 106 Transaction(Volume *volume, block_run refRun) 107 : 108 fJournal(NULL) 109 { 110 Start(volume, volume->ToBlock(refRun)); 111 } 112 113 Transaction() 114 : 115 fJournal(NULL) 116 { 117 } 118 119 ~Transaction() 120 { 121 if (fJournal) 122 fJournal->Unlock(this, false); 123 } 124 125 status_t Start(Volume *volume, off_t refBlock); 126 bool IsStarted() const { return fJournal != NULL; } 127 128 void Done() 129 { 130 if (fJournal != NULL) 131 fJournal->Unlock(this, true); 132 fJournal = NULL; 133 } 134 135 bool HasParent() 136 { 137 if (fJournal != NULL) 138 return fJournal->CurrentTransaction() == this; 139 140 return false; 141 } 142 143 status_t WriteBlocks(off_t blockNumber, const uint8 *buffer, size_t numBlocks = 1) 144 { 145 if (fJournal == NULL) 146 return B_NO_INIT; 147 148 // ToDo: implement this properly! 149 // Currently only used in BlockAllocator::StopChecking(), 150 // so chkbfs won't work correctly 151 #if 0 152 return fJournal->LogBlocks(blockNumber, buffer, numBlocks); 153 #endif 154 return B_ERROR; 155 } 156 157 Volume *GetVolume() { return fJournal != NULL ? fJournal->GetVolume() : NULL; } 158 int32 ID() const { return fJournal->TransactionID(); } 159 160 private: 161 Transaction(const Transaction &); 162 Transaction &operator=(const Transaction &); 163 // no implementation 164 165 Journal *fJournal; 166 }; 167 168 #endif /* JOURNAL_H */ 169