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