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