1 /* 2 * Copyright 2010, Haiku Inc. All rights reserved. 3 * Copyright 2001-2010, Axel Dörfler, axeld@pinc-software.de. 4 * This file may be used under the terms of the MIT License. 5 * 6 * Authors: 7 * Janito V. Ferreira Filho 8 */ 9 #ifndef JOURNAL_H 10 #define JOURNAL_H 11 12 13 #define JOURNAL_MAGIC 0xc03b3998U 14 15 #define JOURNAL_DESCRIPTOR_BLOCK 1 16 #define JOURNAL_COMMIT_BLOCK 2 17 #define JOURNAL_SUPERBLOCK_V1 3 18 #define JOURNAL_SUPERBLOCK_V2 4 19 #define JOURNAL_REVOKE_BLOCK 5 20 21 #define JOURNAL_FLAG_ESCAPED 1 22 #define JOURNAL_FLAG_SAME_UUID 2 23 #define JOURNAL_FLAG_DELETED 4 24 #define JOURNAL_FLAG_LAST_TAG 8 25 26 #define JOURNAL_FEATURE_INCOMPATIBLE_REVOKE 1 27 28 #define JOURNAL_KNOWN_READ_ONLY_COMPATIBLE_FEATURES 0 29 #define JOURNAL_KNOWN_INCOMPATIBLE_FEATURES \ 30 JOURNAL_FEATURE_INCOMPATIBLE_REVOKE 31 32 33 #include "Volume.h" 34 35 #include <AutoDeleter.h> 36 #include <util/DoublyLinkedList.h> 37 38 #include "Transaction.h" 39 40 41 class RevokeManager; 42 43 44 struct JournalHeader { 45 uint32 magic; 46 uint32 block_type; 47 uint32 sequence; 48 char data[0]; 49 50 uint32 Magic() const 51 { return B_BENDIAN_TO_HOST_INT32(magic); } 52 uint32 BlockType() const 53 { return B_BENDIAN_TO_HOST_INT32(block_type); } 54 uint32 Sequence() const 55 { return B_BENDIAN_TO_HOST_INT32(sequence); } 56 57 bool CheckMagic() const 58 { return Magic() == JOURNAL_MAGIC; } 59 60 void IncrementSequence() 61 { sequence = B_HOST_TO_BENDIAN_INT32(Sequence() + 1); } 62 void DecrementSequence() 63 { sequence = B_HOST_TO_BENDIAN_INT32(Sequence() - 1); } 64 void MakeDescriptor(uint32 sequence); 65 void MakeCommit(uint32 sequence); 66 } _PACKED; 67 68 69 struct JournalBlockTag { 70 uint32 block_number; 71 uint32 flags; 72 73 uint32 BlockNumber() const 74 { return B_BENDIAN_TO_HOST_INT32(block_number); } 75 uint32 Flags() const 76 { return B_BENDIAN_TO_HOST_INT32(flags); } 77 78 void SetBlockNumber(uint32 block) 79 { block_number = B_HOST_TO_BENDIAN_INT32(block); } 80 void SetFlags(uint32 new_flags) 81 { flags = B_HOST_TO_BENDIAN_INT32(new_flags); } 82 void SetLastTagFlag() 83 { flags |= B_HOST_TO_BENDIAN_INT32(JOURNAL_FLAG_LAST_TAG); } 84 void SetEscapedFlag() 85 { flags |= B_HOST_TO_BENDIAN_INT32(JOURNAL_FLAG_ESCAPED); } 86 } _PACKED; 87 88 89 struct JournalRevokeHeader { 90 JournalHeader header; 91 uint32 num_bytes; 92 93 uint32 revoke_blocks[0]; 94 95 uint32 NumBytes() const 96 { return B_BENDIAN_TO_HOST_INT32(num_bytes); } 97 uint32 RevokeBlock(int offset) const 98 { return B_BENDIAN_TO_HOST_INT32(revoke_blocks[offset]); } 99 } _PACKED; 100 101 102 struct JournalSuperBlock { 103 JournalHeader header; 104 105 uint32 block_size; 106 uint32 num_blocks; 107 uint32 first_log_block; 108 109 uint32 first_commit_id; 110 uint32 log_start; 111 112 uint32 error; 113 114 uint32 compatible_features; 115 uint32 incompatible_features; 116 uint32 read_only_compatible_features; 117 118 uint8 uuid[16]; 119 120 uint32 num_users; 121 uint32 dynamic_superblock; 122 123 uint32 max_transaction_blocks; 124 uint32 max_transaction_data; 125 126 uint32 padding[44]; 127 128 uint8 user_ids[16*48]; 129 130 uint32 BlockSize() const 131 { return B_BENDIAN_TO_HOST_INT32(block_size); } 132 uint32 NumBlocks() const 133 { return B_BENDIAN_TO_HOST_INT32(num_blocks); } 134 uint32 FirstLogBlock() const 135 { return B_BENDIAN_TO_HOST_INT32(first_log_block); } 136 uint32 FirstCommitID() const 137 { return B_BENDIAN_TO_HOST_INT32(first_commit_id); } 138 uint32 LogStart() const 139 { return B_BENDIAN_TO_HOST_INT32(log_start); } 140 uint32 IncompatibleFeatures() const 141 { return B_BENDIAN_TO_HOST_INT32(incompatible_features); } 142 uint32 ReadOnlyCompatibleFeatures() const 143 { return B_BENDIAN_TO_HOST_INT32(read_only_compatible_features); } 144 uint32 MaxTransactionBlocks() const 145 { return B_BENDIAN_TO_HOST_INT32(max_transaction_blocks); } 146 uint32 MaxTransactionData() const 147 { return B_BENDIAN_TO_HOST_INT32(max_transaction_data); } 148 149 void SetLogStart(uint32 logStart) 150 { log_start = B_HOST_TO_BENDIAN_INT32(logStart); } 151 void SetFirstCommitID(uint32 firstCommitID) 152 { first_commit_id = B_HOST_TO_BENDIAN_INT32(firstCommitID); } 153 } _PACKED; 154 155 class LogEntry; 156 class Transaction; 157 typedef DoublyLinkedList<LogEntry> LogEntryList; 158 159 160 class Journal { 161 public: 162 Journal(Volume *fsVolume, Volume *jVolume); 163 virtual ~Journal(); 164 165 virtual status_t InitCheck(); 166 virtual status_t Uninit(); 167 168 virtual status_t Recover(); 169 virtual status_t StartLog(); 170 status_t RestartLog(); 171 172 virtual status_t Lock(Transaction* owner, 173 bool separateSubTransactions); 174 virtual status_t Unlock(Transaction* owner, bool success); 175 176 virtual status_t MapBlock(off_t logical, fsblock_t& physical); 177 inline uint32 FreeLogBlocks() const; 178 179 status_t FlushLogAndBlocks(); 180 181 int32 TransactionID() const; 182 183 Volume* GetFilesystemVolume() 184 { return fFilesystemVolume; } 185 protected: 186 Journal(); 187 188 status_t _WritePartialTransactionToLog( 189 JournalHeader* descriptorBlock, 190 bool detached, uint8** escapedBlock, 191 uint32& logBlock, off_t& blockNumber, 192 long& cookie, 193 ArrayDeleter<uint8>& escapedDataDeleter, 194 uint32& blockCount, bool& finished); 195 virtual status_t _WriteTransactionToLog(); 196 197 status_t _SaveSuperBlock(); 198 status_t _LoadSuperBlock(); 199 200 201 Volume* fJournalVolume; 202 void* fJournalBlockCache; 203 Volume* fFilesystemVolume; 204 void* fFilesystemBlockCache; 205 206 recursive_lock fLock; 207 Transaction* fOwner; 208 209 RevokeManager* fRevokeManager; 210 211 status_t fInitStatus; 212 uint32 fBlockSize; 213 uint32 fFirstCommitID; 214 uint32 fFirstCacheCommitID; 215 uint32 fFirstLogBlock; 216 uint32 fLogSize; 217 uint32 fVersion; 218 219 bool fIsStarted; 220 uint32 fLogStart; 221 uint32 fLogEnd; 222 uint32 fFreeBlocks; 223 uint32 fMaxTransactionSize; 224 225 uint32 fCurrentCommitID; 226 227 LogEntryList fLogEntries; 228 mutex fLogEntriesLock; 229 bool fHasSubTransaction; 230 bool fSeparateSubTransactions; 231 int32 fUnwrittenTransactions; 232 int32 fTransactionID; 233 234 private: 235 status_t _CheckFeatures(JournalSuperBlock* superblock); 236 237 uint32 _CountTags(JournalHeader *descriptorBlock); 238 status_t _RecoverPassScan(uint32& lastCommitID); 239 status_t _RecoverPassRevoke(uint32 lastCommitID); 240 status_t _RecoverPassReplay(uint32 lastCommitID); 241 242 status_t _FlushLog(bool canWait, bool flushBlocks); 243 244 inline uint32 _WrapAroundLog(uint32 block); 245 246 size_t _CurrentTransactionSize() const; 247 size_t _FullTransactionSize() const; 248 size_t _MainTransactionSize() const; 249 250 virtual status_t _TransactionDone(bool success); 251 252 static void _TransactionWritten(int32 transactionID, 253 int32 event, void* _logEntry); 254 static void _TransactionIdle(int32 transactionID, 255 int32 event, void* _journal); 256 }; 257 258 #endif // JOURNAL_H 259 260