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