xref: /haiku/src/add-ons/kernel/file_systems/ext2/Journal.h (revision 2b76973fa2401f7a5edf68e6470f3d3210cbcff3)
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