]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - db/dir2.c
xfsprogs: Release v4.18.0
[thirdparty/xfsprogs-dev.git] / db / dir2.c
CommitLineData
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
17static int dir2_block_hdr_count(void *obj, int startoff);
18static int dir2_block_leaf_count(void *obj, int startoff);
19static int dir2_block_leaf_offset(void *obj, int startoff, int idx);
20static int dir2_block_tail_count(void *obj, int startoff);
21static int dir2_block_tail_offset(void *obj, int startoff, int idx);
22static int dir2_block_u_count(void *obj, int startoff);
23static int dir2_block_u_offset(void *obj, int startoff, int idx);
24static int dir2_data_union_freetag_count(void *obj, int startoff);
25static int dir2_data_union_inumber_count(void *obj, int startoff);
26static int dir2_data_union_length_count(void *obj, int startoff);
27static int dir2_data_union_name_count(void *obj, int startoff);
28static int dir2_data_union_namelen_count(void *obj, int startoff);
29static int dir2_data_union_tag_count(void *obj, int startoff);
30static int dir2_data_union_tag_offset(void *obj, int startoff, int idx);
31static int dir2_data_hdr_count(void *obj, int startoff);
32static int dir2_data_u_count(void *obj, int startoff);
33static int dir2_data_u_offset(void *obj, int startoff, int idx);
34static int dir2_free_bests_count(void *obj, int startoff);
35static int dir2_free_hdr_count(void *obj, int startoff);
36static int dir2_leaf_bests_count(void *obj, int startoff);
37static int dir2_leaf_bests_offset(void *obj, int startoff, int idx);
38static int dir2_leaf_ents_count(void *obj, int startoff);
39static int dir2_leaf_hdr_count(void *obj, int startoff);
40static int dir2_leaf_tail_count(void *obj, int startoff);
41static int dir2_leaf_tail_offset(void *obj, int startoff, int idx);
42static int dir2_node_btree_count(void *obj, int startoff);
43static int dir2_node_hdr_count(void *obj, int startoff);
44
45const 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 55const 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))
88const 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))
95const 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))
102const 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))
111const 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))
128const 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))
135const 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))
143const 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))
149const 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))
158const 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))
167const 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))
174const 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 */
184static 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
198static 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
220static 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
247static int
248dir2_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
258static int
259dir3_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
269static int
270dir2_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
285static int
286dir2_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
303static int
304dir2_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
314static int
315dir3_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
325static int
326dir2_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
338static int
339dir2_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
357static int
358dir2_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
380static int
381dir2_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
395static int
396dir2_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
412static int
413dir2_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
427static int
428dir2_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
447static int
448dir2_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
464static int
465dir2_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
495static int
496dir2_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
515static int
516dir2_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
526static int
527dir3_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
537static int
538dir2_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
554static int
555dir2_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
572int
573dir2_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
592static int
593dir3_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
614static int
615dir2_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
627static int
628dir3_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
640static int
641dir2_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
651static int
652dir3_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
665static int
666dir2_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
681static int
682dir2_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
699static int
700dir2_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
713static int
714dir3_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
727static int
728dir2_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
739static int
740dir3_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
751static int
752dir2_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
762static int
763dir3_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
773static int
774dir2_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
793static int
794dir2_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
806static int
807dir3_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
819static int
820dir2_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
830static int
831dir3_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
841int
842dir2_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 */
853const 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))
863const 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))
897const 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))
916const 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))
927const 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))
936const 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))
945const 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))
956const 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))
967const 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. */
976void
977xfs_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 */
1016static void
1017xfs_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 }
1055verify:
1056 bp->b_ops->verify_read(bp);
1057}
1058
1059static void
1060xfs_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
1067const 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};