1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
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
);
45 const field_t dir2_hfld
[] = {
46 { "", FLDT_DIR2
, OI(0), C1
, 0, TYP_NONE
},
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))
55 const field_t dir2_flds
[] = {
56 { "bhdr", FLDT_DIR2_DATA_HDR
, OI(BOFF(magic
)), dir2_block_hdr_count
,
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
},
64 { "dhdr", FLDT_DIR2_DATA_HDR
, OI(DOFF(magic
)), dir2_data_hdr_count
,
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
},
72 { "lents", FLDT_DIR2_LEAF_ENTRY
, OI(LOFF(__ents
)), dir2_leaf_ents_count
,
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
},
76 { "nhdr", FLDT_DA_NODE_HDR
, OI(NOFF(hdr
)), dir2_node_hdr_count
,
77 FLD_COUNT
, TYP_NONE
},
78 { "nbtree", FLDT_DA_NODE_ENTRY
, OI(NOFF(__btree
)), dir2_node_btree_count
,
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
},
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
},
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
},
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
},
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
},
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
},
134 #define LHOFF(f) bitize(offsetof(xfs_dir2_leaf_hdr_t, f))
135 const field_t dir2_leaf_hdr_flds
[] = {
136 { "info", FLDT_DA_BLKINFO
, OI(LHOFF(info
)), C1
, 0, TYP_NONE
},
137 { "count", FLDT_UINT16D
, OI(LHOFF(count
)), C1
, 0, TYP_NONE
},
138 { "stale", FLDT_UINT16D
, OI(LHOFF(stale
)), C1
, 0, TYP_NONE
},
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
},
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
},
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
},
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
},
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
},
176 { "count", FLDT_UINT16D
, OI(HOFF(__count
)), C1
, 0, TYP_NONE
},
177 { "level", FLDT_UINT16D
, OI(HOFF(__level
)), C1
, 0, TYP_NONE
},
182 * Worker functions shared between either dir2/dir3 or block/data formats
185 __dir2_block_tail_offset(
186 struct xfs_dir2_data_hdr
*block
,
190 struct xfs_dir2_block_tail
*btp
;
192 ASSERT(startoff
== 0);
194 btp
= xfs_dir2_block_tail_p(mp
->m_dir_geo
, block
);
195 return bitize((int)((char *)btp
- (char *)block
));
199 __dir2_data_entries_count(
205 for (i
= 0; ptr
< endptr
; i
++) {
206 struct xfs_dir2_data_entry
*dep
;
207 struct xfs_dir2_data_unused
*dup
;
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
);
213 dep
= (xfs_dir2_data_entry_t
*)ptr
;
214 ptr
+= libxfs_dir2_data_entsize(mp
, dep
->namelen
);
221 __dir2_data_entry_offset(
228 for (i
= 0; i
< idx
; i
++) {
229 struct xfs_dir2_data_entry
*dep
;
230 struct xfs_dir2_data_unused
*dup
;
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
);
237 dep
= (xfs_dir2_data_entry_t
*)ptr
;
238 ptr
+= libxfs_dir2_data_entsize(mp
, dep
->namelen
);
245 * Block format functions
248 dir2_block_hdr_count(
252 struct xfs_dir2_data_hdr
*block
= obj
;
254 ASSERT(startoff
== 0);
255 return be32_to_cpu(block
->magic
) == XFS_DIR2_BLOCK_MAGIC
;
259 dir3_block_hdr_count(
263 struct xfs_dir2_data_hdr
*block
= obj
;
265 ASSERT(startoff
== 0);
266 return be32_to_cpu(block
->magic
) == XFS_DIR3_BLOCK_MAGIC
;
270 dir2_block_leaf_count(
274 struct xfs_dir2_data_hdr
*block
= obj
;
275 struct xfs_dir2_block_tail
*btp
;
277 ASSERT(startoff
== 0);
278 if (be32_to_cpu(block
->magic
) != XFS_DIR2_BLOCK_MAGIC
&&
279 be32_to_cpu(block
->magic
) != XFS_DIR3_BLOCK_MAGIC
)
281 btp
= xfs_dir2_block_tail_p(mp
->m_dir_geo
, block
);
282 return be32_to_cpu(btp
->count
);
286 dir2_block_leaf_offset(
291 struct xfs_dir2_data_hdr
*block
= obj
;
292 struct xfs_dir2_block_tail
*btp
;
293 struct xfs_dir2_leaf_entry
*lep
;
295 ASSERT(startoff
== 0);
296 ASSERT(be32_to_cpu(block
->magic
) == XFS_DIR2_BLOCK_MAGIC
||
297 be32_to_cpu(block
->magic
) == XFS_DIR3_BLOCK_MAGIC
);
298 btp
= xfs_dir2_block_tail_p(mp
->m_dir_geo
, block
);
299 lep
= xfs_dir2_block_leaf_p(btp
) + idx
;
300 return bitize((int)((char *)lep
- (char *)block
));
304 dir2_block_tail_count(
308 struct xfs_dir2_data_hdr
*block
= obj
;
310 ASSERT(startoff
== 0);
311 return be32_to_cpu(block
->magic
) == XFS_DIR2_BLOCK_MAGIC
;
315 dir3_block_tail_count(
319 struct xfs_dir2_data_hdr
*block
= obj
;
321 ASSERT(startoff
== 0);
322 return be32_to_cpu(block
->magic
) == XFS_DIR3_BLOCK_MAGIC
;
326 dir2_block_tail_offset(
331 struct xfs_dir2_data_hdr
*block
= obj
;
333 ASSERT(be32_to_cpu(block
->magic
) == XFS_DIR2_BLOCK_MAGIC
||
334 be32_to_cpu(block
->magic
) == XFS_DIR3_BLOCK_MAGIC
);
335 return __dir2_block_tail_offset(block
, startoff
, idx
);
343 struct xfs_dir2_data_hdr
*block
= obj
;
344 struct xfs_dir2_block_tail
*btp
;
346 ASSERT(startoff
== 0);
347 if (be32_to_cpu(block
->magic
) != XFS_DIR2_BLOCK_MAGIC
&&
348 be32_to_cpu(block
->magic
) != XFS_DIR3_BLOCK_MAGIC
)
351 btp
= xfs_dir2_block_tail_p(mp
->m_dir_geo
, block
);
352 return __dir2_data_entries_count(
353 (char *)obj
+ mp
->m_dir_geo
->data_entry_offset
,
354 (char *)xfs_dir2_block_leaf_p(btp
));
363 struct xfs_dir2_data_hdr
*block
= obj
;
364 struct xfs_dir2_block_tail
*btp
;
367 ASSERT(startoff
== 0);
368 ASSERT(be32_to_cpu(block
->magic
) == XFS_DIR2_BLOCK_MAGIC
||
369 be32_to_cpu(block
->magic
) == XFS_DIR3_BLOCK_MAGIC
);
370 btp
= xfs_dir2_block_tail_p(mp
->m_dir_geo
, block
);
371 ptr
= __dir2_data_entry_offset(
372 (char *)obj
+ mp
->m_dir_geo
->data_entry_offset
,
373 (char *)xfs_dir2_block_leaf_p(btp
), idx
);
374 return bitize((int)(ptr
- (char *)block
));
378 * Data block format functions
381 dir2_data_union_freetag_count(
385 xfs_dir2_data_unused_t
*dup
;
388 ASSERT(bitoffs(startoff
) == 0);
389 dup
= (xfs_dir2_data_unused_t
*)((char *)obj
+ byteize(startoff
));
390 end
= (char *)&dup
->freetag
+ sizeof(dup
->freetag
);
391 return end
<= (char *)obj
+ mp
->m_dir_geo
->blksize
&&
392 be16_to_cpu(dup
->freetag
) == XFS_DIR2_DATA_FREE_TAG
;
396 dir2_data_union_inumber_count(
400 xfs_dir2_data_entry_t
*dep
;
401 xfs_dir2_data_unused_t
*dup
;
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
);
408 return end
<= (char *)obj
+ mp
->m_dir_geo
->blksize
&&
409 be16_to_cpu(dup
->freetag
) != XFS_DIR2_DATA_FREE_TAG
;
413 dir2_data_union_length_count(
417 xfs_dir2_data_unused_t
*dup
;
420 ASSERT(bitoffs(startoff
) == 0);
421 dup
= (xfs_dir2_data_unused_t
*)((char *)obj
+ byteize(startoff
));
422 end
= (char *)&dup
->length
+ sizeof(dup
->length
);
423 return end
<= (char *)obj
+ mp
->m_dir_geo
->blksize
&&
424 be16_to_cpu(dup
->freetag
) == XFS_DIR2_DATA_FREE_TAG
;
428 dir2_data_union_name_count(
432 xfs_dir2_data_entry_t
*dep
;
433 xfs_dir2_data_unused_t
*dup
;
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
);
440 if (end
>= (char *)obj
+ mp
->m_dir_geo
->blksize
||
441 be16_to_cpu(dup
->freetag
) == XFS_DIR2_DATA_FREE_TAG
)
443 end
= (char *)&dep
->name
[0] + dep
->namelen
;
444 return end
<= (char *)obj
+ mp
->m_dir_geo
->blksize
? dep
->namelen
: 0;
448 dir2_data_union_namelen_count(
452 xfs_dir2_data_entry_t
*dep
;
453 xfs_dir2_data_unused_t
*dup
;
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
);
460 return end
<= (char *)obj
+ mp
->m_dir_geo
->blksize
&&
461 be16_to_cpu(dup
->freetag
) != XFS_DIR2_DATA_FREE_TAG
;
465 dir2_data_union_tag_count(
469 xfs_dir2_data_entry_t
*dep
;
470 xfs_dir2_data_unused_t
*dup
;
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
);
478 if (end
> (char *)obj
+ mp
->m_dir_geo
->blksize
)
480 if (be16_to_cpu(dup
->freetag
) == XFS_DIR2_DATA_FREE_TAG
) {
481 end
= (char *)&dup
->length
+ sizeof(dup
->length
);
482 if (end
> (char *)obj
+ mp
->m_dir_geo
->blksize
)
484 tagp
= xfs_dir2_data_unused_tag_p(dup
);
486 end
= (char *)&dep
->namelen
+ sizeof(dep
->namelen
);
487 if (end
> (char *)obj
+ mp
->m_dir_geo
->blksize
)
489 tagp
= libxfs_dir2_data_entry_tag_p(mp
, dep
);
491 end
= (char *)tagp
+ sizeof(*tagp
);
492 return end
<= (char *)obj
+ mp
->m_dir_geo
->blksize
;
496 dir2_data_union_tag_offset(
501 xfs_dir2_data_entry_t
*dep
;
502 xfs_dir2_data_unused_t
*dup
;
504 ASSERT(bitoffs(startoff
) == 0);
506 dup
= (xfs_dir2_data_unused_t
*)((char *)obj
+ byteize(startoff
));
507 if (be16_to_cpu(dup
->freetag
) == XFS_DIR2_DATA_FREE_TAG
)
508 return bitize((int)((char *)xfs_dir2_data_unused_tag_p(dup
) -
510 dep
= (xfs_dir2_data_entry_t
*)dup
;
511 return bitize((int)((char *)libxfs_dir2_data_entry_tag_p(mp
, dep
) -
520 struct xfs_dir2_data_hdr
*data
= obj
;
522 ASSERT(startoff
== 0);
523 return be32_to_cpu(data
->magic
) == XFS_DIR2_DATA_MAGIC
;
531 struct xfs_dir2_data_hdr
*data
= obj
;
533 ASSERT(startoff
== 0);
534 return be32_to_cpu(data
->magic
) == XFS_DIR3_DATA_MAGIC
;
542 struct xfs_dir2_data_hdr
*data
= obj
;
544 ASSERT(startoff
== 0);
545 if (be32_to_cpu(data
->magic
) != XFS_DIR2_DATA_MAGIC
&&
546 be32_to_cpu(data
->magic
) != XFS_DIR3_DATA_MAGIC
)
549 return __dir2_data_entries_count(
550 (char *)data
+ mp
->m_dir_geo
->data_entry_offset
,
551 (char *)data
+ mp
->m_dir_geo
->blksize
);
560 struct xfs_dir2_data_hdr
*data
= obj
;
563 ASSERT(startoff
== 0);
564 ASSERT(be32_to_cpu(data
->magic
) == XFS_DIR2_DATA_MAGIC
||
565 be32_to_cpu(data
->magic
) == XFS_DIR3_DATA_MAGIC
);
566 ptr
= __dir2_data_entry_offset(
567 (char *)data
+ mp
->m_dir_geo
->data_entry_offset
,
568 (char *)data
+ mp
->m_dir_geo
->blksize
, idx
);
569 return bitize((int)(ptr
- (char *)data
));
573 dir2_data_union_size(
578 xfs_dir2_data_entry_t
*dep
;
579 xfs_dir2_data_unused_t
*dup
;
581 ASSERT(bitoffs(startoff
) == 0);
583 dup
= (xfs_dir2_data_unused_t
*)((char *)obj
+ byteize(startoff
));
584 if (be16_to_cpu(dup
->freetag
) == XFS_DIR2_DATA_FREE_TAG
)
585 return bitize(be16_to_cpu(dup
->length
));
587 dep
= (xfs_dir2_data_entry_t
*)dup
;
588 return bitize(libxfs_dir2_data_entsize(mp
, dep
->namelen
));
593 dir3_data_union_ftype_offset(
598 xfs_dir2_data_entry_t
*dep
;
599 xfs_dir2_data_unused_t
*dup
;
601 ASSERT(bitoffs(startoff
) == 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
) -
607 dep
= (xfs_dir2_data_entry_t
*)dup
;
608 return bitize((int)((char *)&dep
->name
[dep
->namelen
] - (char *)dep
));
612 * Free block functions
615 dir2_free_bests_count(
619 struct xfs_dir2_free
*free
= obj
;
621 ASSERT(startoff
== 0);
622 if (be32_to_cpu(free
->hdr
.magic
) != XFS_DIR2_FREE_MAGIC
)
624 return be32_to_cpu(free
->hdr
.nvalid
);
628 dir3_free_bests_count(
632 struct xfs_dir3_free
*free
= obj
;
634 ASSERT(startoff
== 0);
635 if (be32_to_cpu(free
->hdr
.hdr
.magic
) != XFS_DIR3_FREE_MAGIC
)
637 return be32_to_cpu(free
->hdr
.nvalid
);
645 struct xfs_dir2_free
*free
= obj
;
647 ASSERT(startoff
== 0);
648 return be32_to_cpu(free
->hdr
.magic
) == XFS_DIR2_FREE_MAGIC
;
656 struct xfs_dir3_free
*free
= obj
;
658 ASSERT(startoff
== 0);
659 return be32_to_cpu(free
->hdr
.hdr
.magic
) == XFS_DIR3_FREE_MAGIC
;
663 * Leaf block functions
666 dir2_leaf_bests_count(
670 struct xfs_dir2_leaf
*leaf
= obj
;
671 struct xfs_dir2_leaf_tail
*ltp
;
673 ASSERT(startoff
== 0);
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
)
677 ltp
= xfs_dir2_leaf_tail_p(mp
->m_dir_geo
, leaf
);
678 return be32_to_cpu(ltp
->bestcount
);
682 dir2_leaf_bests_offset(
687 struct xfs_dir2_leaf
*leaf
= obj
;
688 struct xfs_dir2_leaf_tail
*ltp
;
691 ASSERT(startoff
== 0);
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
);
694 ltp
= xfs_dir2_leaf_tail_p(mp
->m_dir_geo
, leaf
);
695 lbp
= xfs_dir2_leaf_bests_p(ltp
) + idx
;
696 return bitize((int)((char *)lbp
- (char *)leaf
));
700 dir2_leaf_ents_count(
704 struct xfs_dir2_leaf
*leaf
= obj
;
706 ASSERT(startoff
== 0);
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
)
710 return be16_to_cpu(leaf
->hdr
.count
);
714 dir3_leaf_ents_count(
718 struct xfs_dir3_leaf
*leaf
= obj
;
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
)
724 return be16_to_cpu(leaf
->hdr
.count
);
732 struct xfs_dir2_leaf
*leaf
= obj
;
734 ASSERT(startoff
== 0);
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
;
744 struct xfs_dir3_leaf
*leaf
= obj
;
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
;
752 dir2_leaf_tail_count(
756 struct xfs_dir2_leaf
*leaf
= obj
;
758 ASSERT(startoff
== 0);
759 return be16_to_cpu(leaf
->hdr
.info
.magic
) == XFS_DIR2_LEAF1_MAGIC
;
763 dir3_leaf_tail_count(
767 struct xfs_dir3_leaf
*leaf
= obj
;
769 ASSERT(startoff
== 0);
770 return be16_to_cpu(leaf
->hdr
.info
.hdr
.magic
) == XFS_DIR3_LEAF1_MAGIC
;
774 dir2_leaf_tail_offset(
779 struct xfs_dir2_leaf
*leaf
= obj
;
780 struct xfs_dir2_leaf_tail
*ltp
;
782 ASSERT(startoff
== 0);
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
);
786 ltp
= xfs_dir2_leaf_tail_p(mp
->m_dir_geo
, leaf
);
787 return bitize((int)((char *)ltp
- (char *)leaf
));
791 * Node format functions
794 dir2_node_btree_count(
798 xfs_da_intnode_t
*node
= obj
;
800 ASSERT(startoff
== 0);
801 if (be16_to_cpu(node
->hdr
.info
.magic
) != XFS_DA_NODE_MAGIC
)
803 return be16_to_cpu(node
->hdr
.__count
);
807 dir3_node_btree_count(
811 struct xfs_da3_intnode
*node
= obj
;
813 ASSERT(startoff
== 0);
814 if (be16_to_cpu(node
->hdr
.info
.hdr
.magic
) != XFS_DA3_NODE_MAGIC
)
816 return be16_to_cpu(node
->hdr
.__count
);
824 struct xfs_da_intnode
*node
= obj
;
826 ASSERT(startoff
== 0);
827 return be16_to_cpu(node
->hdr
.info
.magic
) == XFS_DA_NODE_MAGIC
;
835 struct xfs_da3_intnode
*node
= obj
;
837 ASSERT(startoff
== 0);
838 return be16_to_cpu(node
->hdr
.info
.hdr
.magic
) == XFS_DA3_NODE_MAGIC
;
847 return bitize(mp
->m_dir_geo
->blksize
);
851 * CRC enabled structure definitions
853 const field_t dir3_hfld
[] = {
854 { "", FLDT_DIR3
, OI(0), C1
, 0, TYP_NONE
},
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
},
866 { "bu", FLDT_DIR3_DATA_UNION
, dir2_block_u_offset
, dir2_block_u_count
,
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
},
874 { "du", FLDT_DIR3_DATA_UNION
, dir2_data_u_offset
, dir2_data_u_count
,
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
},
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
},
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
},
918 { "crc", FLDT_CRC
, OI(DBH3OFF(crc
)), C1
, 0, TYP_NONE
},
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
},
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
},
931 { "pad", FLDT_UINT32X
, OI(DH3OFF(pad
)), C1
, FLD_SKIPALL
, TYP_NONE
},
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
},
940 { "pad", FLDT_UINT32X
, OI(LH3OFF(pad
)), C1
, FLD_SKIPALL
, TYP_NONE
},
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
},
950 { "pad", FLDT_UINT32X
, OI(FH3OFF(pad
)), C1
, FLD_SKIPALL
, TYP_NONE
},
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
},
958 { "crc", FLDT_CRC
, OI(DB3OFF(crc
)), C1
, 0, TYP_NONE
},
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
},
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
},
971 { "pad", FLDT_UINT32X
, OI(H3OFF(__pad32
)), C1
, FLD_SKIPALL
, TYP_NONE
},
983 magic32
= *(__be32
*)bp
->b_addr
;
984 magic16
= ((struct xfs_da_blkinfo
*)bp
->b_addr
)->magic
;
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
);
991 case cpu_to_be32(XFS_DIR3_FREE_MAGIC
):
992 xfs_buf_update_cksum(bp
, XFS_DIR3_FREE_CRC_OFF
);
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
);
1003 case cpu_to_be16(XFS_DA3_NODE_MAGIC
):
1004 xfs_buf_update_cksum(bp
, XFS_DA3_NODE_CRC_OFF
);
1007 dbprintf(_("Unknown directory buffer type! %x %x\n"), magic32
, magic16
);
1013 * Special read verifier for directory buffers. Detect the magic number
1014 * appropriately and set the correct verifier and call it.
1017 xfs_dir3_db_read_verify(
1023 magic32
= *(__be32
*)bp
->b_addr
;
1024 magic16
= ((struct xfs_da_blkinfo
*)bp
->b_addr
)->magic
;
1027 case cpu_to_be32(XFS_DIR3_BLOCK_MAGIC
):
1028 bp
->b_ops
= &xfs_dir3_block_buf_ops
;
1030 case cpu_to_be32(XFS_DIR3_DATA_MAGIC
):
1031 bp
->b_ops
= &xfs_dir3_data_buf_ops
;
1033 case cpu_to_be32(XFS_DIR3_FREE_MAGIC
):
1034 bp
->b_ops
= &xfs_dir3_free_buf_ops
;
1041 case cpu_to_be16(XFS_DIR3_LEAF1_MAGIC
):
1042 bp
->b_ops
= &xfs_dir3_leaf1_buf_ops
;
1044 case cpu_to_be16(XFS_DIR3_LEAFN_MAGIC
):
1045 bp
->b_ops
= &xfs_dir3_leafn_buf_ops
;
1047 case cpu_to_be16(XFS_DA3_NODE_MAGIC
):
1048 bp
->b_ops
= &xfs_da3_node_buf_ops
;
1051 dbprintf(_("Unknown directory buffer type!\n"));
1052 xfs_buf_ioerror(bp
, -EFSCORRUPTED
);
1056 bp
->b_ops
->verify_read(bp
);
1060 xfs_dir3_db_write_verify(
1063 dbprintf(_("Writing unknown directory buffer type!\n"));
1064 xfs_buf_ioerror(bp
, -EFSCORRUPTED
);
1067 const struct xfs_buf_ops xfs_dir3_db_buf_ops
= {
1069 .verify_read
= xfs_dir3_db_read_verify
,
1070 .verify_write
= xfs_dir3_db_write_verify
,