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