2 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
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
7 * published by the Free Software Foundation.
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.
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
29 static int dir2_block_hdr_count(void *obj
, int startoff
);
30 static int dir2_block_leaf_count(void *obj
, int startoff
);
31 static int dir2_block_leaf_offset(void *obj
, int startoff
, int idx
);
32 static int dir2_block_tail_count(void *obj
, int startoff
);
33 static int dir2_block_tail_offset(void *obj
, int startoff
, int idx
);
34 static int dir2_block_u_count(void *obj
, int startoff
);
35 static int dir2_block_u_offset(void *obj
, int startoff
, int idx
);
36 static int dir2_data_union_freetag_count(void *obj
, int startoff
);
37 static int dir2_data_union_inumber_count(void *obj
, int startoff
);
38 static int dir2_data_union_length_count(void *obj
, int startoff
);
39 static int dir2_data_union_name_count(void *obj
, int startoff
);
40 static int dir2_data_union_namelen_count(void *obj
, int startoff
);
41 static int dir2_data_union_tag_count(void *obj
, int startoff
);
42 static int dir2_data_union_tag_offset(void *obj
, int startoff
, int idx
);
43 static int dir2_data_hdr_count(void *obj
, int startoff
);
44 static int dir2_data_u_count(void *obj
, int startoff
);
45 static int dir2_data_u_offset(void *obj
, int startoff
, int idx
);
46 static int dir2_free_bests_count(void *obj
, int startoff
);
47 static int dir2_free_hdr_count(void *obj
, int startoff
);
48 static int dir2_leaf_bests_count(void *obj
, int startoff
);
49 static int dir2_leaf_bests_offset(void *obj
, int startoff
, int idx
);
50 static int dir2_leaf_ents_count(void *obj
, int startoff
);
51 static int dir2_leaf_hdr_count(void *obj
, int startoff
);
52 static int dir2_leaf_tail_count(void *obj
, int startoff
);
53 static int dir2_leaf_tail_offset(void *obj
, int startoff
, int idx
);
54 static int dir2_node_btree_count(void *obj
, int startoff
);
55 static int dir2_node_hdr_count(void *obj
, int startoff
);
57 const field_t dir2_hfld
[] = {
58 { "", FLDT_DIR2
, OI(0), C1
, 0, TYP_NONE
},
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))
67 const field_t dir2_flds
[] = {
68 { "bhdr", FLDT_DIR2_DATA_HDR
, OI(BOFF(magic
)), dir2_block_hdr_count
,
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
},
76 { "dhdr", FLDT_DIR2_DATA_HDR
, OI(DOFF(magic
)), dir2_data_hdr_count
,
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
},
84 { "lents", FLDT_DIR2_LEAF_ENTRY
, OI(LOFF(__ents
)), dir2_leaf_ents_count
,
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
},
88 { "nhdr", FLDT_DA_NODE_HDR
, OI(NOFF(hdr
)), dir2_node_hdr_count
,
89 FLD_COUNT
, TYP_NONE
},
90 { "nbtree", FLDT_DA_NODE_ENTRY
, OI(NOFF(__btree
)), dir2_node_btree_count
,
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
},
99 #define BTOFF(f) bitize(offsetof(xfs_dir2_block_tail_t, f))
100 const 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
},
106 #define DFOFF(f) bitize(offsetof(xfs_dir2_data_free_t, f))
107 const 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
},
113 #define DHOFF(f) bitize(offsetof(xfs_dir2_data_hdr_t, f))
114 const 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
},
121 #define DEOFF(f) bitize(offsetof(xfs_dir2_data_entry_t, f))
122 #define DUOFF(f) bitize(offsetof(xfs_dir2_data_unused_t, f))
123 const 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
},
139 #define LEOFF(f) bitize(offsetof(xfs_dir2_leaf_entry_t, f))
140 const 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
},
146 #define LHOFF(f) bitize(offsetof(xfs_dir2_leaf_hdr_t, f))
147 const field_t dir2_leaf_hdr_flds
[] = {
148 { "info", FLDT_DA_BLKINFO
, OI(LHOFF(info
)), C1
, 0, TYP_NONE
},
149 { "count", FLDT_UINT16D
, OI(LHOFF(count
)), C1
, 0, TYP_NONE
},
150 { "stale", FLDT_UINT16D
, OI(LHOFF(stale
)), C1
, 0, TYP_NONE
},
154 #define LTOFF(f) bitize(offsetof(xfs_dir2_leaf_tail_t, f))
155 const field_t dir2_leaf_tail_flds
[] = {
156 { "bestcount", FLDT_UINT32D
, OI(LTOFF(bestcount
)), C1
, 0, TYP_NONE
},
160 #define FHOFF(f) bitize(offsetof(xfs_dir2_free_hdr_t, f))
161 const 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
},
169 #define DBOFF(f) bitize(offsetof(xfs_da_blkinfo_t, f))
170 const 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
},
178 #define EOFF(f) bitize(offsetof(xfs_da_node_entry_t, f))
179 const 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
},
185 #define HOFF(f) bitize(offsetof(xfs_da_node_hdr_t, f))
186 const field_t da_node_hdr_flds
[] = {
187 { "info", FLDT_DA_BLKINFO
, OI(HOFF(info
)), C1
, 0, TYP_NONE
},
188 { "count", FLDT_UINT16D
, OI(HOFF(__count
)), C1
, 0, TYP_NONE
},
189 { "level", FLDT_UINT16D
, OI(HOFF(__level
)), C1
, 0, TYP_NONE
},
194 * Worker functions shared between either dir2/dir3 or block/data formats
197 __dir2_block_tail_offset(
198 struct xfs_dir2_data_hdr
*block
,
202 struct xfs_dir2_block_tail
*btp
;
204 ASSERT(startoff
== 0);
206 btp
= xfs_dir2_block_tail_p(mp
->m_dir_geo
, block
);
207 return bitize((int)((char *)btp
- (char *)block
));
211 __dir2_data_entries_count(
217 for (i
= 0; ptr
< endptr
; i
++) {
218 struct xfs_dir2_data_entry
*dep
;
219 struct xfs_dir2_data_unused
*dup
;
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
);
225 dep
= (xfs_dir2_data_entry_t
*)ptr
;
226 ptr
+= M_DIROPS(mp
)->data_entsize(dep
->namelen
);
233 __dir2_data_entry_offset(
240 for (i
= 0; i
< idx
; i
++) {
241 struct xfs_dir2_data_entry
*dep
;
242 struct xfs_dir2_data_unused
*dup
;
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
);
249 dep
= (xfs_dir2_data_entry_t
*)ptr
;
250 ptr
+= M_DIROPS(mp
)->data_entsize(dep
->namelen
);
257 * Block format functions
260 dir2_block_hdr_count(
264 struct xfs_dir2_data_hdr
*block
= obj
;
266 ASSERT(startoff
== 0);
267 return be32_to_cpu(block
->magic
) == XFS_DIR2_BLOCK_MAGIC
;
271 dir3_block_hdr_count(
275 struct xfs_dir2_data_hdr
*block
= obj
;
277 ASSERT(startoff
== 0);
278 return be32_to_cpu(block
->magic
) == XFS_DIR3_BLOCK_MAGIC
;
282 dir2_block_leaf_count(
286 struct xfs_dir2_data_hdr
*block
= obj
;
287 struct xfs_dir2_block_tail
*btp
;
289 ASSERT(startoff
== 0);
290 if (be32_to_cpu(block
->magic
) != XFS_DIR2_BLOCK_MAGIC
&&
291 be32_to_cpu(block
->magic
) != XFS_DIR3_BLOCK_MAGIC
)
293 btp
= xfs_dir2_block_tail_p(mp
->m_dir_geo
, block
);
294 return be32_to_cpu(btp
->count
);
298 dir2_block_leaf_offset(
303 struct xfs_dir2_data_hdr
*block
= obj
;
304 struct xfs_dir2_block_tail
*btp
;
305 struct xfs_dir2_leaf_entry
*lep
;
307 ASSERT(startoff
== 0);
308 ASSERT(be32_to_cpu(block
->magic
) == XFS_DIR2_BLOCK_MAGIC
||
309 be32_to_cpu(block
->magic
) == XFS_DIR3_BLOCK_MAGIC
);
310 btp
= xfs_dir2_block_tail_p(mp
->m_dir_geo
, block
);
311 lep
= xfs_dir2_block_leaf_p(btp
) + idx
;
312 return bitize((int)((char *)lep
- (char *)block
));
316 dir2_block_tail_count(
320 struct xfs_dir2_data_hdr
*block
= obj
;
322 ASSERT(startoff
== 0);
323 return be32_to_cpu(block
->magic
) == XFS_DIR2_BLOCK_MAGIC
;
327 dir3_block_tail_count(
331 struct xfs_dir2_data_hdr
*block
= obj
;
333 ASSERT(startoff
== 0);
334 return be32_to_cpu(block
->magic
) == XFS_DIR3_BLOCK_MAGIC
;
338 dir2_block_tail_offset(
343 struct xfs_dir2_data_hdr
*block
= obj
;
345 ASSERT(be32_to_cpu(block
->magic
) == XFS_DIR2_BLOCK_MAGIC
||
346 be32_to_cpu(block
->magic
) == XFS_DIR3_BLOCK_MAGIC
);
347 return __dir2_block_tail_offset(block
, startoff
, idx
);
355 struct xfs_dir2_data_hdr
*block
= obj
;
356 struct xfs_dir2_block_tail
*btp
;
358 ASSERT(startoff
== 0);
359 if (be32_to_cpu(block
->magic
) != XFS_DIR2_BLOCK_MAGIC
&&
360 be32_to_cpu(block
->magic
) != XFS_DIR3_BLOCK_MAGIC
)
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
));
375 struct xfs_dir2_data_hdr
*block
= obj
;
376 struct xfs_dir2_block_tail
*btp
;
379 ASSERT(startoff
== 0);
380 ASSERT(be32_to_cpu(block
->magic
) == XFS_DIR2_BLOCK_MAGIC
||
381 be32_to_cpu(block
->magic
) == XFS_DIR3_BLOCK_MAGIC
);
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
);
386 return bitize((int)(ptr
- (char *)block
));
390 * Data block format functions
393 dir2_data_union_freetag_count(
397 xfs_dir2_data_unused_t
*dup
;
400 ASSERT(bitoffs(startoff
) == 0);
401 dup
= (xfs_dir2_data_unused_t
*)((char *)obj
+ byteize(startoff
));
402 end
= (char *)&dup
->freetag
+ sizeof(dup
->freetag
);
403 return end
<= (char *)obj
+ mp
->m_dir_geo
->blksize
&&
404 be16_to_cpu(dup
->freetag
) == XFS_DIR2_DATA_FREE_TAG
;
408 dir2_data_union_inumber_count(
412 xfs_dir2_data_entry_t
*dep
;
413 xfs_dir2_data_unused_t
*dup
;
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
);
420 return end
<= (char *)obj
+ mp
->m_dir_geo
->blksize
&&
421 be16_to_cpu(dup
->freetag
) != XFS_DIR2_DATA_FREE_TAG
;
425 dir2_data_union_length_count(
429 xfs_dir2_data_unused_t
*dup
;
432 ASSERT(bitoffs(startoff
) == 0);
433 dup
= (xfs_dir2_data_unused_t
*)((char *)obj
+ byteize(startoff
));
434 end
= (char *)&dup
->length
+ sizeof(dup
->length
);
435 return end
<= (char *)obj
+ mp
->m_dir_geo
->blksize
&&
436 be16_to_cpu(dup
->freetag
) == XFS_DIR2_DATA_FREE_TAG
;
440 dir2_data_union_name_count(
444 xfs_dir2_data_entry_t
*dep
;
445 xfs_dir2_data_unused_t
*dup
;
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
);
452 if (end
>= (char *)obj
+ mp
->m_dir_geo
->blksize
||
453 be16_to_cpu(dup
->freetag
) == XFS_DIR2_DATA_FREE_TAG
)
455 end
= (char *)&dep
->name
[0] + dep
->namelen
;
456 return end
<= (char *)obj
+ mp
->m_dir_geo
->blksize
? dep
->namelen
: 0;
460 dir2_data_union_namelen_count(
464 xfs_dir2_data_entry_t
*dep
;
465 xfs_dir2_data_unused_t
*dup
;
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
);
472 return end
<= (char *)obj
+ mp
->m_dir_geo
->blksize
&&
473 be16_to_cpu(dup
->freetag
) != XFS_DIR2_DATA_FREE_TAG
;
477 dir2_data_union_tag_count(
481 xfs_dir2_data_entry_t
*dep
;
482 xfs_dir2_data_unused_t
*dup
;
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
);
490 if (end
> (char *)obj
+ mp
->m_dir_geo
->blksize
)
492 if (be16_to_cpu(dup
->freetag
) == XFS_DIR2_DATA_FREE_TAG
) {
493 end
= (char *)&dup
->length
+ sizeof(dup
->length
);
494 if (end
> (char *)obj
+ mp
->m_dir_geo
->blksize
)
496 tagp
= xfs_dir2_data_unused_tag_p(dup
);
498 end
= (char *)&dep
->namelen
+ sizeof(dep
->namelen
);
499 if (end
> (char *)obj
+ mp
->m_dir_geo
->blksize
)
501 tagp
= M_DIROPS(mp
)->data_entry_tag_p(dep
);
503 end
= (char *)tagp
+ sizeof(*tagp
);
504 return end
<= (char *)obj
+ mp
->m_dir_geo
->blksize
;
508 dir2_data_union_tag_offset(
513 xfs_dir2_data_entry_t
*dep
;
514 xfs_dir2_data_unused_t
*dup
;
516 ASSERT(bitoffs(startoff
) == 0);
518 dup
= (xfs_dir2_data_unused_t
*)((char *)obj
+ byteize(startoff
));
519 if (be16_to_cpu(dup
->freetag
) == XFS_DIR2_DATA_FREE_TAG
)
520 return bitize((int)((char *)xfs_dir2_data_unused_tag_p(dup
) -
522 dep
= (xfs_dir2_data_entry_t
*)dup
;
523 return bitize((int)((char *)M_DIROPS(mp
)->data_entry_tag_p(dep
) -
532 struct xfs_dir2_data_hdr
*data
= obj
;
534 ASSERT(startoff
== 0);
535 return be32_to_cpu(data
->magic
) == XFS_DIR2_DATA_MAGIC
;
543 struct xfs_dir2_data_hdr
*data
= obj
;
545 ASSERT(startoff
== 0);
546 return be32_to_cpu(data
->magic
) == XFS_DIR3_DATA_MAGIC
;
554 struct xfs_dir2_data_hdr
*data
= obj
;
556 ASSERT(startoff
== 0);
557 if (be32_to_cpu(data
->magic
) != XFS_DIR2_DATA_MAGIC
&&
558 be32_to_cpu(data
->magic
) != XFS_DIR3_DATA_MAGIC
)
561 return __dir2_data_entries_count(
562 (char *)M_DIROPS(mp
)->data_unused_p(data
),
563 (char *)data
+ mp
->m_dir_geo
->blksize
);
572 struct xfs_dir2_data_hdr
*data
= obj
;
575 ASSERT(startoff
== 0);
576 ASSERT(be32_to_cpu(data
->magic
) == XFS_DIR2_DATA_MAGIC
||
577 be32_to_cpu(data
->magic
) == XFS_DIR3_DATA_MAGIC
);
578 ptr
= __dir2_data_entry_offset(
579 (char *)M_DIROPS(mp
)->data_unused_p(data
),
580 (char *)data
+ mp
->m_dir_geo
->blksize
, idx
);
581 return bitize((int)(ptr
- (char *)data
));
585 dir2_data_union_size(
590 xfs_dir2_data_entry_t
*dep
;
591 xfs_dir2_data_unused_t
*dup
;
593 ASSERT(bitoffs(startoff
) == 0);
595 dup
= (xfs_dir2_data_unused_t
*)((char *)obj
+ byteize(startoff
));
596 if (be16_to_cpu(dup
->freetag
) == XFS_DIR2_DATA_FREE_TAG
)
597 return bitize(be16_to_cpu(dup
->length
));
599 dep
= (xfs_dir2_data_entry_t
*)dup
;
600 return bitize(M_DIROPS(mp
)->data_entsize(dep
->namelen
));
605 dir3_data_union_ftype_offset(
610 xfs_dir2_data_entry_t
*dep
;
611 xfs_dir2_data_unused_t
*dup
;
613 ASSERT(bitoffs(startoff
) == 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
) -
619 dep
= (xfs_dir2_data_entry_t
*)dup
;
620 return bitize((int)((char *)&dep
->name
[dep
->namelen
] - (char *)dep
));
624 * Free block functions
627 dir2_free_bests_count(
631 struct xfs_dir2_free
*free
= obj
;
633 ASSERT(startoff
== 0);
634 if (be32_to_cpu(free
->hdr
.magic
) != XFS_DIR2_FREE_MAGIC
)
636 return be32_to_cpu(free
->hdr
.nvalid
);
640 dir3_free_bests_count(
644 struct xfs_dir3_free
*free
= obj
;
646 ASSERT(startoff
== 0);
647 if (be32_to_cpu(free
->hdr
.hdr
.magic
) != XFS_DIR3_FREE_MAGIC
)
649 return be32_to_cpu(free
->hdr
.nvalid
);
657 struct xfs_dir2_free
*free
= obj
;
659 ASSERT(startoff
== 0);
660 return be32_to_cpu(free
->hdr
.magic
) == XFS_DIR2_FREE_MAGIC
;
668 struct xfs_dir3_free
*free
= obj
;
670 ASSERT(startoff
== 0);
671 return be32_to_cpu(free
->hdr
.hdr
.magic
) == XFS_DIR3_FREE_MAGIC
;
675 * Leaf block functions
678 dir2_leaf_bests_count(
682 struct xfs_dir2_leaf
*leaf
= obj
;
683 struct xfs_dir2_leaf_tail
*ltp
;
685 ASSERT(startoff
== 0);
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
)
689 ltp
= xfs_dir2_leaf_tail_p(mp
->m_dir_geo
, leaf
);
690 return be32_to_cpu(ltp
->bestcount
);
694 dir2_leaf_bests_offset(
699 struct xfs_dir2_leaf
*leaf
= obj
;
700 struct xfs_dir2_leaf_tail
*ltp
;
703 ASSERT(startoff
== 0);
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
);
706 ltp
= xfs_dir2_leaf_tail_p(mp
->m_dir_geo
, leaf
);
707 lbp
= xfs_dir2_leaf_bests_p(ltp
) + idx
;
708 return bitize((int)((char *)lbp
- (char *)leaf
));
712 dir2_leaf_ents_count(
716 struct xfs_dir2_leaf
*leaf
= obj
;
718 ASSERT(startoff
== 0);
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
)
722 return be16_to_cpu(leaf
->hdr
.count
);
726 dir3_leaf_ents_count(
730 struct xfs_dir3_leaf
*leaf
= obj
;
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
)
736 return be16_to_cpu(leaf
->hdr
.count
);
744 struct xfs_dir2_leaf
*leaf
= obj
;
746 ASSERT(startoff
== 0);
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
;
756 struct xfs_dir3_leaf
*leaf
= obj
;
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
;
764 dir2_leaf_tail_count(
768 struct xfs_dir2_leaf
*leaf
= obj
;
770 ASSERT(startoff
== 0);
771 return be16_to_cpu(leaf
->hdr
.info
.magic
) == XFS_DIR2_LEAF1_MAGIC
;
775 dir3_leaf_tail_count(
779 struct xfs_dir3_leaf
*leaf
= obj
;
781 ASSERT(startoff
== 0);
782 return be16_to_cpu(leaf
->hdr
.info
.hdr
.magic
) == XFS_DIR3_LEAF1_MAGIC
;
786 dir2_leaf_tail_offset(
791 struct xfs_dir2_leaf
*leaf
= obj
;
792 struct xfs_dir2_leaf_tail
*ltp
;
794 ASSERT(startoff
== 0);
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
);
798 ltp
= xfs_dir2_leaf_tail_p(mp
->m_dir_geo
, leaf
);
799 return bitize((int)((char *)ltp
- (char *)leaf
));
803 * Node format functions
806 dir2_node_btree_count(
810 xfs_da_intnode_t
*node
= obj
;
812 ASSERT(startoff
== 0);
813 if (be16_to_cpu(node
->hdr
.info
.magic
) != XFS_DA_NODE_MAGIC
)
815 return be16_to_cpu(node
->hdr
.__count
);
819 dir3_node_btree_count(
823 struct xfs_da3_intnode
*node
= obj
;
825 ASSERT(startoff
== 0);
826 if (be16_to_cpu(node
->hdr
.info
.hdr
.magic
) != XFS_DA3_NODE_MAGIC
)
828 return be16_to_cpu(node
->hdr
.__count
);
836 struct xfs_da_intnode
*node
= obj
;
838 ASSERT(startoff
== 0);
839 return be16_to_cpu(node
->hdr
.info
.magic
) == XFS_DA_NODE_MAGIC
;
847 struct xfs_da3_intnode
*node
= obj
;
849 ASSERT(startoff
== 0);
850 return be16_to_cpu(node
->hdr
.info
.hdr
.magic
) == XFS_DA3_NODE_MAGIC
;
859 return bitize(mp
->m_dir_geo
->blksize
);
863 * CRC enabled structure definitions
865 const field_t dir3_hfld
[] = {
866 { "", FLDT_DIR3
, OI(0), C1
, 0, TYP_NONE
},
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))
875 const field_t dir3_flds
[] = {
876 { "bhdr", FLDT_DIR3_DATA_HDR
, OI(B3OFF(hdr
)), dir3_block_hdr_count
,
877 FLD_COUNT
, TYP_NONE
},
878 { "bu", FLDT_DIR3_DATA_UNION
, dir2_block_u_offset
, dir2_block_u_count
,
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
},
886 { "du", FLDT_DIR3_DATA_UNION
, dir2_data_u_offset
, dir2_data_u_count
,
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
},
907 #define D3EOFF(f) bitize(offsetof(xfs_dir2_data_entry_t, f))
908 #define D3UOFF(f) bitize(offsetof(xfs_dir2_data_unused_t, f))
909 const 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
},
927 #define DBH3OFF(f) bitize(offsetof(struct xfs_dir3_blk_hdr, f))
928 const field_t dir3_blkhdr_flds
[] = {
929 { "magic", FLDT_UINT32X
, OI(DBH3OFF(magic
)), C1
, 0, TYP_NONE
},
930 { "crc", FLDT_CRC
, OI(DBH3OFF(crc
)), C1
, 0, TYP_NONE
},
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
},
938 #define DH3OFF(f) bitize(offsetof(struct xfs_dir3_data_hdr, f))
939 const 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
},
946 #define LH3OFF(f) bitize(offsetof(struct xfs_dir3_leaf_hdr, f))
947 const field_t dir3_leaf_hdr_flds
[] = {
948 { "info", FLDT_DA3_BLKINFO
, OI(LH3OFF(info
)), C1
, 0, TYP_NONE
},
949 { "count", FLDT_UINT16D
, OI(LH3OFF(count
)), C1
, 0, TYP_NONE
},
950 { "stale", FLDT_UINT16D
, OI(LH3OFF(stale
)), C1
, 0, TYP_NONE
},
954 #define FH3OFF(f) bitize(offsetof(struct xfs_dir3_free_hdr, f))
955 const field_t dir3_free_hdr_flds
[] = {
956 { "hdr", FLDT_DIR3_BLKHDR
, OI(FH3OFF(hdr
)), C1
, 0, TYP_NONE
},
957 { "firstdb", FLDT_INT32D
, OI(FH3OFF(firstdb
)), C1
, 0, TYP_NONE
},
958 { "nvalid", FLDT_INT32D
, OI(FH3OFF(nvalid
)), C1
, 0, TYP_NONE
},
959 { "nused", FLDT_INT32D
, OI(FH3OFF(nused
)), C1
, 0, TYP_NONE
},
964 #define DB3OFF(f) bitize(offsetof(struct xfs_da3_blkinfo, f))
965 const field_t da3_blkinfo_flds
[] = {
966 { "hdr", FLDT_DA_BLKINFO
, OI(DB3OFF(hdr
)), C1
, 0, TYP_NONE
},
967 { "crc", FLDT_CRC
, OI(DB3OFF(crc
)), C1
, 0, TYP_NONE
},
968 { "bno", FLDT_DFSBNO
, OI(DB3OFF(blkno
)), C1
, 0, TYP_BMAPBTD
},
969 { "lsn", FLDT_UINT64X
, OI(DB3OFF(lsn
)), C1
, 0, TYP_NONE
},
970 { "uuid", FLDT_UUID
, OI(DB3OFF(uuid
)), C1
, 0, TYP_NONE
},
971 { "owner", FLDT_INO
, OI(DB3OFF(owner
)), C1
, 0, TYP_NONE
},
975 #define H3OFF(f) bitize(offsetof(struct xfs_da3_node_hdr, f))
976 const field_t da3_node_hdr_flds
[] = {
977 { "info", FLDT_DA3_BLKINFO
, OI(H3OFF(info
)), C1
, 0, TYP_NONE
},
978 { "count", FLDT_UINT16D
, OI(H3OFF(__count
)), C1
, 0, TYP_NONE
},
979 { "level", FLDT_UINT16D
, OI(H3OFF(__level
)), C1
, 0, TYP_NONE
},
980 { "pad", FLDT_UINT32D
, OI(H3OFF(__pad32
)), C1
, 0, TYP_NONE
},
985 * Special read verifier for directory buffers. Detect the magic number
986 * appropriately and set the correct verifier and call it.
989 xfs_dir3_db_read_verify(
995 magic32
= *(__be32
*)bp
->b_addr
;
996 magic16
= ((struct xfs_da_blkinfo
*)bp
->b_addr
)->magic
;
999 case cpu_to_be32(XFS_DIR3_BLOCK_MAGIC
):
1000 bp
->b_ops
= &xfs_dir3_block_buf_ops
;
1002 case cpu_to_be32(XFS_DIR3_DATA_MAGIC
):
1003 bp
->b_ops
= &xfs_dir3_data_buf_ops
;
1005 case cpu_to_be32(XFS_DIR3_FREE_MAGIC
):
1006 bp
->b_ops
= &xfs_dir3_free_buf_ops
;
1013 case cpu_to_be16(XFS_DIR3_LEAF1_MAGIC
):
1014 bp
->b_ops
= &xfs_dir3_leaf1_buf_ops
;
1016 case cpu_to_be16(XFS_DIR3_LEAFN_MAGIC
):
1017 bp
->b_ops
= &xfs_dir3_leafn_buf_ops
;
1019 case cpu_to_be16(XFS_DA3_NODE_MAGIC
):
1020 bp
->b_ops
= &xfs_da3_node_buf_ops
;
1023 dbprintf(_("Unknown directory buffer type!\n"));
1024 xfs_buf_ioerror(bp
, -EFSCORRUPTED
);
1028 bp
->b_ops
->verify_read(bp
);
1032 xfs_dir3_db_write_verify(
1035 dbprintf(_("Writing unknown directory buffer type!\n"));
1036 xfs_buf_ioerror(bp
, -EFSCORRUPTED
);
1039 const struct xfs_buf_ops xfs_dir3_db_buf_ops
= {
1041 .verify_read
= xfs_dir3_db_read_verify
,
1042 .verify_write
= xfs_dir3_db_write_verify
,