]>
Commit | Line | Data |
---|---|---|
959ef981 | 1 | // SPDX-License-Identifier: GPL-2.0 |
2bd0ea18 | 2 | /* |
da23017d NS |
3 | * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. |
4 | * All Rights Reserved. | |
2bd0ea18 NS |
5 | */ |
6 | ||
6b803e5a | 7 | #include "libxfs.h" |
2bd0ea18 NS |
8 | #include "bit.h" |
9 | #include "type.h" | |
10 | #include "faddr.h" | |
11 | #include "fprint.h" | |
12 | #include "field.h" | |
2bd0ea18 | 13 | #include "dir2.h" |
4ca431fc | 14 | #include "init.h" |
fc068a19 | 15 | #include "output.h" |
2bd0ea18 NS |
16 | |
17 | static int dir2_block_hdr_count(void *obj, int startoff); | |
18 | static int dir2_block_leaf_count(void *obj, int startoff); | |
19 | static int dir2_block_leaf_offset(void *obj, int startoff, int idx); | |
20 | static int dir2_block_tail_count(void *obj, int startoff); | |
21 | static int dir2_block_tail_offset(void *obj, int startoff, int idx); | |
22 | static int dir2_block_u_count(void *obj, int startoff); | |
23 | static int dir2_block_u_offset(void *obj, int startoff, int idx); | |
24 | static int dir2_data_union_freetag_count(void *obj, int startoff); | |
25 | static int dir2_data_union_inumber_count(void *obj, int startoff); | |
26 | static int dir2_data_union_length_count(void *obj, int startoff); | |
27 | static int dir2_data_union_name_count(void *obj, int startoff); | |
28 | static int dir2_data_union_namelen_count(void *obj, int startoff); | |
29 | static int dir2_data_union_tag_count(void *obj, int startoff); | |
30 | static int dir2_data_union_tag_offset(void *obj, int startoff, int idx); | |
31 | static int dir2_data_hdr_count(void *obj, int startoff); | |
32 | static int dir2_data_u_count(void *obj, int startoff); | |
33 | static int dir2_data_u_offset(void *obj, int startoff, int idx); | |
34 | static int dir2_free_bests_count(void *obj, int startoff); | |
35 | static int dir2_free_hdr_count(void *obj, int startoff); | |
36 | static int dir2_leaf_bests_count(void *obj, int startoff); | |
37 | static int dir2_leaf_bests_offset(void *obj, int startoff, int idx); | |
38 | static int dir2_leaf_ents_count(void *obj, int startoff); | |
39 | static int dir2_leaf_hdr_count(void *obj, int startoff); | |
40 | static int dir2_leaf_tail_count(void *obj, int startoff); | |
41 | static int dir2_leaf_tail_offset(void *obj, int startoff, int idx); | |
42 | static int dir2_node_btree_count(void *obj, int startoff); | |
43 | static int dir2_node_hdr_count(void *obj, int startoff); | |
44 | ||
45 | const field_t dir2_hfld[] = { | |
46 | { "", FLDT_DIR2, OI(0), C1, 0, TYP_NONE }, | |
47 | { NULL } | |
48 | }; | |
49 | ||
eb0cb950 DC |
50 | #define BOFF(f) bitize(offsetof(struct xfs_dir2_data_hdr, f)) |
51 | #define DOFF(f) bitize(offsetof(struct xfs_dir2_data_hdr, f)) | |
52 | #define FOFF(f) bitize(offsetof(struct xfs_dir2_free, f)) | |
53 | #define LOFF(f) bitize(offsetof(struct xfs_dir2_leaf, f)) | |
54 | #define NOFF(f) bitize(offsetof(struct xfs_da_intnode, f)) | |
2bd0ea18 | 55 | const field_t dir2_flds[] = { |
eb0cb950 | 56 | { "bhdr", FLDT_DIR2_DATA_HDR, OI(BOFF(magic)), dir2_block_hdr_count, |
2bd0ea18 NS |
57 | FLD_COUNT, TYP_NONE }, |
58 | { "bu", FLDT_DIR2_DATA_UNION, dir2_block_u_offset, dir2_block_u_count, | |
59 | FLD_ARRAY|FLD_OFFSET|FLD_COUNT, TYP_NONE }, | |
60 | { "bleaf", FLDT_DIR2_LEAF_ENTRY, dir2_block_leaf_offset, | |
61 | dir2_block_leaf_count, FLD_ARRAY|FLD_OFFSET|FLD_COUNT, TYP_NONE }, | |
62 | { "btail", FLDT_DIR2_BLOCK_TAIL, dir2_block_tail_offset, | |
63 | dir2_block_tail_count, FLD_OFFSET|FLD_COUNT, TYP_NONE }, | |
eb0cb950 | 64 | { "dhdr", FLDT_DIR2_DATA_HDR, OI(DOFF(magic)), dir2_data_hdr_count, |
2bd0ea18 NS |
65 | FLD_COUNT, TYP_NONE }, |
66 | { "du", FLDT_DIR2_DATA_UNION, dir2_data_u_offset, dir2_data_u_count, | |
67 | FLD_ARRAY|FLD_OFFSET|FLD_COUNT, TYP_NONE }, | |
68 | { "lhdr", FLDT_DIR2_LEAF_HDR, OI(LOFF(hdr)), dir2_leaf_hdr_count, | |
69 | FLD_COUNT, TYP_NONE }, | |
70 | { "lbests", FLDT_DIR2_DATA_OFF, dir2_leaf_bests_offset, | |
71 | dir2_leaf_bests_count, FLD_ARRAY|FLD_OFFSET|FLD_COUNT, TYP_NONE }, | |
65b80c98 | 72 | { "lents", FLDT_DIR2_LEAF_ENTRY, OI(LOFF(__ents)), dir2_leaf_ents_count, |
2bd0ea18 NS |
73 | FLD_ARRAY|FLD_COUNT, TYP_NONE }, |
74 | { "ltail", FLDT_DIR2_LEAF_TAIL, dir2_leaf_tail_offset, | |
75 | dir2_leaf_tail_count, FLD_OFFSET|FLD_COUNT, TYP_NONE }, | |
9a048535 | 76 | { "nhdr", FLDT_DA_NODE_HDR, OI(NOFF(hdr)), dir2_node_hdr_count, |
2bd0ea18 | 77 | FLD_COUNT, TYP_NONE }, |
88b32f06 | 78 | { "nbtree", FLDT_DA_NODE_ENTRY, OI(NOFF(__btree)), dir2_node_btree_count, |
2bd0ea18 NS |
79 | FLD_ARRAY|FLD_COUNT, TYP_NONE }, |
80 | { "fhdr", FLDT_DIR2_FREE_HDR, OI(FOFF(hdr)), dir2_free_hdr_count, | |
81 | FLD_COUNT, TYP_NONE }, | |
82 | { "fbests", FLDT_DIR2_DATA_OFFNZ, OI(FOFF(bests)), | |
83 | dir2_free_bests_count, FLD_ARRAY|FLD_COUNT, TYP_NONE }, | |
84 | { NULL } | |
85 | }; | |
86 | ||
87 | #define BTOFF(f) bitize(offsetof(xfs_dir2_block_tail_t, f)) | |
88 | const field_t dir2_block_tail_flds[] = { | |
89 | { "count", FLDT_UINT32D, OI(BTOFF(count)), C1, 0, TYP_NONE }, | |
90 | { "stale", FLDT_UINT32D, OI(BTOFF(stale)), C1, 0, TYP_NONE }, | |
91 | { NULL } | |
92 | }; | |
93 | ||
94 | #define DFOFF(f) bitize(offsetof(xfs_dir2_data_free_t, f)) | |
95 | const field_t dir2_data_free_flds[] = { | |
96 | { "offset", FLDT_DIR2_DATA_OFF, OI(DFOFF(offset)), C1, 0, TYP_NONE }, | |
97 | { "length", FLDT_DIR2_DATA_OFF, OI(DFOFF(length)), C1, 0, TYP_NONE }, | |
98 | { NULL } | |
99 | }; | |
100 | ||
101 | #define DHOFF(f) bitize(offsetof(xfs_dir2_data_hdr_t, f)) | |
102 | const field_t dir2_data_hdr_flds[] = { | |
103 | { "magic", FLDT_UINT32X, OI(DHOFF(magic)), C1, 0, TYP_NONE }, | |
104 | { "bestfree", FLDT_DIR2_DATA_FREE, OI(DHOFF(bestfree)), | |
105 | CI(XFS_DIR2_DATA_FD_COUNT), FLD_ARRAY, TYP_NONE }, | |
106 | { NULL } | |
107 | }; | |
108 | ||
109 | #define DEOFF(f) bitize(offsetof(xfs_dir2_data_entry_t, f)) | |
110 | #define DUOFF(f) bitize(offsetof(xfs_dir2_data_unused_t, f)) | |
111 | const field_t dir2_data_union_flds[] = { | |
112 | { "freetag", FLDT_UINT16X, OI(DUOFF(freetag)), | |
113 | dir2_data_union_freetag_count, FLD_COUNT, TYP_NONE }, | |
114 | { "inumber", FLDT_INO, OI(DEOFF(inumber)), | |
115 | dir2_data_union_inumber_count, FLD_COUNT, TYP_INODE }, | |
116 | { "length", FLDT_DIR2_DATA_OFF, OI(DUOFF(length)), | |
117 | dir2_data_union_length_count, FLD_COUNT, TYP_NONE }, | |
118 | { "namelen", FLDT_UINT8D, OI(DEOFF(namelen)), | |
119 | dir2_data_union_namelen_count, FLD_COUNT, TYP_NONE }, | |
120 | { "name", FLDT_CHARNS, OI(DEOFF(name)), dir2_data_union_name_count, | |
121 | FLD_COUNT, TYP_NONE }, | |
122 | { "tag", FLDT_DIR2_DATA_OFF, dir2_data_union_tag_offset, | |
123 | dir2_data_union_tag_count, FLD_OFFSET|FLD_COUNT, TYP_NONE }, | |
124 | { NULL } | |
125 | }; | |
126 | ||
127 | #define LEOFF(f) bitize(offsetof(xfs_dir2_leaf_entry_t, f)) | |
128 | const field_t dir2_leaf_entry_flds[] = { | |
129 | { "hashval", FLDT_UINT32X, OI(LEOFF(hashval)), C1, 0, TYP_NONE }, | |
130 | { "address", FLDT_UINT32X, OI(LEOFF(address)), C1, 0, TYP_NONE }, | |
131 | { NULL } | |
132 | }; | |
133 | ||
134 | #define LHOFF(f) bitize(offsetof(xfs_dir2_leaf_hdr_t, f)) | |
135 | const field_t dir2_leaf_hdr_flds[] = { | |
9a048535 | 136 | { "info", FLDT_DA_BLKINFO, OI(LHOFF(info)), C1, 0, TYP_NONE }, |
2bd0ea18 NS |
137 | { "count", FLDT_UINT16D, OI(LHOFF(count)), C1, 0, TYP_NONE }, |
138 | { "stale", FLDT_UINT16D, OI(LHOFF(stale)), C1, 0, TYP_NONE }, | |
139 | { NULL } | |
140 | }; | |
141 | ||
142 | #define LTOFF(f) bitize(offsetof(xfs_dir2_leaf_tail_t, f)) | |
143 | const field_t dir2_leaf_tail_flds[] = { | |
144 | { "bestcount", FLDT_UINT32D, OI(LTOFF(bestcount)), C1, 0, TYP_NONE }, | |
145 | { NULL } | |
146 | }; | |
147 | ||
148 | #define FHOFF(f) bitize(offsetof(xfs_dir2_free_hdr_t, f)) | |
149 | const field_t dir2_free_hdr_flds[] = { | |
150 | { "magic", FLDT_UINT32X, OI(FHOFF(magic)), C1, 0, TYP_NONE }, | |
151 | { "firstdb", FLDT_INT32D, OI(FHOFF(firstdb)), C1, 0, TYP_NONE }, | |
152 | { "nvalid", FLDT_INT32D, OI(FHOFF(nvalid)), C1, 0, TYP_NONE }, | |
153 | { "nused", FLDT_INT32D, OI(FHOFF(nused)), C1, 0, TYP_NONE }, | |
154 | { NULL } | |
155 | }; | |
156 | ||
9a048535 DC |
157 | #define DBOFF(f) bitize(offsetof(xfs_da_blkinfo_t, f)) |
158 | const field_t da_blkinfo_flds[] = { | |
159 | { "forw", FLDT_DIRBLOCK, OI(DBOFF(forw)), C1, 0, TYP_INODATA }, | |
160 | { "back", FLDT_DIRBLOCK, OI(DBOFF(back)), C1, 0, TYP_INODATA }, | |
161 | { "magic", FLDT_UINT16X, OI(DBOFF(magic)), C1, 0, TYP_NONE }, | |
162 | { "pad", FLDT_UINT16X, OI(DBOFF(pad)), C1, FLD_SKIPALL, TYP_NONE }, | |
163 | { NULL } | |
164 | }; | |
165 | ||
166 | #define EOFF(f) bitize(offsetof(xfs_da_node_entry_t, f)) | |
167 | const field_t da_node_entry_flds[] = { | |
168 | { "hashval", FLDT_UINT32X, OI(EOFF(hashval)), C1, 0, TYP_NONE }, | |
169 | { "before", FLDT_DIRBLOCK, OI(EOFF(before)), C1, 0, TYP_INODATA }, | |
170 | { NULL } | |
171 | }; | |
172 | ||
173 | #define HOFF(f) bitize(offsetof(xfs_da_node_hdr_t, f)) | |
174 | const field_t da_node_hdr_flds[] = { | |
175 | { "info", FLDT_DA_BLKINFO, OI(HOFF(info)), C1, 0, TYP_NONE }, | |
a24374f4 | 176 | { "count", FLDT_UINT16D, OI(HOFF(__count)), C1, 0, TYP_NONE }, |
88b32f06 | 177 | { "level", FLDT_UINT16D, OI(HOFF(__level)), C1, 0, TYP_NONE }, |
9a048535 DC |
178 | { NULL } |
179 | }; | |
180 | ||
9d0deb45 DC |
181 | /* |
182 | * Worker functions shared between either dir2/dir3 or block/data formats | |
183 | */ | |
184 | static int | |
185 | __dir2_block_tail_offset( | |
186 | struct xfs_dir2_data_hdr *block, | |
187 | int startoff, | |
188 | int idx) | |
189 | { | |
190 | struct xfs_dir2_block_tail *btp; | |
191 | ||
192 | ASSERT(startoff == 0); | |
193 | ASSERT(idx == 0); | |
ff105f75 | 194 | btp = xfs_dir2_block_tail_p(mp->m_dir_geo, block); |
9d0deb45 DC |
195 | return bitize((int)((char *)btp - (char *)block)); |
196 | } | |
197 | ||
198 | static int | |
199 | __dir2_data_entries_count( | |
200 | char *ptr, | |
201 | char *endptr) | |
202 | { | |
203 | int i; | |
204 | ||
205 | for (i = 0; ptr < endptr; i++) { | |
206 | struct xfs_dir2_data_entry *dep; | |
207 | struct xfs_dir2_data_unused *dup; | |
208 | ||
209 | dup = (xfs_dir2_data_unused_t *)ptr; | |
210 | if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) | |
211 | ptr += be16_to_cpu(dup->length); | |
212 | else { | |
213 | dep = (xfs_dir2_data_entry_t *)ptr; | |
ff105f75 | 214 | ptr += M_DIROPS(mp)->data_entsize(dep->namelen); |
9d0deb45 DC |
215 | } |
216 | } | |
217 | return i; | |
218 | } | |
219 | ||
220 | static char * | |
221 | __dir2_data_entry_offset( | |
222 | char *ptr, | |
223 | char *endptr, | |
224 | int idx) | |
225 | { | |
226 | int i; | |
227 | ||
228 | for (i = 0; i < idx; i++) { | |
229 | struct xfs_dir2_data_entry *dep; | |
230 | struct xfs_dir2_data_unused *dup; | |
231 | ||
232 | ASSERT(ptr < endptr); | |
233 | dup = (xfs_dir2_data_unused_t *)ptr; | |
234 | if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) | |
235 | ptr += be16_to_cpu(dup->length); | |
236 | else { | |
237 | dep = (xfs_dir2_data_entry_t *)ptr; | |
ff105f75 | 238 | ptr += M_DIROPS(mp)->data_entsize(dep->namelen); |
9d0deb45 DC |
239 | } |
240 | } | |
241 | return ptr; | |
242 | } | |
243 | ||
244 | /* | |
245 | * Block format functions | |
246 | */ | |
2bd0ea18 NS |
247 | static int |
248 | dir2_block_hdr_count( | |
249 | void *obj, | |
250 | int startoff) | |
251 | { | |
a364668b | 252 | struct xfs_dir2_data_hdr *block = obj; |
2bd0ea18 NS |
253 | |
254 | ASSERT(startoff == 0); | |
eb0cb950 | 255 | return be32_to_cpu(block->magic) == XFS_DIR2_BLOCK_MAGIC; |
2bd0ea18 NS |
256 | } |
257 | ||
a364668b DC |
258 | static int |
259 | dir3_block_hdr_count( | |
260 | void *obj, | |
261 | int startoff) | |
262 | { | |
263 | struct xfs_dir2_data_hdr *block = obj; | |
264 | ||
265 | ASSERT(startoff == 0); | |
266 | return be32_to_cpu(block->magic) == XFS_DIR3_BLOCK_MAGIC; | |
267 | } | |
268 | ||
2bd0ea18 NS |
269 | static int |
270 | dir2_block_leaf_count( | |
271 | void *obj, | |
272 | int startoff) | |
273 | { | |
a364668b | 274 | struct xfs_dir2_data_hdr *block = obj; |
eb0cb950 | 275 | struct xfs_dir2_block_tail *btp; |
2bd0ea18 NS |
276 | |
277 | ASSERT(startoff == 0); | |
a364668b DC |
278 | if (be32_to_cpu(block->magic) != XFS_DIR2_BLOCK_MAGIC && |
279 | be32_to_cpu(block->magic) != XFS_DIR3_BLOCK_MAGIC) | |
2bd0ea18 | 280 | return 0; |
ff105f75 | 281 | btp = xfs_dir2_block_tail_p(mp->m_dir_geo, block); |
5e656dbb | 282 | return be32_to_cpu(btp->count); |
2bd0ea18 NS |
283 | } |
284 | ||
2bd0ea18 NS |
285 | static int |
286 | dir2_block_leaf_offset( | |
287 | void *obj, | |
288 | int startoff, | |
289 | int idx) | |
290 | { | |
a364668b | 291 | struct xfs_dir2_data_hdr *block = obj; |
eb0cb950 DC |
292 | struct xfs_dir2_block_tail *btp; |
293 | struct xfs_dir2_leaf_entry *lep; | |
2bd0ea18 NS |
294 | |
295 | ASSERT(startoff == 0); | |
a364668b DC |
296 | ASSERT(be32_to_cpu(block->magic) == XFS_DIR2_BLOCK_MAGIC || |
297 | be32_to_cpu(block->magic) == XFS_DIR3_BLOCK_MAGIC); | |
ff105f75 | 298 | btp = xfs_dir2_block_tail_p(mp->m_dir_geo, block); |
5e656dbb | 299 | lep = xfs_dir2_block_leaf_p(btp) + idx; |
2bd0ea18 NS |
300 | return bitize((int)((char *)lep - (char *)block)); |
301 | } | |
302 | ||
2bd0ea18 NS |
303 | static int |
304 | dir2_block_tail_count( | |
305 | void *obj, | |
306 | int startoff) | |
307 | { | |
a364668b | 308 | struct xfs_dir2_data_hdr *block = obj; |
2bd0ea18 NS |
309 | |
310 | ASSERT(startoff == 0); | |
eb0cb950 | 311 | return be32_to_cpu(block->magic) == XFS_DIR2_BLOCK_MAGIC; |
2bd0ea18 NS |
312 | } |
313 | ||
a364668b DC |
314 | static int |
315 | dir3_block_tail_count( | |
316 | void *obj, | |
317 | int startoff) | |
318 | { | |
319 | struct xfs_dir2_data_hdr *block = obj; | |
320 | ||
321 | ASSERT(startoff == 0); | |
322 | return be32_to_cpu(block->magic) == XFS_DIR3_BLOCK_MAGIC; | |
323 | } | |
324 | ||
2bd0ea18 NS |
325 | static int |
326 | dir2_block_tail_offset( | |
327 | void *obj, | |
328 | int startoff, | |
329 | int idx) | |
330 | { | |
9d0deb45 | 331 | struct xfs_dir2_data_hdr *block = obj; |
2bd0ea18 | 332 | |
a364668b DC |
333 | ASSERT(be32_to_cpu(block->magic) == XFS_DIR2_BLOCK_MAGIC || |
334 | be32_to_cpu(block->magic) == XFS_DIR3_BLOCK_MAGIC); | |
9d0deb45 | 335 | return __dir2_block_tail_offset(block, startoff, idx); |
2bd0ea18 NS |
336 | } |
337 | ||
2bd0ea18 NS |
338 | static int |
339 | dir2_block_u_count( | |
340 | void *obj, | |
341 | int startoff) | |
342 | { | |
9d0deb45 | 343 | struct xfs_dir2_data_hdr *block = obj; |
eb0cb950 | 344 | struct xfs_dir2_block_tail *btp; |
2bd0ea18 NS |
345 | |
346 | ASSERT(startoff == 0); | |
a364668b DC |
347 | if (be32_to_cpu(block->magic) != XFS_DIR2_BLOCK_MAGIC && |
348 | be32_to_cpu(block->magic) != XFS_DIR3_BLOCK_MAGIC) | |
2bd0ea18 | 349 | return 0; |
eb0cb950 | 350 | |
ff105f75 DC |
351 | btp = xfs_dir2_block_tail_p(mp->m_dir_geo, block); |
352 | return __dir2_data_entries_count( | |
353 | (char *)M_DIROPS(mp)->data_unused_p(block), | |
354 | (char *)xfs_dir2_block_leaf_p(btp)); | |
2bd0ea18 NS |
355 | } |
356 | ||
2bd0ea18 NS |
357 | static int |
358 | dir2_block_u_offset( | |
359 | void *obj, | |
360 | int startoff, | |
361 | int idx) | |
362 | { | |
9d0deb45 | 363 | struct xfs_dir2_data_hdr *block = obj; |
eb0cb950 | 364 | struct xfs_dir2_block_tail *btp; |
2bd0ea18 NS |
365 | char *ptr; |
366 | ||
367 | ASSERT(startoff == 0); | |
a364668b DC |
368 | ASSERT(be32_to_cpu(block->magic) == XFS_DIR2_BLOCK_MAGIC || |
369 | be32_to_cpu(block->magic) == XFS_DIR3_BLOCK_MAGIC); | |
ff105f75 DC |
370 | btp = xfs_dir2_block_tail_p(mp->m_dir_geo, block); |
371 | ptr = __dir2_data_entry_offset( | |
372 | (char *)M_DIROPS(mp)->data_unused_p(block), | |
373 | (char *)xfs_dir2_block_leaf_p(btp), idx); | |
2bd0ea18 NS |
374 | return bitize((int)(ptr - (char *)block)); |
375 | } | |
376 | ||
9d0deb45 DC |
377 | /* |
378 | * Data block format functions | |
379 | */ | |
2bd0ea18 NS |
380 | static int |
381 | dir2_data_union_freetag_count( | |
382 | void *obj, | |
383 | int startoff) | |
384 | { | |
385 | xfs_dir2_data_unused_t *dup; | |
386 | char *end; | |
387 | ||
388 | ASSERT(bitoffs(startoff) == 0); | |
389 | dup = (xfs_dir2_data_unused_t *)((char *)obj + byteize(startoff)); | |
390 | end = (char *)&dup->freetag + sizeof(dup->freetag); | |
ff105f75 | 391 | return end <= (char *)obj + mp->m_dir_geo->blksize && |
5e656dbb | 392 | be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG; |
2bd0ea18 NS |
393 | } |
394 | ||
395 | static int | |
396 | dir2_data_union_inumber_count( | |
397 | void *obj, | |
398 | int startoff) | |
399 | { | |
400 | xfs_dir2_data_entry_t *dep; | |
401 | xfs_dir2_data_unused_t *dup; | |
402 | char *end; | |
403 | ||
404 | ASSERT(bitoffs(startoff) == 0); | |
405 | dup = (xfs_dir2_data_unused_t *)((char *)obj + byteize(startoff)); | |
406 | dep = (xfs_dir2_data_entry_t *)dup; | |
407 | end = (char *)&dep->inumber + sizeof(dep->inumber); | |
ff105f75 | 408 | return end <= (char *)obj + mp->m_dir_geo->blksize && |
5e656dbb | 409 | be16_to_cpu(dup->freetag) != XFS_DIR2_DATA_FREE_TAG; |
2bd0ea18 NS |
410 | } |
411 | ||
412 | static int | |
413 | dir2_data_union_length_count( | |
414 | void *obj, | |
415 | int startoff) | |
416 | { | |
417 | xfs_dir2_data_unused_t *dup; | |
418 | char *end; | |
419 | ||
420 | ASSERT(bitoffs(startoff) == 0); | |
421 | dup = (xfs_dir2_data_unused_t *)((char *)obj + byteize(startoff)); | |
422 | end = (char *)&dup->length + sizeof(dup->length); | |
ff105f75 | 423 | return end <= (char *)obj + mp->m_dir_geo->blksize && |
5e656dbb | 424 | be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG; |
2bd0ea18 NS |
425 | } |
426 | ||
427 | static int | |
428 | dir2_data_union_name_count( | |
429 | void *obj, | |
430 | int startoff) | |
431 | { | |
432 | xfs_dir2_data_entry_t *dep; | |
433 | xfs_dir2_data_unused_t *dup; | |
434 | char *end; | |
435 | ||
436 | ASSERT(bitoffs(startoff) == 0); | |
437 | dup = (xfs_dir2_data_unused_t *)((char *)obj + byteize(startoff)); | |
438 | dep = (xfs_dir2_data_entry_t *)dup; | |
439 | end = (char *)&dep->namelen + sizeof(dep->namelen); | |
ff105f75 | 440 | if (end >= (char *)obj + mp->m_dir_geo->blksize || |
5e656dbb | 441 | be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) |
2bd0ea18 NS |
442 | return 0; |
443 | end = (char *)&dep->name[0] + dep->namelen; | |
ff105f75 | 444 | return end <= (char *)obj + mp->m_dir_geo->blksize ? dep->namelen : 0; |
2bd0ea18 NS |
445 | } |
446 | ||
447 | static int | |
448 | dir2_data_union_namelen_count( | |
449 | void *obj, | |
450 | int startoff) | |
451 | { | |
452 | xfs_dir2_data_entry_t *dep; | |
453 | xfs_dir2_data_unused_t *dup; | |
454 | char *end; | |
455 | ||
456 | ASSERT(bitoffs(startoff) == 0); | |
457 | dup = (xfs_dir2_data_unused_t *)((char *)obj + byteize(startoff)); | |
458 | dep = (xfs_dir2_data_entry_t *)dup; | |
459 | end = (char *)&dep->namelen + sizeof(dep->namelen); | |
ff105f75 | 460 | return end <= (char *)obj + mp->m_dir_geo->blksize && |
5e656dbb | 461 | be16_to_cpu(dup->freetag) != XFS_DIR2_DATA_FREE_TAG; |
2bd0ea18 NS |
462 | } |
463 | ||
464 | static int | |
465 | dir2_data_union_tag_count( | |
466 | void *obj, | |
467 | int startoff) | |
468 | { | |
469 | xfs_dir2_data_entry_t *dep; | |
470 | xfs_dir2_data_unused_t *dup; | |
471 | char *end; | |
5e656dbb | 472 | __be16 *tagp; |
2bd0ea18 NS |
473 | |
474 | ASSERT(bitoffs(startoff) == 0); | |
475 | dup = (xfs_dir2_data_unused_t *)((char *)obj + byteize(startoff)); | |
476 | dep = (xfs_dir2_data_entry_t *)dup; | |
477 | end = (char *)&dup->freetag + sizeof(dup->freetag); | |
ff105f75 | 478 | if (end > (char *)obj + mp->m_dir_geo->blksize) |
2bd0ea18 | 479 | return 0; |
5e656dbb | 480 | if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) { |
2bd0ea18 | 481 | end = (char *)&dup->length + sizeof(dup->length); |
ff105f75 | 482 | if (end > (char *)obj + mp->m_dir_geo->blksize) |
2bd0ea18 | 483 | return 0; |
5e656dbb | 484 | tagp = xfs_dir2_data_unused_tag_p(dup); |
2bd0ea18 NS |
485 | } else { |
486 | end = (char *)&dep->namelen + sizeof(dep->namelen); | |
ff105f75 | 487 | if (end > (char *)obj + mp->m_dir_geo->blksize) |
2bd0ea18 | 488 | return 0; |
ff105f75 | 489 | tagp = M_DIROPS(mp)->data_entry_tag_p(dep); |
2bd0ea18 NS |
490 | } |
491 | end = (char *)tagp + sizeof(*tagp); | |
ff105f75 | 492 | return end <= (char *)obj + mp->m_dir_geo->blksize; |
2bd0ea18 NS |
493 | } |
494 | ||
2bd0ea18 NS |
495 | static int |
496 | dir2_data_union_tag_offset( | |
497 | void *obj, | |
498 | int startoff, | |
499 | int idx) | |
500 | { | |
501 | xfs_dir2_data_entry_t *dep; | |
502 | xfs_dir2_data_unused_t *dup; | |
503 | ||
504 | ASSERT(bitoffs(startoff) == 0); | |
505 | ASSERT(idx == 0); | |
506 | dup = (xfs_dir2_data_unused_t *)((char *)obj + byteize(startoff)); | |
5e656dbb BN |
507 | if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) |
508 | return bitize((int)((char *)xfs_dir2_data_unused_tag_p(dup) - | |
2bd0ea18 NS |
509 | (char *)dup)); |
510 | dep = (xfs_dir2_data_entry_t *)dup; | |
ff105f75 | 511 | return bitize((int)((char *)M_DIROPS(mp)->data_entry_tag_p(dep) - |
2bd0ea18 NS |
512 | (char *)dep)); |
513 | } | |
514 | ||
2bd0ea18 NS |
515 | static int |
516 | dir2_data_hdr_count( | |
517 | void *obj, | |
518 | int startoff) | |
519 | { | |
a364668b | 520 | struct xfs_dir2_data_hdr *data = obj; |
2bd0ea18 NS |
521 | |
522 | ASSERT(startoff == 0); | |
eb0cb950 | 523 | return be32_to_cpu(data->magic) == XFS_DIR2_DATA_MAGIC; |
2bd0ea18 NS |
524 | } |
525 | ||
a364668b DC |
526 | static int |
527 | dir3_data_hdr_count( | |
528 | void *obj, | |
529 | int startoff) | |
530 | { | |
531 | struct xfs_dir2_data_hdr *data = obj; | |
532 | ||
533 | ASSERT(startoff == 0); | |
534 | return be32_to_cpu(data->magic) == XFS_DIR3_DATA_MAGIC; | |
535 | } | |
536 | ||
2bd0ea18 NS |
537 | static int |
538 | dir2_data_u_count( | |
539 | void *obj, | |
540 | int startoff) | |
541 | { | |
9d0deb45 | 542 | struct xfs_dir2_data_hdr *data = obj; |
2bd0ea18 NS |
543 | |
544 | ASSERT(startoff == 0); | |
a364668b DC |
545 | if (be32_to_cpu(data->magic) != XFS_DIR2_DATA_MAGIC && |
546 | be32_to_cpu(data->magic) != XFS_DIR3_DATA_MAGIC) | |
2bd0ea18 | 547 | return 0; |
eb0cb950 | 548 | |
ff105f75 DC |
549 | return __dir2_data_entries_count( |
550 | (char *)M_DIROPS(mp)->data_unused_p(data), | |
551 | (char *)data + mp->m_dir_geo->blksize); | |
2bd0ea18 NS |
552 | } |
553 | ||
2bd0ea18 NS |
554 | static int |
555 | dir2_data_u_offset( | |
556 | void *obj, | |
557 | int startoff, | |
558 | int idx) | |
559 | { | |
9d0deb45 | 560 | struct xfs_dir2_data_hdr *data = obj; |
2bd0ea18 NS |
561 | char *ptr; |
562 | ||
563 | ASSERT(startoff == 0); | |
a364668b DC |
564 | ASSERT(be32_to_cpu(data->magic) == XFS_DIR2_DATA_MAGIC || |
565 | be32_to_cpu(data->magic) == XFS_DIR3_DATA_MAGIC); | |
ff105f75 DC |
566 | ptr = __dir2_data_entry_offset( |
567 | (char *)M_DIROPS(mp)->data_unused_p(data), | |
568 | (char *)data + mp->m_dir_geo->blksize, idx); | |
2bd0ea18 NS |
569 | return bitize((int)(ptr - (char *)data)); |
570 | } | |
571 | ||
2bd0ea18 NS |
572 | int |
573 | dir2_data_union_size( | |
574 | void *obj, | |
575 | int startoff, | |
576 | int idx) | |
577 | { | |
578 | xfs_dir2_data_entry_t *dep; | |
579 | xfs_dir2_data_unused_t *dup; | |
580 | ||
581 | ASSERT(bitoffs(startoff) == 0); | |
582 | ASSERT(idx == 0); | |
583 | dup = (xfs_dir2_data_unused_t *)((char *)obj + byteize(startoff)); | |
5e656dbb BN |
584 | if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) |
585 | return bitize(be16_to_cpu(dup->length)); | |
2bd0ea18 NS |
586 | else { |
587 | dep = (xfs_dir2_data_entry_t *)dup; | |
ff105f75 | 588 | return bitize(M_DIROPS(mp)->data_entsize(dep->namelen)); |
2bd0ea18 NS |
589 | } |
590 | } | |
591 | ||
3beed08e DC |
592 | static int |
593 | dir3_data_union_ftype_offset( | |
594 | void *obj, | |
595 | int startoff, | |
596 | int idx) | |
597 | { | |
598 | xfs_dir2_data_entry_t *dep; | |
599 | xfs_dir2_data_unused_t *dup; | |
600 | ||
601 | ASSERT(bitoffs(startoff) == 0); | |
602 | ASSERT(idx == 0); | |
603 | dup = (xfs_dir2_data_unused_t *)((char *)obj + byteize(startoff)); | |
604 | if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) | |
605 | return bitize((int)((char *)xfs_dir2_data_unused_tag_p(dup) - | |
606 | (char *)dup)); | |
607 | dep = (xfs_dir2_data_entry_t *)dup; | |
608 | return bitize((int)((char *)&dep->name[dep->namelen] - (char *)dep)); | |
609 | } | |
610 | ||
a364668b DC |
611 | /* |
612 | * Free block functions | |
613 | */ | |
2bd0ea18 NS |
614 | static int |
615 | dir2_free_bests_count( | |
616 | void *obj, | |
617 | int startoff) | |
618 | { | |
a364668b | 619 | struct xfs_dir2_free *free = obj; |
2bd0ea18 NS |
620 | |
621 | ASSERT(startoff == 0); | |
5e656dbb | 622 | if (be32_to_cpu(free->hdr.magic) != XFS_DIR2_FREE_MAGIC) |
2bd0ea18 | 623 | return 0; |
5e656dbb | 624 | return be32_to_cpu(free->hdr.nvalid); |
2bd0ea18 NS |
625 | } |
626 | ||
a364668b DC |
627 | static int |
628 | dir3_free_bests_count( | |
629 | void *obj, | |
630 | int startoff) | |
631 | { | |
632 | struct xfs_dir3_free *free = obj; | |
633 | ||
634 | ASSERT(startoff == 0); | |
635 | if (be32_to_cpu(free->hdr.hdr.magic) != XFS_DIR3_FREE_MAGIC) | |
636 | return 0; | |
637 | return be32_to_cpu(free->hdr.nvalid); | |
638 | } | |
639 | ||
2bd0ea18 NS |
640 | static int |
641 | dir2_free_hdr_count( | |
642 | void *obj, | |
643 | int startoff) | |
644 | { | |
a364668b | 645 | struct xfs_dir2_free *free = obj; |
2bd0ea18 NS |
646 | |
647 | ASSERT(startoff == 0); | |
5e656dbb | 648 | return be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC; |
2bd0ea18 NS |
649 | } |
650 | ||
a364668b DC |
651 | static int |
652 | dir3_free_hdr_count( | |
653 | void *obj, | |
654 | int startoff) | |
655 | { | |
656 | struct xfs_dir3_free *free = obj; | |
657 | ||
658 | ASSERT(startoff == 0); | |
659 | return be32_to_cpu(free->hdr.hdr.magic) == XFS_DIR3_FREE_MAGIC; | |
660 | } | |
661 | ||
662 | /* | |
663 | * Leaf block functions | |
664 | */ | |
2bd0ea18 NS |
665 | static int |
666 | dir2_leaf_bests_count( | |
667 | void *obj, | |
668 | int startoff) | |
669 | { | |
a364668b | 670 | struct xfs_dir2_leaf *leaf = obj; |
eb0cb950 | 671 | struct xfs_dir2_leaf_tail *ltp; |
2bd0ea18 NS |
672 | |
673 | ASSERT(startoff == 0); | |
a364668b DC |
674 | if (be16_to_cpu(leaf->hdr.info.magic) != XFS_DIR2_LEAF1_MAGIC && |
675 | be16_to_cpu(leaf->hdr.info.magic) != XFS_DIR3_LEAF1_MAGIC) | |
2bd0ea18 | 676 | return 0; |
ff105f75 | 677 | ltp = xfs_dir2_leaf_tail_p(mp->m_dir_geo, leaf); |
5e656dbb | 678 | return be32_to_cpu(ltp->bestcount); |
2bd0ea18 NS |
679 | } |
680 | ||
2bd0ea18 NS |
681 | static int |
682 | dir2_leaf_bests_offset( | |
683 | void *obj, | |
684 | int startoff, | |
685 | int idx) | |
686 | { | |
a364668b | 687 | struct xfs_dir2_leaf *leaf = obj; |
eb0cb950 | 688 | struct xfs_dir2_leaf_tail *ltp; |
5e656dbb | 689 | __be16 *lbp; |
2bd0ea18 NS |
690 | |
691 | ASSERT(startoff == 0); | |
a364668b DC |
692 | ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAF1_MAGIC || |
693 | be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR3_LEAF1_MAGIC); | |
ff105f75 | 694 | ltp = xfs_dir2_leaf_tail_p(mp->m_dir_geo, leaf); |
5e656dbb | 695 | lbp = xfs_dir2_leaf_bests_p(ltp) + idx; |
2bd0ea18 NS |
696 | return bitize((int)((char *)lbp - (char *)leaf)); |
697 | } | |
698 | ||
2bd0ea18 NS |
699 | static int |
700 | dir2_leaf_ents_count( | |
701 | void *obj, | |
702 | int startoff) | |
703 | { | |
a364668b | 704 | struct xfs_dir2_leaf *leaf = obj; |
2bd0ea18 NS |
705 | |
706 | ASSERT(startoff == 0); | |
5e656dbb BN |
707 | if (be16_to_cpu(leaf->hdr.info.magic) != XFS_DIR2_LEAF1_MAGIC && |
708 | be16_to_cpu(leaf->hdr.info.magic) != XFS_DIR2_LEAFN_MAGIC) | |
2bd0ea18 | 709 | return 0; |
5e656dbb | 710 | return be16_to_cpu(leaf->hdr.count); |
2bd0ea18 NS |
711 | } |
712 | ||
a364668b DC |
713 | static int |
714 | dir3_leaf_ents_count( | |
715 | void *obj, | |
716 | int startoff) | |
717 | { | |
718 | struct xfs_dir3_leaf *leaf = obj; | |
719 | ||
720 | ASSERT(startoff == 0); | |
721 | if (be16_to_cpu(leaf->hdr.info.hdr.magic) != XFS_DIR3_LEAF1_MAGIC && | |
722 | be16_to_cpu(leaf->hdr.info.hdr.magic) != XFS_DIR3_LEAFN_MAGIC) | |
723 | return 0; | |
724 | return be16_to_cpu(leaf->hdr.count); | |
725 | } | |
726 | ||
2bd0ea18 NS |
727 | static int |
728 | dir2_leaf_hdr_count( | |
729 | void *obj, | |
730 | int startoff) | |
731 | { | |
a364668b | 732 | struct xfs_dir2_leaf *leaf = obj; |
dfc130f3 | 733 | |
2bd0ea18 | 734 | ASSERT(startoff == 0); |
5e656dbb BN |
735 | return be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAF1_MAGIC || |
736 | be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC; | |
2bd0ea18 NS |
737 | } |
738 | ||
a364668b DC |
739 | static int |
740 | dir3_leaf_hdr_count( | |
741 | void *obj, | |
742 | int startoff) | |
743 | { | |
744 | struct xfs_dir3_leaf *leaf = obj; | |
745 | ||
746 | ASSERT(startoff == 0); | |
747 | return be16_to_cpu(leaf->hdr.info.hdr.magic) == XFS_DIR3_LEAF1_MAGIC || | |
748 | be16_to_cpu(leaf->hdr.info.hdr.magic) == XFS_DIR3_LEAFN_MAGIC; | |
749 | } | |
750 | ||
2bd0ea18 NS |
751 | static int |
752 | dir2_leaf_tail_count( | |
753 | void *obj, | |
754 | int startoff) | |
755 | { | |
a364668b | 756 | struct xfs_dir2_leaf *leaf = obj; |
2bd0ea18 NS |
757 | |
758 | ASSERT(startoff == 0); | |
5e656dbb | 759 | return be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAF1_MAGIC; |
2bd0ea18 NS |
760 | } |
761 | ||
a364668b DC |
762 | static int |
763 | dir3_leaf_tail_count( | |
764 | void *obj, | |
765 | int startoff) | |
766 | { | |
767 | struct xfs_dir3_leaf *leaf = obj; | |
768 | ||
769 | ASSERT(startoff == 0); | |
770 | return be16_to_cpu(leaf->hdr.info.hdr.magic) == XFS_DIR3_LEAF1_MAGIC; | |
771 | } | |
772 | ||
2bd0ea18 NS |
773 | static int |
774 | dir2_leaf_tail_offset( | |
775 | void *obj, | |
776 | int startoff, | |
777 | int idx) | |
778 | { | |
a364668b | 779 | struct xfs_dir2_leaf *leaf = obj; |
eb0cb950 | 780 | struct xfs_dir2_leaf_tail *ltp; |
2bd0ea18 NS |
781 | |
782 | ASSERT(startoff == 0); | |
783 | ASSERT(idx == 0); | |
a364668b DC |
784 | ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAF1_MAGIC || |
785 | be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR3_LEAF1_MAGIC); | |
ff105f75 | 786 | ltp = xfs_dir2_leaf_tail_p(mp->m_dir_geo, leaf); |
2bd0ea18 NS |
787 | return bitize((int)((char *)ltp - (char *)leaf)); |
788 | } | |
789 | ||
a364668b DC |
790 | /* |
791 | * Node format functions | |
792 | */ | |
2bd0ea18 NS |
793 | static int |
794 | dir2_node_btree_count( | |
795 | void *obj, | |
796 | int startoff) | |
797 | { | |
a364668b | 798 | xfs_da_intnode_t *node = obj; |
2bd0ea18 NS |
799 | |
800 | ASSERT(startoff == 0); | |
5e656dbb | 801 | if (be16_to_cpu(node->hdr.info.magic) != XFS_DA_NODE_MAGIC) |
2bd0ea18 | 802 | return 0; |
a24374f4 | 803 | return be16_to_cpu(node->hdr.__count); |
2bd0ea18 NS |
804 | } |
805 | ||
a364668b DC |
806 | static int |
807 | dir3_node_btree_count( | |
808 | void *obj, | |
809 | int startoff) | |
810 | { | |
811 | struct xfs_da3_intnode *node = obj; | |
812 | ||
813 | ASSERT(startoff == 0); | |
814 | if (be16_to_cpu(node->hdr.info.hdr.magic) != XFS_DA3_NODE_MAGIC) | |
815 | return 0; | |
816 | return be16_to_cpu(node->hdr.__count); | |
817 | } | |
818 | ||
2bd0ea18 NS |
819 | static int |
820 | dir2_node_hdr_count( | |
821 | void *obj, | |
822 | int startoff) | |
823 | { | |
a364668b | 824 | struct xfs_da_intnode *node = obj; |
2bd0ea18 NS |
825 | |
826 | ASSERT(startoff == 0); | |
5e656dbb | 827 | return be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC; |
2bd0ea18 NS |
828 | } |
829 | ||
a364668b DC |
830 | static int |
831 | dir3_node_hdr_count( | |
832 | void *obj, | |
833 | int startoff) | |
834 | { | |
835 | struct xfs_da3_intnode *node = obj; | |
836 | ||
837 | ASSERT(startoff == 0); | |
838 | return be16_to_cpu(node->hdr.info.hdr.magic) == XFS_DA3_NODE_MAGIC; | |
839 | } | |
840 | ||
2bd0ea18 NS |
841 | int |
842 | dir2_size( | |
843 | void *obj, | |
844 | int startoff, | |
845 | int idx) | |
846 | { | |
ff105f75 | 847 | return bitize(mp->m_dir_geo->blksize); |
2bd0ea18 | 848 | } |
a364668b DC |
849 | |
850 | /* | |
851 | * CRC enabled structure definitions | |
852 | */ | |
853 | const field_t dir3_hfld[] = { | |
854 | { "", FLDT_DIR3, OI(0), C1, 0, TYP_NONE }, | |
855 | { NULL } | |
856 | }; | |
857 | ||
858 | #define B3OFF(f) bitize(offsetof(struct xfs_dir3_data_hdr, f)) | |
859 | #define D3OFF(f) bitize(offsetof(struct xfs_dir3_data_hdr, f)) | |
860 | #define F3OFF(f) bitize(offsetof(struct xfs_dir3_free, f)) | |
861 | #define L3OFF(f) bitize(offsetof(struct xfs_dir3_leaf, f)) | |
862 | #define N3OFF(f) bitize(offsetof(struct xfs_da3_intnode, f)) | |
863 | const field_t dir3_flds[] = { | |
864 | { "bhdr", FLDT_DIR3_DATA_HDR, OI(B3OFF(hdr)), dir3_block_hdr_count, | |
865 | FLD_COUNT, TYP_NONE }, | |
3beed08e | 866 | { "bu", FLDT_DIR3_DATA_UNION, dir2_block_u_offset, dir2_block_u_count, |
a364668b DC |
867 | FLD_ARRAY|FLD_OFFSET|FLD_COUNT, TYP_NONE }, |
868 | { "bleaf", FLDT_DIR2_LEAF_ENTRY, dir2_block_leaf_offset, | |
869 | dir2_block_leaf_count, FLD_ARRAY|FLD_OFFSET|FLD_COUNT, TYP_NONE }, | |
870 | { "btail", FLDT_DIR2_BLOCK_TAIL, dir2_block_tail_offset, | |
871 | dir3_block_tail_count, FLD_OFFSET|FLD_COUNT, TYP_NONE }, | |
872 | { "dhdr", FLDT_DIR3_DATA_HDR, OI(D3OFF(hdr)), dir3_data_hdr_count, | |
873 | FLD_COUNT, TYP_NONE }, | |
3beed08e | 874 | { "du", FLDT_DIR3_DATA_UNION, dir2_data_u_offset, dir2_data_u_count, |
a364668b DC |
875 | FLD_ARRAY|FLD_OFFSET|FLD_COUNT, TYP_NONE }, |
876 | { "lhdr", FLDT_DIR3_LEAF_HDR, OI(L3OFF(hdr)), dir3_leaf_hdr_count, | |
877 | FLD_COUNT, TYP_NONE }, | |
878 | { "lbests", FLDT_DIR2_DATA_OFF, dir2_leaf_bests_offset, | |
879 | dir2_leaf_bests_count, FLD_ARRAY|FLD_OFFSET|FLD_COUNT, TYP_NONE }, | |
880 | { "lents", FLDT_DIR2_LEAF_ENTRY, OI(L3OFF(__ents)), dir3_leaf_ents_count, | |
881 | FLD_ARRAY|FLD_COUNT, TYP_NONE }, | |
882 | { "ltail", FLDT_DIR2_LEAF_TAIL, dir2_leaf_tail_offset, | |
883 | dir3_leaf_tail_count, FLD_OFFSET|FLD_COUNT, TYP_NONE }, | |
884 | { "nhdr", FLDT_DA3_NODE_HDR, OI(N3OFF(hdr)), dir3_node_hdr_count, | |
885 | FLD_COUNT, TYP_NONE }, | |
886 | { "nbtree", FLDT_DA_NODE_ENTRY, OI(N3OFF(__btree)), dir3_node_btree_count, | |
887 | FLD_ARRAY|FLD_COUNT, TYP_NONE }, | |
888 | { "fhdr", FLDT_DIR3_FREE_HDR, OI(F3OFF(hdr)), dir3_free_hdr_count, | |
889 | FLD_COUNT, TYP_NONE }, | |
890 | { "fbests", FLDT_DIR2_DATA_OFFNZ, OI(F3OFF(bests)), | |
891 | dir3_free_bests_count, FLD_ARRAY|FLD_COUNT, TYP_NONE }, | |
892 | { NULL } | |
893 | }; | |
894 | ||
3beed08e DC |
895 | #define D3EOFF(f) bitize(offsetof(xfs_dir2_data_entry_t, f)) |
896 | #define D3UOFF(f) bitize(offsetof(xfs_dir2_data_unused_t, f)) | |
897 | const field_t dir3_data_union_flds[] = { | |
898 | { "freetag", FLDT_UINT16X, OI(D3UOFF(freetag)), | |
899 | dir2_data_union_freetag_count, FLD_COUNT, TYP_NONE }, | |
900 | { "inumber", FLDT_INO, OI(D3EOFF(inumber)), | |
901 | dir2_data_union_inumber_count, FLD_COUNT, TYP_INODE }, | |
902 | { "length", FLDT_DIR2_DATA_OFF, OI(D3UOFF(length)), | |
903 | dir2_data_union_length_count, FLD_COUNT, TYP_NONE }, | |
904 | { "namelen", FLDT_UINT8D, OI(D3EOFF(namelen)), | |
905 | dir2_data_union_namelen_count, FLD_COUNT, TYP_NONE }, | |
906 | { "name", FLDT_CHARNS, OI(D3EOFF(name)), dir2_data_union_name_count, | |
907 | FLD_COUNT, TYP_NONE }, | |
908 | { "filetype", FLDT_UINT8D, dir3_data_union_ftype_offset, C1, | |
909 | FLD_OFFSET, TYP_NONE }, | |
910 | { "tag", FLDT_DIR2_DATA_OFF, dir2_data_union_tag_offset, | |
911 | dir2_data_union_tag_count, FLD_OFFSET|FLD_COUNT, TYP_NONE }, | |
912 | { NULL } | |
913 | }; | |
914 | ||
a364668b DC |
915 | #define DBH3OFF(f) bitize(offsetof(struct xfs_dir3_blk_hdr, f)) |
916 | const field_t dir3_blkhdr_flds[] = { | |
917 | { "magic", FLDT_UINT32X, OI(DBH3OFF(magic)), C1, 0, TYP_NONE }, | |
0522f1cc | 918 | { "crc", FLDT_CRC, OI(DBH3OFF(crc)), C1, 0, TYP_NONE }, |
a364668b DC |
919 | { "bno", FLDT_DFSBNO, OI(DBH3OFF(blkno)), C1, 0, TYP_BMAPBTD }, |
920 | { "lsn", FLDT_UINT64X, OI(DBH3OFF(lsn)), C1, 0, TYP_NONE }, | |
921 | { "uuid", FLDT_UUID, OI(DBH3OFF(uuid)), C1, 0, TYP_NONE }, | |
922 | { "owner", FLDT_INO, OI(DBH3OFF(owner)), C1, 0, TYP_NONE }, | |
923 | { NULL } | |
924 | }; | |
925 | ||
926 | #define DH3OFF(f) bitize(offsetof(struct xfs_dir3_data_hdr, f)) | |
927 | const field_t dir3_data_hdr_flds[] = { | |
928 | { "hdr", FLDT_DIR3_BLKHDR, OI(DH3OFF(hdr)), C1, 0, TYP_NONE }, | |
929 | { "bestfree", FLDT_DIR2_DATA_FREE, OI(DH3OFF(best_free)), | |
930 | CI(XFS_DIR2_DATA_FD_COUNT), FLD_ARRAY, TYP_NONE }, | |
70c1cceb | 931 | { "pad", FLDT_UINT32X, OI(DH3OFF(pad)), C1, FLD_SKIPALL, TYP_NONE }, |
a364668b DC |
932 | { NULL } |
933 | }; | |
934 | ||
935 | #define LH3OFF(f) bitize(offsetof(struct xfs_dir3_leaf_hdr, f)) | |
936 | const field_t dir3_leaf_hdr_flds[] = { | |
937 | { "info", FLDT_DA3_BLKINFO, OI(LH3OFF(info)), C1, 0, TYP_NONE }, | |
938 | { "count", FLDT_UINT16D, OI(LH3OFF(count)), C1, 0, TYP_NONE }, | |
939 | { "stale", FLDT_UINT16D, OI(LH3OFF(stale)), C1, 0, TYP_NONE }, | |
70c1cceb | 940 | { "pad", FLDT_UINT32X, OI(LH3OFF(pad)), C1, FLD_SKIPALL, TYP_NONE }, |
a364668b DC |
941 | { NULL } |
942 | }; | |
943 | ||
944 | #define FH3OFF(f) bitize(offsetof(struct xfs_dir3_free_hdr, f)) | |
945 | const field_t dir3_free_hdr_flds[] = { | |
946 | { "hdr", FLDT_DIR3_BLKHDR, OI(FH3OFF(hdr)), C1, 0, TYP_NONE }, | |
947 | { "firstdb", FLDT_INT32D, OI(FH3OFF(firstdb)), C1, 0, TYP_NONE }, | |
948 | { "nvalid", FLDT_INT32D, OI(FH3OFF(nvalid)), C1, 0, TYP_NONE }, | |
949 | { "nused", FLDT_INT32D, OI(FH3OFF(nused)), C1, 0, TYP_NONE }, | |
70c1cceb | 950 | { "pad", FLDT_UINT32X, OI(FH3OFF(pad)), C1, FLD_SKIPALL, TYP_NONE }, |
a364668b DC |
951 | { NULL } |
952 | }; | |
953 | ||
954 | ||
955 | #define DB3OFF(f) bitize(offsetof(struct xfs_da3_blkinfo, f)) | |
956 | const field_t da3_blkinfo_flds[] = { | |
957 | { "hdr", FLDT_DA_BLKINFO, OI(DB3OFF(hdr)), C1, 0, TYP_NONE }, | |
0522f1cc | 958 | { "crc", FLDT_CRC, OI(DB3OFF(crc)), C1, 0, TYP_NONE }, |
a364668b DC |
959 | { "bno", FLDT_DFSBNO, OI(DB3OFF(blkno)), C1, 0, TYP_BMAPBTD }, |
960 | { "lsn", FLDT_UINT64X, OI(DB3OFF(lsn)), C1, 0, TYP_NONE }, | |
961 | { "uuid", FLDT_UUID, OI(DB3OFF(uuid)), C1, 0, TYP_NONE }, | |
962 | { "owner", FLDT_INO, OI(DB3OFF(owner)), C1, 0, TYP_NONE }, | |
963 | { NULL } | |
964 | }; | |
965 | ||
966 | #define H3OFF(f) bitize(offsetof(struct xfs_da3_node_hdr, f)) | |
967 | const field_t da3_node_hdr_flds[] = { | |
968 | { "info", FLDT_DA3_BLKINFO, OI(H3OFF(info)), C1, 0, TYP_NONE }, | |
969 | { "count", FLDT_UINT16D, OI(H3OFF(__count)), C1, 0, TYP_NONE }, | |
970 | { "level", FLDT_UINT16D, OI(H3OFF(__level)), C1, 0, TYP_NONE }, | |
31df6ad1 | 971 | { "pad", FLDT_UINT32X, OI(H3OFF(__pad32)), C1, FLD_SKIPALL, TYP_NONE }, |
a364668b DC |
972 | { NULL } |
973 | }; | |
fc068a19 | 974 | |
89baf918 DW |
975 | /* Set the CRC. */ |
976 | void | |
977 | xfs_dir3_set_crc( | |
978 | struct xfs_buf *bp) | |
979 | { | |
980 | __be32 magic32; | |
981 | __be16 magic16; | |
982 | ||
983 | magic32 = *(__be32 *)bp->b_addr; | |
984 | magic16 = ((struct xfs_da_blkinfo *)bp->b_addr)->magic; | |
985 | ||
986 | switch (magic32) { | |
987 | case cpu_to_be32(XFS_DIR3_BLOCK_MAGIC): | |
988 | case cpu_to_be32(XFS_DIR3_DATA_MAGIC): | |
989 | xfs_buf_update_cksum(bp, XFS_DIR3_DATA_CRC_OFF); | |
990 | return; | |
991 | case cpu_to_be32(XFS_DIR3_FREE_MAGIC): | |
992 | xfs_buf_update_cksum(bp, XFS_DIR3_FREE_CRC_OFF); | |
993 | return; | |
994 | default: | |
995 | break; | |
996 | } | |
997 | ||
998 | switch (magic16) { | |
999 | case cpu_to_be16(XFS_DIR3_LEAF1_MAGIC): | |
1000 | case cpu_to_be16(XFS_DIR3_LEAFN_MAGIC): | |
1001 | xfs_buf_update_cksum(bp, XFS_DIR3_LEAF_CRC_OFF); | |
1002 | return; | |
1003 | case cpu_to_be16(XFS_DA3_NODE_MAGIC): | |
1004 | xfs_buf_update_cksum(bp, XFS_DA3_NODE_CRC_OFF); | |
1005 | return; | |
1006 | default: | |
1007 | dbprintf(_("Unknown directory buffer type! %x %x\n"), magic32, magic16); | |
1008 | break; | |
1009 | } | |
1010 | } | |
1011 | ||
fc068a19 DC |
1012 | /* |
1013 | * Special read verifier for directory buffers. Detect the magic number | |
1014 | * appropriately and set the correct verifier and call it. | |
1015 | */ | |
1016 | static void | |
1017 | xfs_dir3_db_read_verify( | |
1018 | struct xfs_buf *bp) | |
1019 | { | |
1020 | __be32 magic32; | |
1021 | __be16 magic16; | |
1022 | ||
1023 | magic32 = *(__be32 *)bp->b_addr; | |
1024 | magic16 = ((struct xfs_da_blkinfo *)bp->b_addr)->magic; | |
1025 | ||
1026 | switch (magic32) { | |
1027 | case cpu_to_be32(XFS_DIR3_BLOCK_MAGIC): | |
1028 | bp->b_ops = &xfs_dir3_block_buf_ops; | |
1029 | goto verify; | |
1030 | case cpu_to_be32(XFS_DIR3_DATA_MAGIC): | |
1031 | bp->b_ops = &xfs_dir3_data_buf_ops; | |
1032 | goto verify; | |
1033 | case cpu_to_be32(XFS_DIR3_FREE_MAGIC): | |
1034 | bp->b_ops = &xfs_dir3_free_buf_ops; | |
1035 | goto verify; | |
1036 | default: | |
1037 | break; | |
1038 | } | |
1039 | ||
1040 | switch (magic16) { | |
1041 | case cpu_to_be16(XFS_DIR3_LEAF1_MAGIC): | |
1042 | bp->b_ops = &xfs_dir3_leaf1_buf_ops; | |
1043 | break; | |
1044 | case cpu_to_be16(XFS_DIR3_LEAFN_MAGIC): | |
1045 | bp->b_ops = &xfs_dir3_leafn_buf_ops; | |
1046 | break; | |
1047 | case cpu_to_be16(XFS_DA3_NODE_MAGIC): | |
1048 | bp->b_ops = &xfs_da3_node_buf_ops; | |
1049 | break; | |
1050 | default: | |
1051 | dbprintf(_("Unknown directory buffer type!\n")); | |
66fc04e0 | 1052 | xfs_buf_ioerror(bp, -EFSCORRUPTED); |
fc068a19 DC |
1053 | return; |
1054 | } | |
1055 | verify: | |
1056 | bp->b_ops->verify_read(bp); | |
1057 | } | |
1058 | ||
1059 | static void | |
1060 | xfs_dir3_db_write_verify( | |
1061 | struct xfs_buf *bp) | |
1062 | { | |
1063 | dbprintf(_("Writing unknown directory buffer type!\n")); | |
66fc04e0 | 1064 | xfs_buf_ioerror(bp, -EFSCORRUPTED); |
fc068a19 DC |
1065 | } |
1066 | ||
1067 | const struct xfs_buf_ops xfs_dir3_db_buf_ops = { | |
a3fac935 | 1068 | .name = "xfs_dir3", |
fc068a19 DC |
1069 | .verify_read = xfs_dir3_db_read_verify, |
1070 | .verify_write = xfs_dir3_db_write_verify, | |
1071 | }; |