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