1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2017 Oracle. All Rights Reserved.
4 * Author: Darrick J. Wong <darrick.wong@oracle.com>
8 #include "xfs_shared.h"
9 #include "xfs_format.h"
10 #include "xfs_trans_resv.h"
11 #include "xfs_mount.h"
12 #include "xfs_defer.h"
13 #include "xfs_btree.h"
15 #include "xfs_log_format.h"
16 #include "xfs_trans.h"
18 #include "xfs_inode.h"
19 #include "xfs_inode_fork.h"
20 #include "xfs_da_format.h"
21 #include "xfs_da_btree.h"
23 #include "xfs_dir2_priv.h"
24 #include "xfs_attr_leaf.h"
25 #include "scrub/xfs_scrub.h"
26 #include "scrub/scrub.h"
27 #include "scrub/common.h"
28 #include "scrub/trace.h"
29 #include "scrub/dabtree.h"
31 /* Directory/Attribute Btree */
34 * Check for da btree operation errors. See the section about handling
35 * operational errors in common.c.
38 xchk_da_process_error(
39 struct xchk_da_btree
*ds
,
43 struct xfs_scrub
*sc
= ds
->sc
;
50 /* Used to restart an op with deadlock avoidance. */
51 trace_xchk_deadlock_retry(sc
->ip
, sc
->sm
, *error
);
55 /* Note the badness but don't abort. */
56 sc
->sm
->sm_flags
|= XFS_SCRUB_OFLAG_CORRUPT
;
60 trace_xchk_file_op_error(sc
, ds
->dargs
.whichfork
,
61 xfs_dir2_da_to_db(ds
->dargs
.geo
,
62 ds
->state
->path
.blk
[level
].blkno
),
63 *error
, __return_address
);
70 * Check for da btree corruption. See the section about handling
71 * operational errors in common.c.
75 struct xchk_da_btree
*ds
,
78 struct xfs_scrub
*sc
= ds
->sc
;
80 sc
->sm
->sm_flags
|= XFS_SCRUB_OFLAG_CORRUPT
;
82 trace_xchk_fblock_error(sc
, ds
->dargs
.whichfork
,
83 xfs_dir2_da_to_db(ds
->dargs
.geo
,
84 ds
->state
->path
.blk
[level
].blkno
),
88 /* Find an entry at a certain level in a da btree. */
91 struct xchk_da_btree
*ds
,
96 struct xfs_da_state_blk
*blk
;
99 /* Dispatch the entry finding function. */
100 blk
= &ds
->state
->path
.blk
[level
];
101 baddr
= blk
->bp
->b_addr
;
102 switch (blk
->magic
) {
103 case XFS_ATTR_LEAF_MAGIC
:
104 case XFS_ATTR3_LEAF_MAGIC
:
105 ents
= (char *)xfs_attr3_leaf_entryp(baddr
);
106 return ents
+ (rec
* sizeof(struct xfs_attr_leaf_entry
));
107 case XFS_DIR2_LEAFN_MAGIC
:
108 case XFS_DIR3_LEAFN_MAGIC
:
109 ents
= (char *)ds
->dargs
.dp
->d_ops
->leaf_ents_p(baddr
);
110 return ents
+ (rec
* sizeof(struct xfs_dir2_leaf_entry
));
111 case XFS_DIR2_LEAF1_MAGIC
:
112 case XFS_DIR3_LEAF1_MAGIC
:
113 ents
= (char *)ds
->dargs
.dp
->d_ops
->leaf_ents_p(baddr
);
114 return ents
+ (rec
* sizeof(struct xfs_dir2_leaf_entry
));
115 case XFS_DA_NODE_MAGIC
:
116 case XFS_DA3_NODE_MAGIC
:
117 ents
= (char *)ds
->dargs
.dp
->d_ops
->node_tree_p(baddr
);
118 return ents
+ (rec
* sizeof(struct xfs_da_node_entry
));
124 /* Scrub a da btree hash (key). */
127 struct xchk_da_btree
*ds
,
131 struct xfs_da_state_blk
*blks
;
132 struct xfs_da_node_entry
*entry
;
134 xfs_dahash_t parent_hash
;
136 /* Is this hash in order? */
137 hash
= be32_to_cpu(*hashp
);
138 if (hash
< ds
->hashes
[level
])
139 xchk_da_set_corrupt(ds
, level
);
140 ds
->hashes
[level
] = hash
;
145 /* Is this hash no larger than the parent hash? */
146 blks
= ds
->state
->path
.blk
;
147 entry
= xchk_da_btree_entry(ds
, level
- 1, blks
[level
- 1].index
);
148 parent_hash
= be32_to_cpu(entry
->hashval
);
149 if (parent_hash
< hash
)
150 xchk_da_set_corrupt(ds
, level
);
156 * Check a da btree pointer. Returns true if it's ok to use this
160 xchk_da_btree_ptr_ok(
161 struct xchk_da_btree
*ds
,
165 if (blkno
< ds
->lowest
|| (ds
->highest
!= 0 && blkno
>= ds
->highest
)) {
166 xchk_da_set_corrupt(ds
, level
);
174 * The da btree scrubber can handle leaf1 blocks as a degenerate
175 * form of leafn blocks. Since the regular da code doesn't handle
176 * leaf1, we must multiplex the verifiers.
179 xchk_da_btree_read_verify(
182 struct xfs_da_blkinfo
*info
= bp
->b_addr
;
184 switch (be16_to_cpu(info
->magic
)) {
185 case XFS_DIR2_LEAF1_MAGIC
:
186 case XFS_DIR3_LEAF1_MAGIC
:
187 bp
->b_ops
= &xfs_dir3_leaf1_buf_ops
;
188 bp
->b_ops
->verify_read(bp
);
192 * xfs_da3_node_buf_ops already know how to handle
193 * DA*_NODE, ATTR*_LEAF, and DIR*_LEAFN blocks.
195 bp
->b_ops
= &xfs_da3_node_buf_ops
;
196 bp
->b_ops
->verify_read(bp
);
201 xchk_da_btree_write_verify(
204 struct xfs_da_blkinfo
*info
= bp
->b_addr
;
206 switch (be16_to_cpu(info
->magic
)) {
207 case XFS_DIR2_LEAF1_MAGIC
:
208 case XFS_DIR3_LEAF1_MAGIC
:
209 bp
->b_ops
= &xfs_dir3_leaf1_buf_ops
;
210 bp
->b_ops
->verify_write(bp
);
214 * xfs_da3_node_buf_ops already know how to handle
215 * DA*_NODE, ATTR*_LEAF, and DIR*_LEAFN blocks.
217 bp
->b_ops
= &xfs_da3_node_buf_ops
;
218 bp
->b_ops
->verify_write(bp
);
223 xchk_da_btree_verify(
226 struct xfs_da_blkinfo
*info
= bp
->b_addr
;
228 switch (be16_to_cpu(info
->magic
)) {
229 case XFS_DIR2_LEAF1_MAGIC
:
230 case XFS_DIR3_LEAF1_MAGIC
:
231 bp
->b_ops
= &xfs_dir3_leaf1_buf_ops
;
232 return bp
->b_ops
->verify_struct(bp
);
234 bp
->b_ops
= &xfs_da3_node_buf_ops
;
235 return bp
->b_ops
->verify_struct(bp
);
239 static const struct xfs_buf_ops xchk_da_btree_buf_ops
= {
240 .name
= "xchk_da_btree",
241 .verify_read
= xchk_da_btree_read_verify
,
242 .verify_write
= xchk_da_btree_write_verify
,
243 .verify_struct
= xchk_da_btree_verify
,
246 /* Check a block's sibling. */
248 xchk_da_btree_block_check_sibling(
249 struct xchk_da_btree
*ds
,
257 memcpy(&ds
->state
->altpath
, &ds
->state
->path
,
258 sizeof(ds
->state
->altpath
));
261 * If the pointer is null, we shouldn't be able to move the upper
262 * level pointer anywhere.
265 error
= xfs_da3_path_shift(ds
->state
, &ds
->state
->altpath
,
266 direction
, false, &retval
);
267 if (error
== 0 && retval
== 0)
268 xchk_da_set_corrupt(ds
, level
);
273 /* Move the alternate cursor one block in the direction given. */
274 error
= xfs_da3_path_shift(ds
->state
, &ds
->state
->altpath
,
275 direction
, false, &retval
);
276 if (!xchk_da_process_error(ds
, level
, &error
))
279 xchk_da_set_corrupt(ds
, level
);
282 if (ds
->state
->altpath
.blk
[level
].bp
)
283 xchk_buffer_recheck(ds
->sc
,
284 ds
->state
->altpath
.blk
[level
].bp
);
286 /* Compare upper level pointer to sibling pointer. */
287 if (ds
->state
->altpath
.blk
[level
].blkno
!= sibling
)
288 xchk_da_set_corrupt(ds
, level
);
289 xfs_trans_brelse(ds
->dargs
.trans
, ds
->state
->altpath
.blk
[level
].bp
);
294 /* Check a block's sibling pointers. */
296 xchk_da_btree_block_check_siblings(
297 struct xchk_da_btree
*ds
,
299 struct xfs_da_blkinfo
*hdr
)
305 forw
= be32_to_cpu(hdr
->forw
);
306 back
= be32_to_cpu(hdr
->back
);
308 /* Top level blocks should not have sibling pointers. */
310 if (forw
!= 0 || back
!= 0)
311 xchk_da_set_corrupt(ds
, level
);
316 * Check back (left) and forw (right) pointers. These functions
317 * absorb error codes for us.
319 error
= xchk_da_btree_block_check_sibling(ds
, level
, 0, back
);
322 error
= xchk_da_btree_block_check_sibling(ds
, level
, 1, forw
);
325 memset(&ds
->state
->altpath
, 0, sizeof(ds
->state
->altpath
));
329 /* Load a dir/attribute block from a btree. */
332 struct xchk_da_btree
*ds
,
336 struct xfs_da_state_blk
*blk
;
337 struct xfs_da_intnode
*node
;
338 struct xfs_da_node_entry
*btree
;
339 struct xfs_da3_blkinfo
*hdr3
;
340 struct xfs_da_args
*dargs
= &ds
->dargs
;
341 struct xfs_inode
*ip
= ds
->dargs
.dp
;
344 struct xfs_da3_icnode_hdr nodehdr
;
347 blk
= &ds
->state
->path
.blk
[level
];
348 ds
->state
->path
.active
= level
+ 1;
350 /* Release old block. */
352 xfs_trans_brelse(dargs
->trans
, blk
->bp
);
356 /* Check the pointer. */
358 if (!xchk_da_btree_ptr_ok(ds
, level
, blkno
))
361 /* Read the buffer. */
362 error
= xfs_da_read_buf(dargs
->trans
, dargs
->dp
, blk
->blkno
, -2,
363 &blk
->bp
, dargs
->whichfork
,
364 &xchk_da_btree_buf_ops
);
365 if (!xchk_da_process_error(ds
, level
, &error
))
368 xchk_buffer_recheck(ds
->sc
, blk
->bp
);
371 * We didn't find a dir btree root block, which means that
372 * there's no LEAF1/LEAFN tree (at least not where it's supposed
373 * to be), so jump out now.
375 if (ds
->dargs
.whichfork
== XFS_DATA_FORK
&& level
== 0 &&
379 /* It's /not/ ok for attr trees not to have a da btree. */
380 if (blk
->bp
== NULL
) {
381 xchk_da_set_corrupt(ds
, level
);
385 hdr3
= blk
->bp
->b_addr
;
386 blk
->magic
= be16_to_cpu(hdr3
->hdr
.magic
);
387 pmaxrecs
= &ds
->maxrecs
[level
];
389 /* We only started zeroing the header on v5 filesystems. */
390 if (xfs_sb_version_hascrc(&ds
->sc
->mp
->m_sb
) && hdr3
->hdr
.pad
)
391 xchk_da_set_corrupt(ds
, level
);
393 /* Check the owner. */
394 if (xfs_sb_version_hascrc(&ip
->i_mount
->m_sb
)) {
395 owner
= be64_to_cpu(hdr3
->owner
);
396 if (owner
!= ip
->i_ino
)
397 xchk_da_set_corrupt(ds
, level
);
400 /* Check the siblings. */
401 error
= xchk_da_btree_block_check_siblings(ds
, level
, &hdr3
->hdr
);
405 /* Interpret the buffer. */
406 switch (blk
->magic
) {
407 case XFS_ATTR_LEAF_MAGIC
:
408 case XFS_ATTR3_LEAF_MAGIC
:
409 xfs_trans_buf_set_type(dargs
->trans
, blk
->bp
,
410 XFS_BLFT_ATTR_LEAF_BUF
);
411 blk
->magic
= XFS_ATTR_LEAF_MAGIC
;
412 blk
->hashval
= xfs_attr_leaf_lasthash(blk
->bp
, pmaxrecs
);
413 if (ds
->tree_level
!= 0)
414 xchk_da_set_corrupt(ds
, level
);
416 case XFS_DIR2_LEAFN_MAGIC
:
417 case XFS_DIR3_LEAFN_MAGIC
:
418 xfs_trans_buf_set_type(dargs
->trans
, blk
->bp
,
419 XFS_BLFT_DIR_LEAFN_BUF
);
420 blk
->magic
= XFS_DIR2_LEAFN_MAGIC
;
421 blk
->hashval
= xfs_dir2_leaf_lasthash(ip
, blk
->bp
, pmaxrecs
);
422 if (ds
->tree_level
!= 0)
423 xchk_da_set_corrupt(ds
, level
);
425 case XFS_DIR2_LEAF1_MAGIC
:
426 case XFS_DIR3_LEAF1_MAGIC
:
427 xfs_trans_buf_set_type(dargs
->trans
, blk
->bp
,
428 XFS_BLFT_DIR_LEAF1_BUF
);
429 blk
->magic
= XFS_DIR2_LEAF1_MAGIC
;
430 blk
->hashval
= xfs_dir2_leaf_lasthash(ip
, blk
->bp
, pmaxrecs
);
431 if (ds
->tree_level
!= 0)
432 xchk_da_set_corrupt(ds
, level
);
434 case XFS_DA_NODE_MAGIC
:
435 case XFS_DA3_NODE_MAGIC
:
436 xfs_trans_buf_set_type(dargs
->trans
, blk
->bp
,
437 XFS_BLFT_DA_NODE_BUF
);
438 blk
->magic
= XFS_DA_NODE_MAGIC
;
439 node
= blk
->bp
->b_addr
;
440 ip
->d_ops
->node_hdr_from_disk(&nodehdr
, node
);
441 btree
= ip
->d_ops
->node_tree_p(node
);
442 *pmaxrecs
= nodehdr
.count
;
443 blk
->hashval
= be32_to_cpu(btree
[*pmaxrecs
- 1].hashval
);
445 if (nodehdr
.level
>= XFS_DA_NODE_MAXDEPTH
) {
446 xchk_da_set_corrupt(ds
, level
);
449 ds
->tree_level
= nodehdr
.level
;
451 if (ds
->tree_level
!= nodehdr
.level
) {
452 xchk_da_set_corrupt(ds
, level
);
457 /* XXX: Check hdr3.pad32 once we know how to fix it. */
460 xchk_da_set_corrupt(ds
, level
);
467 xfs_trans_brelse(dargs
->trans
, blk
->bp
);
474 /* Visit all nodes and leaves of a da btree. */
477 struct xfs_scrub
*sc
,
479 xchk_da_btree_rec_fn scrub_fn
,
482 struct xchk_da_btree ds
= {};
483 struct xfs_mount
*mp
= sc
->mp
;
484 struct xfs_da_state_blk
*blks
;
485 struct xfs_da_node_entry
*key
;
491 /* Skip short format data structures; no btree to scan. */
492 if (XFS_IFORK_FORMAT(sc
->ip
, whichfork
) != XFS_DINODE_FMT_EXTENTS
&&
493 XFS_IFORK_FORMAT(sc
->ip
, whichfork
) != XFS_DINODE_FMT_BTREE
)
496 /* Set up initial da state. */
497 ds
.dargs
.dp
= sc
->ip
;
498 ds
.dargs
.whichfork
= whichfork
;
499 ds
.dargs
.trans
= sc
->tp
;
500 ds
.dargs
.op_flags
= XFS_DA_OP_OKNOENT
;
501 ds
.state
= xfs_da_state_alloc();
502 ds
.state
->args
= &ds
.dargs
;
505 ds
.private = private;
506 if (whichfork
== XFS_ATTR_FORK
) {
507 ds
.dargs
.geo
= mp
->m_attr_geo
;
511 ds
.dargs
.geo
= mp
->m_dir_geo
;
512 ds
.lowest
= ds
.dargs
.geo
->leafblk
;
513 ds
.highest
= ds
.dargs
.geo
->freeblk
;
518 /* Find the root of the da tree, if present. */
519 blks
= ds
.state
->path
.blk
;
520 error
= xchk_da_btree_block(&ds
, level
, blkno
);
524 * We didn't find a block at ds.lowest, which means that there's
525 * no LEAF1/LEAFN tree (at least not where it's supposed to be),
528 if (blks
[level
].bp
== NULL
)
531 blks
[level
].index
= 0;
532 while (level
>= 0 && level
< XFS_DA_NODE_MAXDEPTH
) {
533 /* Handle leaf block. */
534 if (blks
[level
].magic
!= XFS_DA_NODE_MAGIC
) {
535 /* End of leaf, pop back towards the root. */
536 if (blks
[level
].index
>= ds
.maxrecs
[level
]) {
538 blks
[level
- 1].index
++;
544 /* Dispatch record scrubbing. */
545 rec
= xchk_da_btree_entry(&ds
, level
,
547 error
= scrub_fn(&ds
, level
, rec
);
550 if (xchk_should_terminate(sc
, &error
) ||
551 (sc
->sm
->sm_flags
& XFS_SCRUB_OFLAG_CORRUPT
))
559 /* End of node, pop back towards the root. */
560 if (blks
[level
].index
>= ds
.maxrecs
[level
]) {
562 blks
[level
- 1].index
++;
568 /* Hashes in order for scrub? */
569 key
= xchk_da_btree_entry(&ds
, level
, blks
[level
].index
);
570 error
= xchk_da_btree_hash(&ds
, level
, &key
->hashval
);
574 /* Drill another level deeper. */
575 blkno
= be32_to_cpu(key
->before
);
577 if (level
>= XFS_DA_NODE_MAXDEPTH
) {
579 xchk_da_set_corrupt(&ds
, level
- 1);
583 error
= xchk_da_btree_block(&ds
, level
, blkno
);
586 if (blks
[level
].bp
== NULL
)
589 blks
[level
].index
= 0;
593 /* Release all the buffers we're tracking. */
594 for (level
= 0; level
< XFS_DA_NODE_MAXDEPTH
; level
++) {
595 if (blks
[level
].bp
== NULL
)
597 xfs_trans_brelse(sc
->tp
, blks
[level
].bp
);
598 blks
[level
].bp
= NULL
;
602 xfs_da_state_free(ds
.state
);