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
24struct 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
76struct 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
92struct btrfs_timespec {
93	uint64	seconds;
94	uint32	nanoseconds;
95} _PACKED;
96
97
98struct 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
128struct 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
144struct 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
157struct btrfs_stream {
158	btrfs_header header;
159	union {
160		btrfs_entry entries[0];
161		btrfs_index index[0];
162	};
163} _PACKED;
164
165
166struct 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
175struct 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
202struct 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
220struct 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
275struct 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
322struct 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
339struct 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
359struct 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
388struct 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
421struct 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
433struct 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
444struct 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
453struct 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
528struct 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
537extern fs_volume_ops gBtrfsVolumeOps;
538extern fs_vnode_ops gBtrfsVnodeOps;
539
540
541#endif	// BTRFS_H
542