xref: /haiku/src/add-ons/kernel/file_systems/xfs/Inode.h (revision 4a850ca730d8282b5b924e49e09b4ba4d6db7f54)
1 /*
2  * Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com
3  * All rights reserved. Distributed under the terms of the MIT License.
4  */
5 #ifndef _INODE_H_
6 #define _INODE_H_
7 
8 
9 #include "system_dependencies.h"
10 #include "Volume.h"
11 #include "xfs_types.h"
12 
13 
14 #define INODE_MAGIC 0x494e
15 #define INODE_MINSIZE_LOG 8
16 #define INODE_MAXSIZE_LOG 11
17 #define INODE_CORE_SIZE 96
18 #define INODE_CORE_UNLINKED_SIZE 100
19 	// Inode core but with unlinked pointer
20 #define DATA_FORK_OFFSET 0x64
21 	// For v4 FS
22 #define INO_MASK(x)		((1ULL << (x)) - 1)
23 	// Gets 2^x - 1
24 #define INO_TO_AGNO(id, volume)	(xfs_agnumber_t)id >> (volume->AgInodeBits())
25 	// Gets AG number from inode number
26 #define INO_TO_AGINO(id, bits)	(uint32) id & INO_MASK(bits);
27 	// Gets the AG relative inode number
28 #define INO_TO_AGBLOCK(id, volume) \
29 		(id >> (volume->InodesPerBlkLog())) \
30 		& (INO_MASK(volume->AgBlocksLog()))
31 	// Gets the AG relative block number that contains inode
32 #define INO_TO_BLOCKOFFSET(id, volume) (id & INO_MASK(volume->InodesPerBlkLog()))
33 	// Gets the offset into the block from the inode number
34 #define DIR_DFORK_PTR(dir_ino_ptr) (void*) \
35 		((char*) dir_ino_ptr + DATA_FORK_OFFSET)
36 #define DIR_AFORK_PTR(dir_ino_ptr, forkoff) \
37 					(void*)((char*)DIR_DFORK_PTR(dir_ino_ptr) + \
38 					(((uint32)forkoff)<<3))
39 #define DIR_AFORK_EXIST(dir_ino_ptr) dir_ino_ptr->di_forkoff!=0
40 #define MASK(n) ((1UL << n) - 1)
41 #define FSBLOCKS_TO_AGNO(n, volume) ((n) >> volume->AgBlocksLog())
42 #define FSBLOCKS_TO_AGBLOCKNO(n, volume) ((n) & MASK(volume->AgBlocksLog()))
43 #define BLOCKNO_FROM_POSITION(n, volume) \
44 	((n) >> (volume->BlockLog()))
45 #define BLOCKOFFSET_FROM_POSITION(n, inode) ((n) & (inode->BlockSize() - 1))
46 
47 
48 // xfs_bmdr_block
49 struct BlockInDataFork {
50 			uint16				Levels()
51 									{ return
52 										B_BENDIAN_TO_HOST_INT16(bb_level); }
53 			uint16				NumRecords()
54 									{ return
55 										B_BENDIAN_TO_HOST_INT16(bb_numrecs); }
56 			uint16				bb_level;
57 			uint16				bb_numrecs;
58 };
59 
60 
61 // xfs_da_blkinfo_t
62 struct BlockInfo {
63 			uint32				forw;
64 			uint32				back;
65 			uint16				magic;
66 			uint16				pad;
67 };
68 
69 
70 struct ExtentMapEntry {
71 			xfs_fileoff_t		br_startoff;
72 				// logical file block offset
73 			xfs_fsblock_t		br_startblock;
74 				// absolute block number
75 			xfs_filblks_t		br_blockcount;
76 				// # of blocks
77 			uint8				br_state;
78 				// state of the extent
79 };
80 
81 
82 uint32
83 hashfunction(const char* name, int length);
84 
85 
86 struct xfs_timestamp_t {
87 		int32				t_sec;
88 		int32				t_nsec;
89 };
90 
91 
92 enum xfs_dinode_fmt_t {
93 		XFS_DINODE_FMT_DEV,
94 			// For devices
95 		XFS_DINODE_FMT_LOCAL,
96 			// For Directories and links
97 		XFS_DINODE_FMT_EXTENTS,
98 			// For large number of extents
99 		XFS_DINODE_FMT_BTREE,
100 			// Extents and Directories
101 		XFS_DINODE_FMT_UUID,
102 			// Not used
103 };
104 
105 /*
106  * The xfs_ino_t is the same for all types of inodes, the data and attribute
107  * fork might be different and that is to be handled accordingly.
108  */
109 struct xfs_inode_t {
110 			void				SwapEndian();
111 			int8				Version() const;
112 			mode_t				Mode() const;
113 			void				GetModificationTime(struct timespec&
114 									timestamp);
115 			void				GetChangeTime(struct timespec& timestamp);
116 			void				GetAccessTime(struct timespec& timestamp);
117 			int8				Format() const;
118 				// The format of the inode
119 			xfs_fsize_t			Size() const;
120 			xfs_rfsblock_t		BlockCount() const;
121 			uint32				NLink() const;
122 			uint16				Flags() const;
123 			uint32				UserId() const;
124 			uint32				GroupId() const;
125 			xfs_extnum_t		DataExtentsCount() const;
126 			uint8				ForkOffset() const;
127 			uint16				di_magic;
128 			uint16				di_mode;
129 				// uses standard S_Ixxx
130 			int8				di_version;
131 				//This either would be 1 or 2
132 			int8				di_format;
133 			uint16				di_onlink;
134 			uint32				di_uid;
135 			uint32				di_gid;
136 			uint32				di_nlink;
137 			uint16				di_projid;
138 			uint8				di_pad[8];
139 			uint16				di_flushiter;
140 			xfs_timestamp_t		di_atime;
141 			xfs_timestamp_t		di_mtime;
142 			xfs_timestamp_t		di_ctime;
143 			xfs_fsize_t			di_size;
144 				// size in bytes or length if link
145 			xfs_rfsblock_t		di_nblocks;
146 				// blocks used including metadata
147 				// extended attributes not included
148 			xfs_extlen_t		di_extsize;
149 				// extent size
150 			xfs_extnum_t		di_nextents;
151 				// number of data extents
152 			xfs_aextnum_t		di_anextents;
153 				// number of EA extents
154 			uint8				di_forkoff;
155 				// decides where di_a starts
156 			int8				di_aformat;
157 				// similar to di_format
158 			uint32				di_dmevmask;
159 			uint16				di_dmstate;
160 			uint16				di_flags;
161 			uint32				di_gen;
162 			uint32				di_next_unlinked;
163 };
164 
165 
166 class Inode {
167 public:
168 								Inode(Volume* volume, xfs_ino_t id);
169 								~Inode();
170 			status_t			Init();
171 
172 			xfs_ino_t			ID() const { return fId; }
173 
174 			bool				IsDirectory() const
175 									{ return S_ISDIR(Mode()); }
176 
177 			bool				IsFile() const
178 									{ return S_ISREG(Mode()); }
179 
180 			bool				IsSymLink() const
181 									{ return S_ISLNK(Mode()); }
182 
183 			mode_t				Mode() const { return fNode->Mode(); }
184 
185 			Volume*				GetVolume() { return fVolume;}
186 
187 			int8				Format() const { return fNode->Format(); }
188 
189 			bool				IsLocal() const
190 									{ return
191 										Format() == XFS_DINODE_FMT_LOCAL; }
192 
193 			uint32				NLink() const { return fNode->NLink(); }
194 
195 			int8				Version() const { return fNode->Version(); }
196 
197 			xfs_rfsblock_t		BlockCount() const
198 									{ return fNode->BlockCount(); }
199 
200 			char*				Buffer() { return fBuffer; }
201 
202 			int16				Flags() const { return fNode->Flags(); }
203 
204 			xfs_fsize_t			Size() const { return fNode->Size(); }
205 
206 			uint32				DirBlockSize() const
207 									{ return fVolume->DirBlockSize(); }
208 
209 			uint32				BlockSize() const
210 									{ return fVolume->BlockSize(); }
211 
212 			void				GetChangeTime(struct timespec& timestamp) const
213 								{ fNode->GetChangeTime(timestamp); }
214 
215 			void				GetModificationTime(struct timespec& timestamp)
216 									const
217 								{ fNode->GetModificationTime(timestamp); }
218 
219 			void				GetAccessTime(struct timespec& timestamp) const
220 								{ fNode->GetAccessTime(timestamp); }
221 
222 			status_t			CheckPermissions(int accessMode) const;
223 			uint32				UserId() const { return fNode->UserId(); }
224 			uint32				GroupId() const { return fNode->GroupId(); }
225 			bool				HasFileTypeField() const;
226 			xfs_extnum_t		DataExtentsCount() const
227 									{ return fNode->DataExtentsCount(); }
228 			uint64				FileSystemBlockToAddr(uint64 block);
229 			uint8				ForkOffset() const
230 									{ return fNode->ForkOffset(); }
231 			status_t			ReadExtents();
232 			status_t			ReadAt(off_t pos, uint8* buffer, size_t* length);
233 			status_t			GetNodefromTree(uint16& levelsInTree,
234 									Volume* volume, size_t& len,
235 									size_t DirBlockSize, char* block);
236 			int					SearchMapInAllExtent(int blockNo);
237 			void				UnWrapExtentFromWrappedEntry(
238 									uint64 wrappedExtent[2],
239 									ExtentMapEntry* entry);
240 			status_t			ReadExtentsFromExtentBasedInode();
241 			status_t			ReadExtentsFromTreeInode();
242 			size_t				MaxRecordsPossibleInTreeRoot();
243 			size_t				MaxRecordsPossibleNode();
244 			TreePointer*		GetPtrFromRoot(int pos);
245 			TreePointer*		GetPtrFromNode(int pos, void* buffer);
246 			size_t				GetPtrOffsetIntoRoot(int pos);
247 			size_t				GetPtrOffsetIntoNode(int pos);
248 private:
249 			status_t			GetFromDisk();
250 			xfs_inode_t*		fNode;
251 			xfs_ino_t			fId;
252 			Volume*				fVolume;
253 			char*				fBuffer;
254 				// Contains the disk inode in BE format
255 			ExtentMapEntry*		fExtents;
256 };
257 
258 #endif
259