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
13typedef uint64 fileblock_t;		// file block number
14typedef 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
25struct 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
77struct 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
93struct btrfs_timespec {
94	uint64	seconds;
95	uint32	nanoseconds;
96} _PACKED;
97
98
99struct 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
129struct 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
145struct 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
158struct btrfs_stream {
159	btrfs_header header;
160	union {
161		btrfs_entry entries[0];
162		btrfs_index index[0];
163	};
164} _PACKED;
165
166
167struct 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
176struct 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
203struct 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
221struct 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
276struct 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
323struct 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
340struct 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
360struct 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
389struct 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
422struct 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
434struct 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
445struct 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
454struct 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
529struct 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
538extern fs_volume_ops gBtrfsVolumeOps;
539extern fs_vnode_ops gBtrfsVnodeOps;
540
541
542#endif	// BTRFS_H
543