xref: /haiku/src/add-ons/kernel/file_systems/xfs/Inode.cpp (revision 7cea5bf07ffaec7e25508f3b81a2e5bd989e1b34)
1 /*
2  * Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com
3  * All rights reserved. Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "Inode.h"
8 
9 
10 void
11 xfs_inode_t::SwapEndian()
12 {
13 	di_magic = B_BENDIAN_TO_HOST_INT16(di_magic);
14 	di_mode = B_BENDIAN_TO_HOST_INT16(di_mode);
15 	di_onlink = B_BENDIAN_TO_HOST_INT16(di_onlink);
16 	di_uid = B_BENDIAN_TO_HOST_INT32(di_uid);
17 	di_gid = B_BENDIAN_TO_HOST_INT32(di_gid);
18 	di_nlink = B_BENDIAN_TO_HOST_INT32(di_nlink);
19 	di_projid = B_BENDIAN_TO_HOST_INT16(di_projid);
20 	di_flushiter = B_BENDIAN_TO_HOST_INT16(di_flushiter);
21 	di_atime.t_sec = B_BENDIAN_TO_HOST_INT32(di_atime.t_sec);
22 	di_atime.t_nsec = B_BENDIAN_TO_HOST_INT32(di_atime.t_nsec);
23 	di_mtime.t_sec = B_BENDIAN_TO_HOST_INT32(di_mtime.t_sec);
24 	di_mtime.t_nsec = B_BENDIAN_TO_HOST_INT32(di_mtime.t_nsec);
25 	di_ctime.t_sec = B_BENDIAN_TO_HOST_INT32(di_ctime.t_sec);
26 	di_ctime.t_nsec = B_BENDIAN_TO_HOST_INT32(di_ctime.t_nsec);
27 	di_size = B_BENDIAN_TO_HOST_INT64(di_size);
28 	di_nblocks =  B_BENDIAN_TO_HOST_INT64(di_nblocks);
29 	di_extsize = B_BENDIAN_TO_HOST_INT32(di_extsize);
30 	di_nextents = B_BENDIAN_TO_HOST_INT32(di_nextents);
31 	di_anextents = B_BENDIAN_TO_HOST_INT16(di_anextents);
32 	di_dmevmask = B_BENDIAN_TO_HOST_INT32(di_dmevmask);
33 	di_dmstate = B_BENDIAN_TO_HOST_INT16(di_dmstate);
34 	di_flags = B_BENDIAN_TO_HOST_INT16(di_flags);
35 	di_gen = B_BENDIAN_TO_HOST_INT32(di_gen);
36 	di_next_unlinked = B_BENDIAN_TO_HOST_INT32(di_next_unlinked);
37 }
38 
39 
40 xfs_rfsblock_t
41 xfs_inode_t::NoOfBlocks() const
42 {
43 	return di_nblocks;
44 }
45 
46 
47 xfs_fsize_t
48 xfs_inode_t::Size() const
49 {
50 	return di_size;
51 }
52 
53 
54 mode_t
55 xfs_inode_t::Mode() const
56 {
57 	return di_mode;
58 }
59 
60 
61 uint32
62 xfs_inode_t::UserId() const
63 {
64 	return di_uid;
65 }
66 
67 
68 uint32
69 xfs_inode_t::GroupId() const
70 {
71 	return di_gid;
72 }
73 
74 
75 void
76 xfs_inode_t::GetModificationTime(struct timespec& stamp)
77 {
78 	stamp.tv_sec = di_mtime.t_sec;
79 	stamp.tv_nsec = di_mtime.t_nsec;
80 }
81 
82 
83 void
84 xfs_inode_t::GetAccessTime(struct timespec& stamp)
85 {
86 	stamp.tv_sec = di_atime.t_sec;
87 	stamp.tv_nsec = di_atime.t_nsec;
88 }
89 
90 
91 void
92 xfs_inode_t::GetChangeTime(struct timespec& stamp)
93 {
94 	stamp.tv_sec = di_ctime.t_sec;
95 	stamp.tv_nsec = di_ctime.t_nsec;
96 }
97 
98 
99 uint32
100 xfs_inode_t::NLink() const
101 {
102 	return di_nlink;
103 }
104 
105 
106 int8
107 xfs_inode_t::Version() const
108 {
109 	return di_version;
110 }
111 
112 
113 uint16
114 xfs_inode_t::Flags() const
115 {
116 	return di_flags;
117 }
118 
119 
120 int8
121 xfs_inode_t::Format() const
122 {
123 	return di_format;
124 }
125 
126 
127 Inode::Inode(Volume* volume, xfs_ino_t id)
128 	:
129 	fVolume(volume),
130 	fId(id)
131 {
132 
133 }
134 
135 
136 status_t
137 Inode::Init()
138 {
139 	fNode = new(std::nothrow) xfs_inode_t;
140 	if (fNode == NULL)
141 		return B_NO_MEMORY;
142 
143 	uint16 inodeSize = fVolume->InodeSize();
144 	fBuffer = new(std::nothrow) char[inodeSize];
145 	if (fBuffer == NULL)
146 		return B_NO_MEMORY;
147 
148 	status_t status = GetFromDisk();
149 	if (status == B_OK) {
150 		if (fNode->di_magic == INODE_MAGIC) {
151 			TRACE("Init(): Inode successfully read.\n");
152 			status = B_OK;
153 		} else {
154 			TRACE("Init(): Inode wasn't read successfully!\n");
155 			status = B_BAD_VALUE;
156 		}
157 	}
158 
159 	return status;
160 }
161 
162 
163 status_t
164 Inode::GetFromDisk()
165 {
166 	xfs_agnumber_t agNo = INO_TO_AGNO(fId, fVolume);
167 		// Get the AG number from the inode
168 	uint32 agRelativeInodeNo = INO_TO_AGINO(fId, fVolume->AgInodeBits());
169 		// AG relative ino #
170 	xfs_agblock_t agBlock = INO_TO_AGBLOCK(agRelativeInodeNo, fVolume);
171 		// AG relative block number
172 	xfs_off_t offset = INO_TO_BLOCKOFFSET(fId, fVolume);
173 		// Offset into the block1
174 	uint32 len = fVolume->InodeSize();
175 		// Inode len to read (size of inode)
176 
177 	TRACE("AgNumber: (%d), AgRelativeIno: (%d), AgRelativeBlockNum: (%d),"
178 		"Offset: (%d), len: (%d)\n", agNo,
179 		agRelativeInodeNo, agBlock, offset, len);
180 
181 	if (agNo > fVolume->AgCount()) {
182 		ERROR("Inode::GetFromDisk : AG Number more than number of AGs");
183 		return B_ENTRY_NOT_FOUND;
184 	}
185 
186 	xfs_agblock_t numberOfBlocksInAg = fVolume->AgBlocks();
187 
188 	xfs_fsblock_t blockToRead = FSBLOCKS_TO_BASICBLOCKS(fVolume->BlockLog(),
189 		((uint64)(agNo * numberOfBlocksInAg) + agBlock));
190 
191 	xfs_daddr_t readPos = blockToRead * (BASICBLOCKSIZE) + offset * len;
192 
193 	if (read_pos(fVolume->Device(), readPos, fBuffer, len) != len) {
194 		ERROR("Inode::Inode(): IO Error");
195 		return B_IO_ERROR;
196 	}
197 
198 	memcpy(fNode, fBuffer, INODE_CORE_UNLINKED_SIZE);
199 	fNode->SwapEndian();
200 
201 	return B_OK;
202 }
203 
204 
205 Inode::~Inode()
206 {
207 	delete fBuffer;
208 	delete fNode;
209 }
210 
211 
212 uint32
213 hashfunction(const char* name, int length)
214 {
215 	uint32 hashVal = 0;
216 
217 	int lengthCovered = 0;
218 	int index = 0;
219 	if (length >= 4) {
220 		for (; index <= length; index+=4)
221 		{
222 			lengthCovered = index;
223 			hashVal = (name[index] << 21) ^ (name[index+1] << 14)
224 				^ (name[index+2] << 7) ^ (name[index+3] << 0)
225 				^ ((hashVal << 28) | (hashVal >> (4)));
226 		}
227 	}
228 
229 	int leftToCover = length - lengthCovered;
230 	if (leftToCover == 3) {
231 		hashVal = (name[index] << 14) ^ (name[index+1] << 7)
232 			^ (name[index+2] << 0) ^ ((hashVal << 21) | (hashVal >> (11)));
233 	}
234 	if (leftToCover == 2) {
235 		hashVal = (name[index] << 7) ^ (name[index+1] << 0)
236 			^ ((hashVal << 14) | (hashVal >> (32 - 14)));
237 	}
238 	if (leftToCover == 1) {
239 		hashVal = (name[index] << 0)
240 			^ ((hashVal << 7) | (hashVal >> (32 - 7)));
241 	}
242 
243 	return hashVal;
244 }
245