xref: /haiku/src/add-ons/kernel/file_systems/bfs/bfs.h (revision 7120e97489acbf17d86d3f33e3b2e68974fd4b23)
1 #ifndef BFS_H
2 #define BFS_H
3 /* bfs - BFS definitions and helper functions
4 **
5 ** Initial version by Axel Dörfler, axeld@pinc-software.de
6 ** Parts of this code is based on work previously done by Marcus Overhagen
7 **
8 ** Copyright 2001 pinc Software. All Rights Reserved.
9 ** This file may be used under the terms of the OpenBeOS License.
10 */
11 
12 
13 #include <SupportDefs.h>
14 
15 #ifndef B_BEOS_VERSION_DANO
16 #	define B_BAD_DATA B_ERROR
17 #endif
18 
19 
20 struct block_run
21 {
22 	int32		allocation_group;
23 	uint16		start;
24 	uint16		length;
25 
26 	inline bool operator==(const block_run &run) const;
27 	inline bool operator!=(const block_run &run) const;
28 	inline bool IsZero();
29 	inline bool MergeableWith(block_run run) const;
30 	inline void SetTo(int32 group, uint16 start, uint16 length = 1);
31 
32 	inline static block_run Run(int32 group, uint16 start, uint16 length = 1);
33 		// can't have a constructor because it's used in a union
34 };
35 
36 typedef block_run inode_addr;
37 
38 // Since the block_run::length field spans 16 bits, the largest number of
39 // blocks covered by a block_run is 65535 (as long as we don't want to
40 // break compatibility and take a zero length for 65536).
41 #define MAX_BLOCK_RUN_LENGTH	65535
42 
43 //**************************************
44 
45 
46 #define BFS_DISK_NAME_LENGTH	32
47 
48 struct disk_super_block
49 {
50 	char		name[BFS_DISK_NAME_LENGTH];
51 	int32		magic1;
52 	int32		fs_byte_order;
53 	uint32		block_size;
54 	uint32		block_shift;
55 	off_t		num_blocks;
56 	off_t		used_blocks;
57 	int32		inode_size;
58 	int32		magic2;
59 	int32		blocks_per_ag;
60 	int32		ag_shift;
61 	int32		num_ags;
62 	int32		flags;
63 	block_run	log_blocks;
64 	off_t		log_start;
65 	off_t		log_end;
66 	int32		magic3;
67 	inode_addr	root_dir;
68 	inode_addr	indices;
69 	int32		pad[8];
70 };
71 
72 #define SUPER_BLOCK_FS_LENDIAN		'BIGE'		/* BIGE */
73 
74 #define SUPER_BLOCK_MAGIC1			'BFS1'		/* BFS1 */
75 #define SUPER_BLOCK_MAGIC2			0xdd121031
76 #define SUPER_BLOCK_MAGIC3			0x15b6830e
77 
78 #define SUPER_BLOCK_DISK_CLEAN		'CLEN'		/* CLEN */
79 #define SUPER_BLOCK_DISK_DIRTY		'DIRT'		/* DIRT */
80 
81 //**************************************
82 
83 #define NUM_DIRECT_BLOCKS			12
84 
85 struct data_stream
86 {
87 	block_run	direct[NUM_DIRECT_BLOCKS];
88 	off_t		max_direct_range;
89 	block_run	indirect;
90 	off_t		max_indirect_range;
91 	block_run	double_indirect;
92 	off_t		max_double_indirect_range;
93 	off_t		size;
94 };
95 
96 // This defines the size of the indirect and double indirect
97 // blocks. Note: the code may not work correctly at some places
98 // if this value is changed (it's not tested).
99 #define NUM_ARRAY_BLOCKS		4
100 #define ARRAY_BLOCKS_SHIFT		2
101 #define INDIRECT_BLOCKS_SHIFT	(ARRAY_BLOCKS_SHIFT + ARRAY_BLOCKS_SHIFT)
102 
103 //**************************************
104 
105 struct bfs_inode;
106 
107 struct small_data
108 {
109 	uint32		type;
110 	uint16		name_size;
111 	uint16		data_size;
112 	char		name[0];	// name_size long, followed by data
113 
114 	inline char		*Name();
115 	inline uint8	*Data();
116 	inline uint32	Size();
117 	inline small_data *Next();
118 	inline bool		IsLast(bfs_inode *inode);
119 };
120 
121 // the file name is part of the small_data structure
122 #define FILE_NAME_TYPE			'CSTR'
123 #define FILE_NAME_NAME			0x13
124 #define FILE_NAME_NAME_LENGTH	1
125 
126 //**************************************
127 
128 #define SHORT_SYMLINK_NAME_LENGTH	144 // length incl. terminating '\0'
129 
130 struct bfs_inode
131 {
132 	int32		magic1;
133 	inode_addr	inode_num;
134 	int32		uid;
135 	int32		gid;
136 	int32		mode;				// see sys/stat.h
137 	int32		flags;
138 	bigtime_t	create_time;
139 	bigtime_t	last_modified_time;
140 	inode_addr	parent;
141 	inode_addr	attributes;
142 	uint32		type;				// attribute type
143 
144 	int32		inode_size;
145 	uint32		etc;				// for in-memory structures (unused in OpenBeOS' fs)
146 
147 	union {
148 		data_stream		data;
149 		char 			short_symlink[SHORT_SYMLINK_NAME_LENGTH];
150 	};
151 	int32		pad[4];
152 	small_data	small_data_start[0];
153 };
154 
155 #define INODE_MAGIC1			0x3bbe0ad9
156 #define INODE_TIME_SHIFT		16
157 #define INODE_TIME_MASK			0xffff
158 #define INODE_FILE_NAME_LENGTH	256
159 
160 enum inode_flags
161 {
162 	INODE_IN_USE			= 0x00000001,	// always set
163 	INODE_ATTR_INODE		= 0x00000004,
164 	INODE_LOGGED			= 0x00000008,	// log changes to the data stream
165 	INODE_DELETED			= 0x00000010,
166 	INODE_LONG_SYMLINK		= 0x00000040,	// symlink in data stream
167 
168 	INODE_PERMANENT_FLAGS	= 0x0000ffff,
169 
170 	INODE_NO_CACHE			= 0x00010000,
171 	INODE_WAS_WRITTEN		= 0x00020000,
172 	INODE_NO_TRANSACTION	= 0x00040000,
173 	INODE_DONT_FREE_SPACE	= 0x00080000,	// only used by the "chkbfs" functionality
174 	INODE_NOT_READY			= 0x00100000,	// used during construction
175 	INODE_CHKBFS_RUNNING	= 0x00200000,
176 };
177 
178 //**************************************
179 
180 struct file_cookie {
181 	bigtime_t last_notification;
182 	off_t	last_size;
183 	int		open_mode;
184 };
185 
186 // notify every second if the file size has changed
187 #define INODE_NOTIFICATION_INTERVAL	1000000LL
188 
189 //**************************************
190 
191 
192 inline int32
193 divide_roundup(int32 num,int32 divisor)
194 {
195 	return (num + divisor - 1) / divisor;
196 }
197 
198 inline int64
199 divide_roundup(int64 num,int32 divisor)
200 {
201 	return (num + divisor - 1) / divisor;
202 }
203 
204 inline int
205 get_shift(uint64 i)
206 {
207 	int c;
208 	c = 0;
209 	while (i > 1) {
210 		i >>= 1;
211 		c++;
212 	}
213 	return c;
214 }
215 
216 inline int32
217 round_up(uint32 data)
218 {
219 	// rounds up to the next off_t boundary
220 	return (data + sizeof(off_t) - 1) & ~(sizeof(off_t) - 1);
221 }
222 
223 
224 /************************ block_run inline functions ************************/
225 //	#pragma mark -
226 
227 
228 inline bool
229 block_run::operator==(const block_run &run) const
230 {
231 	return allocation_group == run.allocation_group
232 		&& start == run.start
233 		&& length == run.length;
234 }
235 
236 
237 inline bool
238 block_run::operator!=(const block_run &run) const
239 {
240 	return allocation_group != run.allocation_group
241 		|| start != run.start
242 		|| length != run.length;
243 }
244 
245 
246 inline bool
247 block_run::IsZero()
248 {
249 	return allocation_group == 0 && start == 0 && length == 0;
250 }
251 
252 
253 inline bool
254 block_run::MergeableWith(block_run run) const
255 {
256 	// 65535 is the maximum allowed run size for BFS
257 	if (allocation_group == run.allocation_group
258 		&& start + length == run.start
259 		&& (uint32)length + run.length <= MAX_BLOCK_RUN_LENGTH)
260 		return true;
261 
262 	return false;
263 }
264 
265 
266 inline void
267 block_run::SetTo(int32 _group,uint16 _start,uint16 _length)
268 {
269 	allocation_group = _group;
270 	start = _start;
271 	length = _length;
272 }
273 
274 
275 inline block_run
276 block_run::Run(int32 group, uint16 start, uint16 length)
277 {
278 	block_run run;
279 	run.allocation_group = group;
280 	run.start = start;
281 	run.length = length;
282 	return run;
283 }
284 
285 
286 /************************ small_data inline functions ************************/
287 //	#pragma mark -
288 
289 
290 inline char *
291 small_data::Name()
292 {
293 	return name;
294 }
295 
296 
297 inline uint8 *
298 small_data::Data()
299 {
300 	return (uint8 *)name + name_size + 3;
301 }
302 
303 
304 inline uint32
305 small_data::Size()
306 {
307 	return sizeof(small_data) + name_size + 3 + data_size + 1;
308 }
309 
310 
311 inline small_data *
312 small_data::Next()
313 {
314 	return (small_data *)((uint8 *)this + Size());
315 }
316 
317 
318 inline bool
319 small_data::IsLast(bfs_inode *inode)
320 {
321 	// we need to check the location first, because if name_size is already beyond
322 	// the block, we would touch invalid memory (although that can't cause wrong
323 	// results)
324 	return (uint32)this > (uint32)inode + inode->inode_size - sizeof(small_data) || name_size == 0;
325 }
326 
327 #endif	/* BFS_H */
328