xref: /haiku/src/add-ons/kernel/file_systems/btrfs/btrfs.h (revision 15fb7d88e971c4d6c787c6a3a5c159afb1ebf77b)
1 /*
2  * Copyright 2017, Chế Vũ Gia Hy, cvghy116@gmail.com.
3  * Copyright 2011, Jérôme Duval, korli@users.berlios.de.
4  * Distributed under the terms of the MIT License.
5  */
6 #ifndef BTRFS_H
7 #define BTRFS_H
8 
9 
10 #include "system_dependencies.h"
11 
12 
13 typedef uint64 fileblock_t;		// file block number
14 typedef uint64 fsblock_t;		// filesystem block number
15 
16 #define BTRFS_LABEL_SIZE					256
17 
18 #define BTRFS_SUPER_BLOCK_OFFSET			0x10000	 // 64KiB
19 #define BTRFS_RESERVED_SPACE_OFFSET			0x100000 // 1MiB
20 
21 #define BTRFS_NUM_ROOT_BACKUPS				4
22 
23 
24 struct btrfs_backup_roots {
25 	uint64	root;
26 	uint64	root_generation;
27 	uint64	chunk_root;
28 	uint64	chunk_root_generation;
29 	uint64	extent_root;
30 	uint64	extent_root_generation;
31 	uint64	fs_root;
32 	uint64	fs_root_generation;
33 	uint64	device_root;
34 	uint64	device_root_generation;
35 	uint64	csum_root;
36 	uint64	csum_root_generation;
37 	uint64	total_size;
38 	uint64	used_size;
39 	uint64	num_devices;
40 	uint8	unused_1[32];
41 	uint8	root_level;
42 	uint8	chunk_root_level;
43 	uint8	extent_root_level;
44 	uint8	fs_root_level;
45 	uint8	device_root_level;
46 	uint8	csum_root_level;
47 	uint8	unused_2[10];
48 
49 	uint64 Root() const { return B_LENDIAN_TO_HOST_INT64(root); }
50 	uint64 RootGen() const
51 		{ return B_LENDIAN_TO_HOST_INT64(root_generation); }
52 	uint64 ChunkRoot() const { return B_LENDIAN_TO_HOST_INT64(chunk_root); }
53 	uint64 ChunkRootGen() const
54 		{ return B_LENDIAN_TO_HOST_INT64(chunk_root_generation); }
55 	uint64 ExtentRoot() const { return B_LENDIAN_TO_HOST_INT64(extent_root); }
56 	uint64 ExtentRootGen() const
57 		{ return B_LENDIAN_TO_HOST_INT64(extent_root_generation); }
58 	uint64 FSRoot() const { return B_LENDIAN_TO_HOST_INT64(fs_root); }
59 	uint64 FSRootGen() const
60 		{ return B_LENDIAN_TO_HOST_INT64(fs_root_generation); }
61 	uint64 DeviceRoot() const { return B_LENDIAN_TO_HOST_INT64(device_root); }
62 	uint64 DeviceRootGen() const
63 		{ return B_LENDIAN_TO_HOST_INT64(device_root_generation); }
64 	uint64 CSumRoot() const { return B_LENDIAN_TO_HOST_INT64(csum_root); }
65 	uint64 CSumRootGen() const
66 		{ return B_LENDIAN_TO_HOST_INT64(csum_root_generation); }
67 	uint8 RootLevel() const { return root_level; }
68 	uint8 ChunkRootLevel() const { return chunk_root_level; }
69 	uint8 ExtentRootLevel() const { return extent_root_level; }
70 	uint8 FSRootLevel() const { return fs_root_level; }
71 	uint8 DeviceRootLevel() const { return device_root_level; }
72 	uint8 CSumRootLevel() const { return csum_root_level; }
73 } _PACKED;
74 
75 
76 struct btrfs_key {
77 	uint64	object_id;
78 	uint8	type;
79 	uint64	offset;
80 
81 	uint64	ObjectID() const { return B_LENDIAN_TO_HOST_INT64(object_id); }
82 	uint8	Type() const { return type; }
83 	uint64	Offset() const { return B_LENDIAN_TO_HOST_INT64(offset); }
84 	void SetObjectID(uint64 id) { object_id = B_HOST_TO_LENDIAN_INT64(id); }
85 	void SetType(uint8 key_type) { type = key_type; }
86 	void SetOffset(uint64 off) { offset = B_HOST_TO_LENDIAN_INT64(off); }
87 	int32 Compare(const btrfs_key& key) const;
88 		// implemented in BTree.cpp
89 } _PACKED;
90 
91 
92 struct btrfs_timespec {
93 	uint64	seconds;
94 	uint32	nanoseconds;
95 } _PACKED;
96 
97 
98 struct btrfs_header {
99 	uint8	checksum[32];
100 	uuid_t	fsid;
101 	uint64	logical_address;
102 	uint64	flags;
103 	uuid_t	chunk_tree_uuid;
104 	uint64	generation;
105 	uint64	owner;
106 	uint32	item_count;
107 	uint8	level;
108 	uint64 LogicalAddress() const
109 		{ return B_LENDIAN_TO_HOST_INT64(logical_address); }
110 	uint64 Flags() const { return B_LENDIAN_TO_HOST_INT64(flags); }
111 	uint64 Generation() const
112 		{ return B_LENDIAN_TO_HOST_INT64(generation); }
113 	uint64 Owner() const
114 		{ return B_LENDIAN_TO_HOST_INT64(owner); }
115 	uint32 ItemCount() const
116 		{ return B_LENDIAN_TO_HOST_INT32(item_count); }
117 	uint8 Level() const { return level; }
118 
119 	void SetLogicalAddress(uint64 logical)
120 		{ logical_address = B_HOST_TO_LENDIAN_INT64(logical); }
121 	void SetGeneration(uint64 gen)
122 		{ generation = B_HOST_TO_LENDIAN_INT64(gen); }
123 	void SetItemCount(uint32 itemCount)
124 		{ item_count = B_HOST_TO_LENDIAN_INT32(itemCount); }
125 } _PACKED;
126 
127 
128 struct btrfs_index {
129 	btrfs_key key;
130 	uint64	logical_address;
131 	uint64	generation;
132 	uint64 LogicalAddress() const
133 		{ return B_LENDIAN_TO_HOST_INT64(logical_address); }
134 	uint64 Generation() const
135 		{ return B_LENDIAN_TO_HOST_INT64(generation); }
136 
137 	void SetLogicalAddress(uint64 address)
138 		{ logical_address = B_HOST_TO_LENDIAN_INT64(address); }
139 	void SetGeneration(uint64 gen)
140 		{ generation = B_HOST_TO_LENDIAN_INT64(gen); }
141 } _PACKED;
142 
143 
144 struct btrfs_entry {
145 	btrfs_key key;
146 	uint32 offset;
147 	uint32 size;
148 	uint32 Offset() const
149 		{ return B_LENDIAN_TO_HOST_INT32(offset); }
150 	uint32 Size() const
151 		{ return B_LENDIAN_TO_HOST_INT32(size); }
152 	void SetOffset(uint32 off) { offset = B_HOST_TO_LENDIAN_INT32(off); }
153 	void SetSize(uint32 itemSize) { size = B_HOST_TO_LENDIAN_INT32(itemSize); }
154 } _PACKED;
155 
156 
157 struct btrfs_stream {
158 	btrfs_header header;
159 	union {
160 		btrfs_entry entries[0];
161 		btrfs_index index[0];
162 	};
163 } _PACKED;
164 
165 
166 struct btrfs_stripe {
167 	uint64	device_id;
168 	uint64	offset;
169 	uuid_t	device_uuid;
170 	uint64	DeviceID() const { return B_LENDIAN_TO_HOST_INT64(device_id); }
171 	uint64	Offset() const { return B_LENDIAN_TO_HOST_INT64(offset); }
172 } _PACKED;
173 
174 
175 struct btrfs_chunk {
176 	uint64	length;
177 	uint64	owner;
178 	uint64	stripe_length;
179 	uint64	type;
180 	uint32	io_align;
181 	uint32	io_width;
182 	uint32	sector_size;
183 	uint16	stripe_count;
184 	uint16	sub_stripes;
185 	btrfs_stripe stripes[0];
186 	uint64 Length() const { return B_LENDIAN_TO_HOST_INT64(length); }
187 	uint64 Owner() const { return B_LENDIAN_TO_HOST_INT64(owner); }
188 	uint64 StripeLength() const
189 		{ return B_LENDIAN_TO_HOST_INT64(stripe_length); }
190 	uint64 Type() const { return B_LENDIAN_TO_HOST_INT64(type); }
191 	uint32 IOAlign() const { return B_LENDIAN_TO_HOST_INT32(io_align); }
192 	uint32 IOWidth() const { return B_LENDIAN_TO_HOST_INT32(io_width); }
193 	uint32 SectorSize() const
194 		{ return B_LENDIAN_TO_HOST_INT32(sector_size); }
195 	uint16 StripeCount() const
196 		{ return B_LENDIAN_TO_HOST_INT16(stripe_count); }
197 	uint16 SubStripes() const
198 		{ return B_LENDIAN_TO_HOST_INT16(sub_stripes); }
199 } _PACKED;
200 
201 
202 struct btrfs_device {
203 	uint64	id;
204 	uint64	total_size;
205 	uint64	used_size;
206 	uint32	io_align;
207 	uint32	io_width;
208 	uint32	sector_size;
209 	uint64	type;
210 	uint64	generation;
211 	uint64	start_offset;
212 	uint32	group;
213 	uint8	seek_speed;
214 	uint8	bandwidth;
215 	uuid_t	uuid;
216 	uuid_t	fsid;
217 } _PACKED;
218 
219 
220 struct btrfs_super_block {
221 	uint8	checksum[32];
222 	uuid_t	fsid;
223 	uint64	blocknum;
224 	uint64	flags;
225 	char	magic[8];
226 	uint64	generation;
227 	uint64	root;
228 	uint64	chunk_root;
229 	uint64	log_root;
230 	uint64	log_root_transaction_id;
231 	uint64	total_size;
232 	uint64	used_size;
233 	uint64	root_dir_object_id;
234 	uint64	num_devices;
235 	uint32	sector_size;
236 	uint32	node_size;
237 	uint32	leaf_size;
238 	uint32	stripe_size;
239 	uint32	system_chunk_array_size;
240 	uint64	chunk_root_generation;
241 	uint64	compat_flags;
242 	uint64	readonly_flags;
243 	uint64	incompat_flags;
244 	uint16	checksum_type;
245 	uint8	root_level;
246 	uint8	chunk_root_level;
247 	uint8	log_root_level;
248 	btrfs_device device;
249 	char	label[BTRFS_LABEL_SIZE];
250 	uint64	reserved[32];
251 	uint8	system_chunk_array[2048];
252 	btrfs_backup_roots backup_roots[BTRFS_NUM_ROOT_BACKUPS];
253 
254 	// implemented in Volume.cpp:
255 	bool IsValid() const;
256 	void Initialize(const char* name, off_t numBlocks,
257 			uint32 blockSize, uint32 sectorSize);
258 	uint64 TotalSize() const { return B_LENDIAN_TO_HOST_INT64(total_size); }
259 	uint32 BlockSize() const { return B_LENDIAN_TO_HOST_INT32(node_size); }
260 	uint32 SectorSize() const { return B_LENDIAN_TO_HOST_INT32(sector_size); }
261 	uint64 RootDirObjectID() const
262 		{ return B_LENDIAN_TO_HOST_INT64(root_dir_object_id); }
263 	uint64 Generation() const
264 		{ return B_LENDIAN_TO_HOST_INT64(generation); }
265 	uint64 Root() const
266 		{ return B_LENDIAN_TO_HOST_INT64(root); }
267 	uint64 ChunkRoot() const
268 		{ return B_LENDIAN_TO_HOST_INT64(chunk_root); }
269 	uint64 LogRoot() const
270 		{ return B_LENDIAN_TO_HOST_INT64(log_root); }
271 	uint8 ChunkRootLevel() const { return chunk_root_level; }
272 } _PACKED;
273 
274 
275 struct btrfs_inode {
276 	uint64	generation;
277 	uint64	transaction_id;
278 	uint64	size;
279 	uint64	nbytes;
280 	uint64	blockgroup;
281 	uint32	num_links;
282 	uint32	uid;
283 	uint32	gid;
284 	uint32	mode;
285 	uint64	rdev;
286 	uint64	flags;
287 	uint64	sequence;
288 	uint64	reserved[4];
289 	btrfs_timespec access_time;
290 	btrfs_timespec change_time;
291 	btrfs_timespec modification_time;
292 	btrfs_timespec creation_time;
293 	uint64 Generation() const { return B_LENDIAN_TO_HOST_INT64(generation); }
294 	uint64 Size() const { return B_LENDIAN_TO_HOST_INT64(size); }
295 	uint32 UserID() const { return B_LENDIAN_TO_HOST_INT32(uid); }
296 	uint32 GroupID() const { return B_LENDIAN_TO_HOST_INT32(gid); }
297 	uint32 Mode() const { return B_LENDIAN_TO_HOST_INT32(mode); }
298 	uint64 Flags() const { return B_LENDIAN_TO_HOST_INT64(flags); }
299 	uint64 Sequence() const { return B_LENDIAN_TO_HOST_INT64(sequence); }
300 	static void _DecodeTime(struct timespec& timespec,
301 		const btrfs_timespec& time)
302 	{
303 		timespec.tv_sec = B_LENDIAN_TO_HOST_INT64(time.seconds);
304 		timespec.tv_nsec = B_LENDIAN_TO_HOST_INT32(time.nanoseconds);
305 	}
306 	void GetAccessTime(struct timespec& timespec) const
307 		{ _DecodeTime(timespec, access_time); }
308 	void GetChangeTime(struct timespec& timespec) const
309 		{ _DecodeTime(timespec, change_time); }
310 	void GetModificationTime(struct timespec& timespec) const
311 		{ _DecodeTime(timespec, modification_time); }
312 	void GetCreationTime(struct timespec& timespec) const
313 		{ _DecodeTime(timespec, creation_time); }
314 	static void SetTime(btrfs_timespec& time, const struct timespec& timespec)
315 	{
316 		time.seconds = B_HOST_TO_LENDIAN_INT64(timespec.tv_sec);
317 		time.nanoseconds = B_HOST_TO_LENDIAN_INT64(timespec.tv_nsec);
318 	}
319 } _PACKED;
320 
321 
322 struct btrfs_inode_ref {
323 	uint64	index;
324 	uint16	name_length;
325 	uint8	name[];
326 
327 	uint64 Index() const { return index; }
328 	uint16 NameLength() const { return B_LENDIAN_TO_HOST_INT16(name_length); }
329 	uint16 Length() const
330 		{ return sizeof(btrfs_inode_ref) + NameLength(); }
331 	void SetName(const char* name, uint16 nameLength)
332 	{
333 		name_length = B_HOST_TO_LENDIAN_INT16(nameLength);
334 		memcpy(this->name, name, nameLength);
335 	}
336 } _PACKED;
337 
338 
339 struct btrfs_root {
340 	btrfs_inode inode;
341 	uint64	generation;
342 	uint64	root_dirid;
343 	uint64	logical_address;
344 	uint64	limit_bytes;
345 	uint64	used_bytes;
346 	uint64	last_snapshot;
347 	uint64	flags;
348 	uint32	refs;
349 	btrfs_key drop_progress;
350 	uint8	drop_level;
351 	uint8	level;
352 	uint64 Generation() const
353 		{ return B_LENDIAN_TO_HOST_INT64(generation); }
354 	uint64 LogicalAddress() const
355 		{ return B_LENDIAN_TO_HOST_INT64(logical_address); }
356 } _PACKED;
357 
358 
359 struct btrfs_dir_entry {
360 	btrfs_key location;
361 	uint64	transaction_id;
362 	uint16	data_length;
363 	uint16	name_length;
364 	uint8	type;
365 	uint8	name[];
366 	// if attribute data exists, it goes here
367 	uint16 DataLength() const { return B_LENDIAN_TO_HOST_INT16(data_length); }
368 	uint16 NameLength() const { return B_LENDIAN_TO_HOST_INT16(name_length); }
369 	ino_t InodeID() const { return location.ObjectID(); }
370 	uint16 Length() const
371 		{ return sizeof(*this) + NameLength() + DataLength(); }
372 	void SetTransactionID(uint64 id)
373 		{ transaction_id = B_HOST_TO_LENDIAN_INT64(id); }
374 	void SetAttributeData(void* data, uint16 dataLength)
375 	{
376 		data_length = B_HOST_TO_LENDIAN_INT16(dataLength);
377 		if (data != NULL)
378 			memcpy(&name[name_length], data, dataLength);
379 	}
380 	void SetName(const char* name, uint16 nameLength)
381 	{
382 		name_length = B_HOST_TO_LENDIAN_INT16(nameLength);
383 		memcpy(this->name, name, nameLength);
384 	}
385 } _PACKED;
386 
387 
388 struct btrfs_extent_data {
389 	uint64	generation;
390 	uint64	memory_size;
391 	uint8	compression;
392 	uint8	encryption;
393 	uint16	reserved;
394 	uint8	type;
395 	union {
396 		struct {
397 			uint64	disk_offset;
398 			uint64	disk_size;
399 			uint64	extent_offset;
400 			uint64	size;
401 		};
402 		uint8 inline_data[0];
403 	};
404 	uint64 Generation() const
405 		{ return B_LENDIAN_TO_HOST_INT64(generation); }
406 	uint64 MemoryBytes() const
407 		{ return B_LENDIAN_TO_HOST_INT64(memory_size); }
408 	uint8 Compression() const { return compression; }
409 	uint8 Type() const { return type; }
410 	uint64 DiskOffset() const
411 		{ return B_LENDIAN_TO_HOST_INT64(disk_offset); }
412 	uint64 DiskSize() const
413 		{ return B_LENDIAN_TO_HOST_INT64(disk_size); }
414 	uint64 ExtentOffset() const
415 		{ return B_LENDIAN_TO_HOST_INT64(extent_offset); }
416 	uint64 Size() const
417 		{ return B_LENDIAN_TO_HOST_INT64(size); }
418 } _PACKED;
419 
420 
421 struct btrfs_block_group {
422 	uint64	used_space;
423 	uint64	chunk_object_id;
424 	uint64	flags;
425 
426 	uint64 UsedSpace() const { return B_LENDIAN_TO_HOST_INT64(used_space); }
427 	uint64 ChunkObjectID() const
428 		{ return B_LENDIAN_TO_HOST_INT64(chunk_object_id); }
429 	uint64 Flags() const { return B_LENDIAN_TO_HOST_INT64(flags); }
430 } _PACKED;
431 
432 
433 struct btrfs_extent {
434 	uint64	refs;
435 	uint64	generation;
436 	uint64	flags;
437 
438 	uint64 RefCount() const { return B_LENDIAN_TO_HOST_INT64(refs); }
439 	uint64 Generation() const { return B_LENDIAN_TO_HOST_INT64(generation); }
440 	uint64 Flags() const { return B_LENDIAN_TO_HOST_INT64(flags); }
441 } _PACKED;
442 
443 
444 struct btrfs_extent_inline_ref {
445 	uint8	type;
446 	uint64	offset;
447 
448 	uint8 Type() const { return type; }
449 	uint64 Offset() const { return B_LENDIAN_TO_HOST_INT64(offset); }
450 } _PACKED;
451 
452 
453 struct btrfs_extent_data_ref {
454 	uint64	root_id;
455 	uint64	inode_id;
456 	uint64	offset;
457 	uint32	ref_count;
458 
459 	uint64 RootID() const { return B_LENDIAN_TO_HOST_INT64(root_id); }
460 	uint64 InodeID() const { return B_LENDIAN_TO_HOST_INT64(inode_id); }
461 	uint64 Offset() const { return B_LENDIAN_TO_HOST_INT64(offset);}
462 	uint32 RefCount() const { return B_LENDIAN_TO_HOST_INT32(ref_count); }
463 } _PACKED;
464 
465 #define BTRFS_SUPER_BLOCK_MAGIC				"_BHRfS_M"
466 #define BTRFS_SUPER_BLOCK_MAGIC_TEMPORARY	"!BHRfS_M"
467 
468 #define BTRFS_FIRST_SUBVOLUME				256
469 
470 #define BTRFS_CSUM_TYPE_CRC32				0
471 
472 #define BTRFS_OBJECT_ID_ROOT_TREE			1
473 #define BTRFS_OBJECT_ID_EXTENT_TREE			2
474 #define BTRFS_OBJECT_ID_CHUNK_TREE			3
475 #define BTRFS_OBJECT_ID_DEV_TREE			4
476 #define BTRFS_OBJECT_ID_FS_TREE				5
477 #define BTRFS_OBJECT_ID_ROOT_TREE_DIR		6
478 #define BTRFS_OBJECT_ID_CHECKSUM_TREE		7
479 #define BTRFS_OBJECT_ID_FIRST_CHUNK_TREE	256
480 
481 #define BTRFS_KEY_TYPE_ANY					0
482 #define BTRFS_KEY_TYPE_INODE_ITEM			1
483 #define BTRFS_KEY_TYPE_INODE_REF			12
484 #define BTRFS_KEY_TYPE_XATTR_ITEM			24
485 #define BTRFS_KEY_TYPE_DIR_ITEM				84
486 #define BTRFS_KEY_TYPE_DIR_INDEX			96
487 #define BTRFS_KEY_TYPE_EXTENT_DATA			108
488 #define BTRFS_KEY_TYPE_ROOT_ITEM			132
489 #define BTRFS_KEY_TYPE_EXTENT_ITEM			168
490 #define BTRFS_KEY_TYPE_METADATA_ITEM		169
491 #define BTRFS_KEY_TYPE_EXTENT_DATA_REF		178
492 #define BTRFS_KEY_TYPE_BLOCKGROUP_ITEM		192
493 #define BTRFS_KEY_TYPE_CHUNK_ITEM			228
494 
495 #define BTRFS_EXTENT_COMPRESS_NONE			0
496 #define BTRFS_EXTENT_COMPRESS_ZLIB			1
497 #define BTRFS_EXTENT_COMPRESS_LZO			2
498 #define BTRFS_EXTENT_DATA_INLINE			0
499 #define BTRFS_EXTENT_DATA_REGULAR			1
500 #define BTRFS_EXTENT_DATA_PRE				2
501 #define BTRFS_EXTENT_FLAG_DATA				1
502 #define BTRFS_EXTENT_FLAG_TREE_BLOCK		2
503 #define BTRFS_EXTENT_FLAG_ALLOCATED			4
504 
505 #define BTRFS_BLOCKGROUP_FLAG_DATA			1
506 #define BTRFS_BLOCKGROUP_FLAG_SYSTEM		2
507 #define BTRFS_BLOCKGROUP_FLAG_METADATA		4
508 #define BTRFS_BLOCKGROUP_FLAG_RAID0			8
509 #define BTRFS_BLOCKGROUP_FLAG_RAID1			16
510 #define BTRFS_BLOCKGROUP_FLAG_DUP			32
511 #define BTRFS_BLOCKGROUP_FLAG_RAID10		64
512 #define BTRFS_BLOCKGROUP_FLAG_RAID5			128
513 #define BTRFS_BLOCKGROUP_FLAG_RAID6			256
514 #define BTRFS_BLOCKGROUP_FLAG_MASK			511
515 
516 // d_type in struct dirent
517 #define BTRFS_FILETYPE_UNKNOWN				0
518 #define BTRFS_FILETYPE_REGULAR				1
519 #define BTRFS_FILETYPE_DIRECTORY			2
520 #define BTRFS_FILETYPE_CHRDEV				3	// character device
521 #define BTRFS_FILETYPE_BLKDEV				4	// block device
522 #define BTRFS_FILETYPE_FIFO					5	// fifo device
523 #define BTRFS_FILETYPE_SOCKET				6
524 #define BTRFS_FILETYPE_SYMLINK				7
525 #define BTRFS_FILETYPE_XATTR				8	// ondisk but not user-visible
526 
527 
528 struct file_cookie {
529 	bigtime_t	last_notification;
530 	off_t		last_size;
531 	int			open_mode;
532 };
533 
534 
535 #define BTRFS_OPEN_MODE_USER_MASK		0x7fffffff
536 
537 extern fs_volume_ops gBtrfsVolumeOps;
538 extern fs_vnode_ops gBtrfsVnodeOps;
539 
540 
541 #endif	// BTRFS_H
542