Merge tag 'devicetree-fixes-for-5.6' of git://git.kernel.org/pub/scm/linux/kernel...
[linux/fpc-iii.git] / fs / xfs / scrub / dabtree.c
blob97a15b6f286512c847b20d2dec72303c5b34e0d4
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright (C) 2017 Oracle. All Rights Reserved.
4 * Author: Darrick J. Wong <darrick.wong@oracle.com>
5 */
6 #include "xfs.h"
7 #include "xfs_fs.h"
8 #include "xfs_shared.h"
9 #include "xfs_format.h"
10 #include "xfs_trans_resv.h"
11 #include "xfs_mount.h"
12 #include "xfs_log_format.h"
13 #include "xfs_trans.h"
14 #include "xfs_inode.h"
15 #include "xfs_dir2.h"
16 #include "xfs_dir2_priv.h"
17 #include "xfs_attr_leaf.h"
18 #include "scrub/scrub.h"
19 #include "scrub/common.h"
20 #include "scrub/trace.h"
21 #include "scrub/dabtree.h"
23 /* Directory/Attribute Btree */
26 * Check for da btree operation errors. See the section about handling
27 * operational errors in common.c.
29 bool
30 xchk_da_process_error(
31 struct xchk_da_btree *ds,
32 int level,
33 int *error)
35 struct xfs_scrub *sc = ds->sc;
37 if (*error == 0)
38 return true;
40 switch (*error) {
41 case -EDEADLOCK:
42 /* Used to restart an op with deadlock avoidance. */
43 trace_xchk_deadlock_retry(sc->ip, sc->sm, *error);
44 break;
45 case -EFSBADCRC:
46 case -EFSCORRUPTED:
47 /* Note the badness but don't abort. */
48 sc->sm->sm_flags |= XFS_SCRUB_OFLAG_CORRUPT;
49 *error = 0;
50 /* fall through */
51 default:
52 trace_xchk_file_op_error(sc, ds->dargs.whichfork,
53 xfs_dir2_da_to_db(ds->dargs.geo,
54 ds->state->path.blk[level].blkno),
55 *error, __return_address);
56 break;
58 return false;
62 * Check for da btree corruption. See the section about handling
63 * operational errors in common.c.
65 void
66 xchk_da_set_corrupt(
67 struct xchk_da_btree *ds,
68 int level)
70 struct xfs_scrub *sc = ds->sc;
72 sc->sm->sm_flags |= XFS_SCRUB_OFLAG_CORRUPT;
74 trace_xchk_fblock_error(sc, ds->dargs.whichfork,
75 xfs_dir2_da_to_db(ds->dargs.geo,
76 ds->state->path.blk[level].blkno),
77 __return_address);
80 static struct xfs_da_node_entry *
81 xchk_da_btree_node_entry(
82 struct xchk_da_btree *ds,
83 int level)
85 struct xfs_da_state_blk *blk = &ds->state->path.blk[level];
86 struct xfs_da3_icnode_hdr hdr;
88 ASSERT(blk->magic == XFS_DA_NODE_MAGIC);
90 xfs_da3_node_hdr_from_disk(ds->sc->mp, &hdr, blk->bp->b_addr);
91 return hdr.btree + blk->index;
94 /* Scrub a da btree hash (key). */
95 int
96 xchk_da_btree_hash(
97 struct xchk_da_btree *ds,
98 int level,
99 __be32 *hashp)
101 struct xfs_da_node_entry *entry;
102 xfs_dahash_t hash;
103 xfs_dahash_t parent_hash;
105 /* Is this hash in order? */
106 hash = be32_to_cpu(*hashp);
107 if (hash < ds->hashes[level])
108 xchk_da_set_corrupt(ds, level);
109 ds->hashes[level] = hash;
111 if (level == 0)
112 return 0;
114 /* Is this hash no larger than the parent hash? */
115 entry = xchk_da_btree_node_entry(ds, level - 1);
116 parent_hash = be32_to_cpu(entry->hashval);
117 if (parent_hash < hash)
118 xchk_da_set_corrupt(ds, level);
120 return 0;
124 * Check a da btree pointer. Returns true if it's ok to use this
125 * pointer.
127 STATIC bool
128 xchk_da_btree_ptr_ok(
129 struct xchk_da_btree *ds,
130 int level,
131 xfs_dablk_t blkno)
133 if (blkno < ds->lowest || (ds->highest != 0 && blkno >= ds->highest)) {
134 xchk_da_set_corrupt(ds, level);
135 return false;
138 return true;
142 * The da btree scrubber can handle leaf1 blocks as a degenerate
143 * form of leafn blocks. Since the regular da code doesn't handle
144 * leaf1, we must multiplex the verifiers.
146 static void
147 xchk_da_btree_read_verify(
148 struct xfs_buf *bp)
150 struct xfs_da_blkinfo *info = bp->b_addr;
152 switch (be16_to_cpu(info->magic)) {
153 case XFS_DIR2_LEAF1_MAGIC:
154 case XFS_DIR3_LEAF1_MAGIC:
155 bp->b_ops = &xfs_dir3_leaf1_buf_ops;
156 bp->b_ops->verify_read(bp);
157 return;
158 default:
160 * xfs_da3_node_buf_ops already know how to handle
161 * DA*_NODE, ATTR*_LEAF, and DIR*_LEAFN blocks.
163 bp->b_ops = &xfs_da3_node_buf_ops;
164 bp->b_ops->verify_read(bp);
165 return;
168 static void
169 xchk_da_btree_write_verify(
170 struct xfs_buf *bp)
172 struct xfs_da_blkinfo *info = bp->b_addr;
174 switch (be16_to_cpu(info->magic)) {
175 case XFS_DIR2_LEAF1_MAGIC:
176 case XFS_DIR3_LEAF1_MAGIC:
177 bp->b_ops = &xfs_dir3_leaf1_buf_ops;
178 bp->b_ops->verify_write(bp);
179 return;
180 default:
182 * xfs_da3_node_buf_ops already know how to handle
183 * DA*_NODE, ATTR*_LEAF, and DIR*_LEAFN blocks.
185 bp->b_ops = &xfs_da3_node_buf_ops;
186 bp->b_ops->verify_write(bp);
187 return;
190 static void *
191 xchk_da_btree_verify(
192 struct xfs_buf *bp)
194 struct xfs_da_blkinfo *info = bp->b_addr;
196 switch (be16_to_cpu(info->magic)) {
197 case XFS_DIR2_LEAF1_MAGIC:
198 case XFS_DIR3_LEAF1_MAGIC:
199 bp->b_ops = &xfs_dir3_leaf1_buf_ops;
200 return bp->b_ops->verify_struct(bp);
201 default:
202 bp->b_ops = &xfs_da3_node_buf_ops;
203 return bp->b_ops->verify_struct(bp);
207 static const struct xfs_buf_ops xchk_da_btree_buf_ops = {
208 .name = "xchk_da_btree",
209 .verify_read = xchk_da_btree_read_verify,
210 .verify_write = xchk_da_btree_write_verify,
211 .verify_struct = xchk_da_btree_verify,
214 /* Check a block's sibling. */
215 STATIC int
216 xchk_da_btree_block_check_sibling(
217 struct xchk_da_btree *ds,
218 int level,
219 int direction,
220 xfs_dablk_t sibling)
222 int retval;
223 int error;
225 memcpy(&ds->state->altpath, &ds->state->path,
226 sizeof(ds->state->altpath));
229 * If the pointer is null, we shouldn't be able to move the upper
230 * level pointer anywhere.
232 if (sibling == 0) {
233 error = xfs_da3_path_shift(ds->state, &ds->state->altpath,
234 direction, false, &retval);
235 if (error == 0 && retval == 0)
236 xchk_da_set_corrupt(ds, level);
237 error = 0;
238 goto out;
241 /* Move the alternate cursor one block in the direction given. */
242 error = xfs_da3_path_shift(ds->state, &ds->state->altpath,
243 direction, false, &retval);
244 if (!xchk_da_process_error(ds, level, &error))
245 return error;
246 if (retval) {
247 xchk_da_set_corrupt(ds, level);
248 return error;
250 if (ds->state->altpath.blk[level].bp)
251 xchk_buffer_recheck(ds->sc,
252 ds->state->altpath.blk[level].bp);
254 /* Compare upper level pointer to sibling pointer. */
255 if (ds->state->altpath.blk[level].blkno != sibling)
256 xchk_da_set_corrupt(ds, level);
257 if (ds->state->altpath.blk[level].bp) {
258 xfs_trans_brelse(ds->dargs.trans,
259 ds->state->altpath.blk[level].bp);
260 ds->state->altpath.blk[level].bp = NULL;
262 out:
263 return error;
266 /* Check a block's sibling pointers. */
267 STATIC int
268 xchk_da_btree_block_check_siblings(
269 struct xchk_da_btree *ds,
270 int level,
271 struct xfs_da_blkinfo *hdr)
273 xfs_dablk_t forw;
274 xfs_dablk_t back;
275 int error = 0;
277 forw = be32_to_cpu(hdr->forw);
278 back = be32_to_cpu(hdr->back);
280 /* Top level blocks should not have sibling pointers. */
281 if (level == 0) {
282 if (forw != 0 || back != 0)
283 xchk_da_set_corrupt(ds, level);
284 return 0;
288 * Check back (left) and forw (right) pointers. These functions
289 * absorb error codes for us.
291 error = xchk_da_btree_block_check_sibling(ds, level, 0, back);
292 if (error)
293 goto out;
294 error = xchk_da_btree_block_check_sibling(ds, level, 1, forw);
296 out:
297 memset(&ds->state->altpath, 0, sizeof(ds->state->altpath));
298 return error;
301 /* Load a dir/attribute block from a btree. */
302 STATIC int
303 xchk_da_btree_block(
304 struct xchk_da_btree *ds,
305 int level,
306 xfs_dablk_t blkno)
308 struct xfs_da_state_blk *blk;
309 struct xfs_da_intnode *node;
310 struct xfs_da_node_entry *btree;
311 struct xfs_da3_blkinfo *hdr3;
312 struct xfs_da_args *dargs = &ds->dargs;
313 struct xfs_inode *ip = ds->dargs.dp;
314 xfs_ino_t owner;
315 int *pmaxrecs;
316 struct xfs_da3_icnode_hdr nodehdr;
317 int error = 0;
319 blk = &ds->state->path.blk[level];
320 ds->state->path.active = level + 1;
322 /* Release old block. */
323 if (blk->bp) {
324 xfs_trans_brelse(dargs->trans, blk->bp);
325 blk->bp = NULL;
328 /* Check the pointer. */
329 blk->blkno = blkno;
330 if (!xchk_da_btree_ptr_ok(ds, level, blkno))
331 goto out_nobuf;
333 /* Read the buffer. */
334 error = xfs_da_read_buf(dargs->trans, dargs->dp, blk->blkno,
335 XFS_DABUF_MAP_HOLE_OK, &blk->bp, dargs->whichfork,
336 &xchk_da_btree_buf_ops);
337 if (!xchk_da_process_error(ds, level, &error))
338 goto out_nobuf;
339 if (blk->bp)
340 xchk_buffer_recheck(ds->sc, blk->bp);
343 * We didn't find a dir btree root block, which means that
344 * there's no LEAF1/LEAFN tree (at least not where it's supposed
345 * to be), so jump out now.
347 if (ds->dargs.whichfork == XFS_DATA_FORK && level == 0 &&
348 blk->bp == NULL)
349 goto out_nobuf;
351 /* It's /not/ ok for attr trees not to have a da btree. */
352 if (blk->bp == NULL) {
353 xchk_da_set_corrupt(ds, level);
354 goto out_nobuf;
357 hdr3 = blk->bp->b_addr;
358 blk->magic = be16_to_cpu(hdr3->hdr.magic);
359 pmaxrecs = &ds->maxrecs[level];
361 /* We only started zeroing the header on v5 filesystems. */
362 if (xfs_sb_version_hascrc(&ds->sc->mp->m_sb) && hdr3->hdr.pad)
363 xchk_da_set_corrupt(ds, level);
365 /* Check the owner. */
366 if (xfs_sb_version_hascrc(&ip->i_mount->m_sb)) {
367 owner = be64_to_cpu(hdr3->owner);
368 if (owner != ip->i_ino)
369 xchk_da_set_corrupt(ds, level);
372 /* Check the siblings. */
373 error = xchk_da_btree_block_check_siblings(ds, level, &hdr3->hdr);
374 if (error)
375 goto out;
377 /* Interpret the buffer. */
378 switch (blk->magic) {
379 case XFS_ATTR_LEAF_MAGIC:
380 case XFS_ATTR3_LEAF_MAGIC:
381 xfs_trans_buf_set_type(dargs->trans, blk->bp,
382 XFS_BLFT_ATTR_LEAF_BUF);
383 blk->magic = XFS_ATTR_LEAF_MAGIC;
384 blk->hashval = xfs_attr_leaf_lasthash(blk->bp, pmaxrecs);
385 if (ds->tree_level != 0)
386 xchk_da_set_corrupt(ds, level);
387 break;
388 case XFS_DIR2_LEAFN_MAGIC:
389 case XFS_DIR3_LEAFN_MAGIC:
390 xfs_trans_buf_set_type(dargs->trans, blk->bp,
391 XFS_BLFT_DIR_LEAFN_BUF);
392 blk->magic = XFS_DIR2_LEAFN_MAGIC;
393 blk->hashval = xfs_dir2_leaf_lasthash(ip, blk->bp, pmaxrecs);
394 if (ds->tree_level != 0)
395 xchk_da_set_corrupt(ds, level);
396 break;
397 case XFS_DIR2_LEAF1_MAGIC:
398 case XFS_DIR3_LEAF1_MAGIC:
399 xfs_trans_buf_set_type(dargs->trans, blk->bp,
400 XFS_BLFT_DIR_LEAF1_BUF);
401 blk->magic = XFS_DIR2_LEAF1_MAGIC;
402 blk->hashval = xfs_dir2_leaf_lasthash(ip, blk->bp, pmaxrecs);
403 if (ds->tree_level != 0)
404 xchk_da_set_corrupt(ds, level);
405 break;
406 case XFS_DA_NODE_MAGIC:
407 case XFS_DA3_NODE_MAGIC:
408 xfs_trans_buf_set_type(dargs->trans, blk->bp,
409 XFS_BLFT_DA_NODE_BUF);
410 blk->magic = XFS_DA_NODE_MAGIC;
411 node = blk->bp->b_addr;
412 xfs_da3_node_hdr_from_disk(ip->i_mount, &nodehdr, node);
413 btree = nodehdr.btree;
414 *pmaxrecs = nodehdr.count;
415 blk->hashval = be32_to_cpu(btree[*pmaxrecs - 1].hashval);
416 if (level == 0) {
417 if (nodehdr.level >= XFS_DA_NODE_MAXDEPTH) {
418 xchk_da_set_corrupt(ds, level);
419 goto out_freebp;
421 ds->tree_level = nodehdr.level;
422 } else {
423 if (ds->tree_level != nodehdr.level) {
424 xchk_da_set_corrupt(ds, level);
425 goto out_freebp;
429 /* XXX: Check hdr3.pad32 once we know how to fix it. */
430 break;
431 default:
432 xchk_da_set_corrupt(ds, level);
433 goto out_freebp;
436 out:
437 return error;
438 out_freebp:
439 xfs_trans_brelse(dargs->trans, blk->bp);
440 blk->bp = NULL;
441 out_nobuf:
442 blk->blkno = 0;
443 return error;
446 /* Visit all nodes and leaves of a da btree. */
448 xchk_da_btree(
449 struct xfs_scrub *sc,
450 int whichfork,
451 xchk_da_btree_rec_fn scrub_fn,
452 void *private)
454 struct xchk_da_btree ds = {};
455 struct xfs_mount *mp = sc->mp;
456 struct xfs_da_state_blk *blks;
457 struct xfs_da_node_entry *key;
458 xfs_dablk_t blkno;
459 int level;
460 int error;
462 /* Skip short format data structures; no btree to scan. */
463 if (!xfs_ifork_has_extents(sc->ip, whichfork))
464 return 0;
466 /* Set up initial da state. */
467 ds.dargs.dp = sc->ip;
468 ds.dargs.whichfork = whichfork;
469 ds.dargs.trans = sc->tp;
470 ds.dargs.op_flags = XFS_DA_OP_OKNOENT;
471 ds.state = xfs_da_state_alloc();
472 ds.state->args = &ds.dargs;
473 ds.state->mp = mp;
474 ds.sc = sc;
475 ds.private = private;
476 if (whichfork == XFS_ATTR_FORK) {
477 ds.dargs.geo = mp->m_attr_geo;
478 ds.lowest = 0;
479 ds.highest = 0;
480 } else {
481 ds.dargs.geo = mp->m_dir_geo;
482 ds.lowest = ds.dargs.geo->leafblk;
483 ds.highest = ds.dargs.geo->freeblk;
485 blkno = ds.lowest;
486 level = 0;
488 /* Find the root of the da tree, if present. */
489 blks = ds.state->path.blk;
490 error = xchk_da_btree_block(&ds, level, blkno);
491 if (error)
492 goto out_state;
494 * We didn't find a block at ds.lowest, which means that there's
495 * no LEAF1/LEAFN tree (at least not where it's supposed to be),
496 * so jump out now.
498 if (blks[level].bp == NULL)
499 goto out_state;
501 blks[level].index = 0;
502 while (level >= 0 && level < XFS_DA_NODE_MAXDEPTH) {
503 /* Handle leaf block. */
504 if (blks[level].magic != XFS_DA_NODE_MAGIC) {
505 /* End of leaf, pop back towards the root. */
506 if (blks[level].index >= ds.maxrecs[level]) {
507 if (level > 0)
508 blks[level - 1].index++;
509 ds.tree_level++;
510 level--;
511 continue;
514 /* Dispatch record scrubbing. */
515 error = scrub_fn(&ds, level);
516 if (error)
517 break;
518 if (xchk_should_terminate(sc, &error) ||
519 (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT))
520 break;
522 blks[level].index++;
523 continue;
527 /* End of node, pop back towards the root. */
528 if (blks[level].index >= ds.maxrecs[level]) {
529 if (level > 0)
530 blks[level - 1].index++;
531 ds.tree_level++;
532 level--;
533 continue;
536 /* Hashes in order for scrub? */
537 key = xchk_da_btree_node_entry(&ds, level);
538 error = xchk_da_btree_hash(&ds, level, &key->hashval);
539 if (error)
540 goto out;
542 /* Drill another level deeper. */
543 blkno = be32_to_cpu(key->before);
544 level++;
545 if (level >= XFS_DA_NODE_MAXDEPTH) {
546 /* Too deep! */
547 xchk_da_set_corrupt(&ds, level - 1);
548 break;
550 ds.tree_level--;
551 error = xchk_da_btree_block(&ds, level, blkno);
552 if (error)
553 goto out;
554 if (blks[level].bp == NULL)
555 goto out;
557 blks[level].index = 0;
560 out:
561 /* Release all the buffers we're tracking. */
562 for (level = 0; level < XFS_DA_NODE_MAXDEPTH; level++) {
563 if (blks[level].bp == NULL)
564 continue;
565 xfs_trans_brelse(sc->tp, blks[level].bp);
566 blks[level].bp = NULL;
569 out_state:
570 xfs_da_state_free(ds.state);
571 return error;