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