xref: /haiku/src/add-ons/kernel/file_systems/xfs/Extent.h (revision 52c4471a3024d2eb81fe88e2c3982b9f8daa5e56)
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 public:
56 
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 uuid_t*				Uuid()						=	0;
63 			static	uint32				ExpectedMagic(int8 WhichDirectory,
64 										Inode* inode);
65 			static	uint32				CRCOffset();
66 			static	ExtentDataHeader*	Create(Inode* inode, const char* buffer);
67 			static	uint32				Size(Inode* inode);
68 };
69 
70 
71 //xfs_dir_data_hdr_t
72 class ExtentDataHeaderV4 : public ExtentDataHeader {
73 public :
74 
75 								ExtentDataHeaderV4(const char* buffer);
76 								~ExtentDataHeaderV4();
77 			void				SwapEndian();
78 			uint32				Magic();
79 			uint64				Blockno();
80 			uint64				Lsn();
81 			uint64				Owner();
82 			uuid_t*				Uuid();
83 
84 			uint32				magic;
85 private:
86 			FreeRegion			bestfree[XFS_DIR2_DATA_FD_COUNT];
87 };
88 
89 
90 // xfs_dir3_data_hdr_t
91 class ExtentDataHeaderV5 : public ExtentDataHeader {
92 public:
93 								ExtentDataHeaderV5(const char* buffer);
94 								~ExtentDataHeaderV5();
95 			void				SwapEndian();
96 			uint32				Magic();
97 			uint64				Blockno();
98 			uint64				Lsn();
99 			uint64				Owner();
100 			uuid_t*				Uuid();
101 public:
102 			uint32				magic;
103 			uint32				crc;
104 private:
105 			uint64				blkno;
106 			uint64				lsn;
107 			uuid_t				uuid;
108 			uint64				owner;
109 			FreeRegion			bestfree[XFS_DIR2_DATA_FD_COUNT];
110 			uint32				pad;
111 };
112 
113 #define XFS_EXTENT_CRC_OFF  offsetof(ExtentDataHeaderV5, crc)
114 #define XFS_EXTENT_V5_VPTR_OFF offsetof(ExtentDataHeaderV5, magic)
115 #define XFS_EXTENT_V4_VPTR_OFF offsetof(ExtentDataHeaderV4, magic)
116 
117 
118 // xfs_dir2_data_entry_t
119 struct ExtentDataEntry {
120 			xfs_ino_t			inumber;
121 			uint8				namelen;
122 			uint8				name[];
123 
124 // Followed by a file type (8bit) if applicable and a 16bit tag
125 // tag is the offset from start of the block
126 };
127 
128 
129 // xfs_dir2_data_unused_t
130 struct ExtentUnusedEntry {
131 			uint16				freetag;
132 				// takes the value 0xffff
133 			uint16				length;
134 				// freetag+length overrides the inumber of an entry
135 			uint16				tag;
136 };
137 
138 
139 // xfs_dir2_leaf_entry_t
140 struct ExtentLeafEntry {
141 			uint32				hashval;
142 			uint32				address;
143 				// offset into block after >> 3
144 };
145 
146 
147 // xfs_dir2_block_tail_t
148 struct ExtentBlockTail {
149 			uint32				count;
150 				// # of entries in leaf
151 			uint32				stale;
152 				// # of free leaf entries
153 };
154 
155 
156 class Extent : public DirectoryIterator {
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