xref: /haiku/src/add-ons/kernel/file_systems/xfs/Extent.h (revision 44cceee67e056d8e34cb017d5f5c07b9fac874c0)
1 /*
2  * Copyright 2022, Raghav Sharma, raghavself28@gmail.com
3  * Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com
4  * All rights reserved. Distributed under the terms of the MIT License.
5  */
6 #ifndef _EXTENT_H_
7 #define _EXTENT_H_
8 
9 
10 #include "Inode.h"
11 #include "system_dependencies.h"
12 
13 
14 #define DIR2_BLOCK_HEADER_MAGIC 0x58443242
15 	// for v4 system
16 #define DIR3_BLOCK_HEADER_MAGIC 0x58444233
17 	// for v5 system
18 #define DIR2_FREE_TAG 0xffff
19 #define XFS_DIR2_DATA_FD_COUNT 3
20 #define EXTENT_REC_SIZE		128
21 #define EXTENT_SIZE 16
22 #define BLOCKNO_FROM_ADDRESS(n, volume) \
23 	((n) >> (volume->BlockLog() + volume->DirBlockLog()))
24 #define BLOCKOFFSET_FROM_ADDRESS(n, inode) ((n) & (inode->DirBlockSize() - 1))
25 #define LEAF_STARTOFFSET(n) 1UL << (35 - (n))
26 
27 
28 // xfs_exntst_t
29 enum ExtentState {
30 	XFS_EXT_NORM,
31 	XFS_EXT_UNWRITTEN,
32 	XFS_EXT_INVALID
33 };
34 
35 
36 // Enum values to check which directory we are reading
37 enum DirectoryType {
38 	XFS_BLOCK,
39 	XFS_LEAF,
40 	XFS_NODE,
41 	XFS_BTREE,
42 };
43 
44 
45 // xfs_dir2_data_free_t
46 struct FreeRegion {
47 			uint16				offset;
48 			uint16				length;
49 };
50 
51 
52 // This class will act as interface for V4 and V5 data header
53 class ExtentDataHeader {
54 public:
55 
56 			virtual						~ExtentDataHeader()			=	0;
57 			virtual uint32				Magic()						=	0;
58 			virtual uint64				Blockno()					=	0;
59 			virtual uint64				Lsn()						=	0;
60 			virtual uint64				Owner()						=	0;
61 			virtual uuid_t*				Uuid()						=	0;
62 			static	uint32				ExpectedMagic(int8 WhichDirectory,
63 										Inode* inode);
64 			static	uint32				CRCOffset();
65 			static	ExtentDataHeader*	Create(Inode* inode, const char* buffer);
66 			static	uint32				Size(Inode* inode);
67 };
68 
69 
70 //xfs_dir_data_hdr_t
71 class ExtentDataHeaderV4 : public ExtentDataHeader {
72 public :
73 
74 								ExtentDataHeaderV4(const char* buffer);
75 								~ExtentDataHeaderV4();
76 			void				SwapEndian();
77 			uint32				Magic();
78 			uint64				Blockno();
79 			uint64				Lsn();
80 			uint64				Owner();
81 			uuid_t*				Uuid();
82 
83 			uint32				magic;
84 private:
85 			FreeRegion			bestfree[XFS_DIR2_DATA_FD_COUNT];
86 };
87 
88 
89 // xfs_dir3_data_hdr_t
90 class ExtentDataHeaderV5 : public ExtentDataHeader {
91 public:
92 								ExtentDataHeaderV5(const char* buffer);
93 								~ExtentDataHeaderV5();
94 			void				SwapEndian();
95 			uint32				Magic();
96 			uint64				Blockno();
97 			uint64				Lsn();
98 			uint64				Owner();
99 			uuid_t*				Uuid();
100 public:
101 			uint32				magic;
102 			uint32				crc;
103 private:
104 			uint64				blkno;
105 			uint64				lsn;
106 			uuid_t				uuid;
107 			uint64				owner;
108 			FreeRegion			bestfree[XFS_DIR2_DATA_FD_COUNT];
109 			uint32				pad;
110 };
111 
112 #define XFS_EXTENT_CRC_OFF  offsetof(ExtentDataHeaderV5, crc)
113 #define XFS_EXTENT_V5_VPTR_OFF offsetof(ExtentDataHeaderV5, magic)
114 #define XFS_EXTENT_V4_VPTR_OFF offsetof(ExtentDataHeaderV4, magic)
115 
116 
117 // xfs_dir2_data_entry_t
118 struct ExtentDataEntry {
119 			xfs_ino_t			inumber;
120 			uint8				namelen;
121 			uint8				name[];
122 
123 // Followed by a file type (8bit) if applicable and a 16bit tag
124 // tag is the offset from start of the block
125 };
126 
127 
128 // xfs_dir2_data_unused_t
129 struct ExtentUnusedEntry {
130 			uint16				freetag;
131 				// takes the value 0xffff
132 			uint16				length;
133 				// freetag+length overrides the inumber of an entry
134 			uint16				tag;
135 };
136 
137 
138 // xfs_dir2_leaf_entry_t
139 struct ExtentLeafEntry {
140 			uint32				hashval;
141 			uint32				address;
142 				// offset into block after >> 3
143 };
144 
145 
146 // xfs_dir2_block_tail_t
147 struct ExtentBlockTail {
148 			uint32				count;
149 				// # of entries in leaf
150 			uint32				stale;
151 				// # of free leaf entries
152 };
153 
154 
155 class Extent
156 {
157 public:
158 								Extent(Inode* inode);
159 								~Extent();
160 			status_t			Init();
161 			bool				IsBlockType();
162 			void				FillMapEntry(void* pointerToMap);
163 			status_t			FillBlockBuffer();
164 			ExtentBlockTail*	BlockTail();
165 			ExtentLeafEntry*	BlockFirstLeaf(ExtentBlockTail* tail);
166 			xfs_ino_t			GetIno();
167 			uint32				GetOffsetFromAddress(uint32 address);
168 			int					EntrySize(int len) const;
169 			status_t			GetNext(char* name, size_t* length,
170 									xfs_ino_t* ino);
171 			status_t			Lookup(const char* name, size_t length,
172 									xfs_ino_t* id);
173 private:
174 			Inode*				fInode;
175 			ExtentMapEntry*		fMap;
176 			uint32				fOffset;
177 			char*				fBlockBuffer;
178 				// This isn't inode data. It holds the directory block.
179 };
180 
181 #endif
182