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.
7 * Janito V. Ferreira Filho
13 #define JOURNAL_MAGIC 0xc03b3998U
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
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
26 #define JOURNAL_FEATURE_INCOMPATIBLE_REVOKE 1
28 #define JOURNAL_KNOWN_READ_ONLY_COMPATIBLE_FEATURES 0
29 #define JOURNAL_KNOWN_INCOMPATIBLE_FEATURES \
30 JOURNAL_FEATURE_INCOMPATIBLE_REVOKE
35 #include <AutoDeleter.h>
36 #include <util/DoublyLinkedList.h>
38 #include "Transaction.h"
44 struct JournalHeader
{
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
); }
57 bool CheckMagic() const
58 { return Magic() == JOURNAL_MAGIC
; }
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
);
69 struct JournalBlockTag
{
73 uint32
BlockNumber() const
74 { return B_BENDIAN_TO_HOST_INT32(block_number
); }
76 { return B_BENDIAN_TO_HOST_INT32(flags
); }
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
); }
83 { flags
|= B_HOST_TO_BENDIAN_INT32(JOURNAL_FLAG_LAST_TAG
); }
85 { flags
|= B_HOST_TO_BENDIAN_INT32(JOURNAL_FLAG_ESCAPED
); }
89 struct JournalRevokeHeader
{
93 uint32 revoke_blocks
[0];
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
]); }
102 struct JournalSuperBlock
{
103 JournalHeader header
;
107 uint32 first_log_block
;
109 uint32 first_commit_id
;
114 uint32 compatible_features
;
115 uint32 incompatible_features
;
116 uint32 read_only_compatible_features
;
121 uint32 dynamic_superblock
;
123 uint32 max_transaction_blocks
;
124 uint32 max_transaction_data
;
128 uint8 user_ids
[16*48];
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
); }
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
); }
157 typedef DoublyLinkedList
<LogEntry
> LogEntryList
;
162 Journal(Volume
*fsVolume
, Volume
*jVolume
);
165 virtual status_t
InitCheck();
166 virtual status_t
Uninit();
168 virtual status_t
Recover();
169 virtual status_t
StartLog();
170 status_t
RestartLog();
172 virtual status_t
Lock(Transaction
* owner
,
173 bool separateSubTransactions
);
174 virtual status_t
Unlock(Transaction
* owner
, bool success
);
176 virtual status_t
MapBlock(off_t logical
, fsblock_t
& physical
);
177 inline uint32
FreeLogBlocks() const;
179 status_t
FlushLogAndBlocks();
181 int32
TransactionID() const;
183 Volume
* GetFilesystemVolume()
184 { return fFilesystemVolume
; }
188 status_t
_WritePartialTransactionToLog(
189 JournalHeader
* descriptorBlock
,
190 bool detached
, uint8
** escapedBlock
,
191 uint32
& logBlock
, off_t
& blockNumber
,
193 ArrayDeleter
<uint8
>& escapedDataDeleter
,
194 uint32
& blockCount
, bool& finished
);
195 virtual status_t
_WriteTransactionToLog();
197 status_t
_SaveSuperBlock();
198 status_t
_LoadSuperBlock();
201 Volume
* fJournalVolume
;
202 void* fJournalBlockCache
;
203 Volume
* fFilesystemVolume
;
204 void* fFilesystemBlockCache
;
206 recursive_lock fLock
;
209 RevokeManager
* fRevokeManager
;
211 status_t fInitStatus
;
213 uint32 fFirstCommitID
;
214 uint32 fFirstCacheCommitID
;
215 uint32 fFirstLogBlock
;
223 uint32 fMaxTransactionSize
;
225 uint32 fCurrentCommitID
;
227 LogEntryList fLogEntries
;
228 mutex fLogEntriesLock
;
229 bool fHasSubTransaction
;
230 bool fSeparateSubTransactions
;
231 int32 fUnwrittenTransactions
;
232 int32 fTransactionID
;
235 status_t
_CheckFeatures(JournalSuperBlock
* superblock
);
237 uint32
_CountTags(JournalHeader
*descriptorBlock
);
238 status_t
_RecoverPassScan(uint32
& lastCommitID
);
239 status_t
_RecoverPassRevoke(uint32 lastCommitID
);
240 status_t
_RecoverPassReplay(uint32 lastCommitID
);
242 status_t
_FlushLog(bool canWait
, bool flushBlocks
);
244 inline uint32
_WrapAroundLog(uint32 block
);
246 size_t _CurrentTransactionSize() const;
247 size_t _FullTransactionSize() const;
248 size_t _MainTransactionSize() const;
250 virtual status_t
_TransactionDone(bool success
);
252 static void _TransactionWritten(int32 transactionID
,
253 int32 event
, void* _logEntry
);
254 static void _TransactionIdle(int32 transactionID
,
255 int32 event
, void* _journal
);