LCOV - code coverage report
Current view: top level - fs/xfs/scrub - dabtree.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc4-xfsx @ Mon Jul 31 20:08:34 PDT 2023 Lines: 231 325 71.1 %
Date: 2023-07-31 20:08:34 Functions: 10 13 76.9 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-or-later
       2             : /*
       3             :  * Copyright (C) 2017-2023 Oracle.  All Rights Reserved.
       4             :  * Author: Darrick J. Wong <djwong@kernel.org>
       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"
      22             : 
      23             : /* Directory/Attribute Btree */
      24             : 
      25             : /*
      26             :  * Check for da btree operation errors.  See the section about handling
      27             :  * operational errors in common.c.
      28             :  */
      29             : bool
      30     3839635 : xchk_da_process_error(
      31             :         struct xchk_da_btree    *ds,
      32             :         int                     level,
      33             :         int                     *error)
      34             : {
      35     3839635 :         struct xfs_scrub        *sc = ds->sc;
      36             : 
      37     3839635 :         if (*error == 0)
      38             :                 return true;
      39             : 
      40           0 :         switch (*error) {
      41           0 :         case -EDEADLOCK:
      42             :         case -ECHRNG:
      43             :                 /* Used to restart an op with deadlock avoidance. */
      44           0 :                 trace_xchk_deadlock_retry(sc->ip, sc->sm, *error);
      45           0 :                 break;
      46           0 :         case -EFSBADCRC:
      47             :         case -EFSCORRUPTED:
      48             :                 /* Note the badness but don't abort. */
      49           0 :                 sc->sm->sm_flags |= XFS_SCRUB_OFLAG_CORRUPT;
      50           0 :                 xchk_whine(sc->mp, "ino 0x%llx fork %d type %s dablk 0x%llx error %d ret_ip %pS",
      51           0 :                                 sc->ip->i_ino,
      52             :                                 ds->dargs.whichfork,
      53           0 :                                 xchk_type_string(sc->sm->sm_type),
      54             :                                 xfs_dir2_da_to_db(ds->dargs.geo,
      55           0 :                                         ds->state->path.blk[level].blkno),
      56             :                                 *error,
      57             :                                 __return_address);
      58           0 :                 *error = 0;
      59           0 :                 fallthrough;
      60           0 :         default:
      61           0 :                 if (*error)
      62           0 :                         xchk_whine(sc->mp, "ino 0x%llx fork %d type %s dablk 0x%llx error %d ret_ip %pS",
      63           0 :                                         sc->ip->i_ino,
      64             :                                         ds->dargs.whichfork,
      65           0 :                                         xchk_type_string(sc->sm->sm_type),
      66             :                                         xfs_dir2_da_to_db(ds->dargs.geo,
      67           0 :                                                 ds->state->path.blk[level].blkno),
      68             :                                         *error,
      69             :                                         __return_address);
      70           0 :                 trace_xchk_file_op_error(sc, ds->dargs.whichfork,
      71           0 :                                 xfs_dir2_da_to_db(ds->dargs.geo,
      72           0 :                                         ds->state->path.blk[level].blkno),
      73             :                                 *error, __return_address);
      74           0 :                 break;
      75             :         }
      76             :         return false;
      77             : }
      78             : 
      79             : /*
      80             :  * Check for da btree corruption.  See the section about handling
      81             :  * operational errors in common.c.
      82             :  */
      83             : void
      84           0 : xchk_da_set_corrupt(
      85             :         struct xchk_da_btree    *ds,
      86             :         int                     level)
      87             : {
      88           0 :         struct xfs_scrub        *sc = ds->sc;
      89             : 
      90           0 :         sc->sm->sm_flags |= XFS_SCRUB_OFLAG_CORRUPT;
      91             : 
      92           0 :         xchk_whine(sc->mp, "ino 0x%llx fork %d type %s dablk 0x%llx ret_ip %pS",
      93           0 :                         sc->ip->i_ino,
      94             :                         ds->dargs.whichfork,
      95           0 :                         xchk_type_string(sc->sm->sm_type),
      96             :                         xfs_dir2_da_to_db(ds->dargs.geo,
      97           0 :                                 ds->state->path.blk[level].blkno),
      98             :                         __return_address);
      99           0 :         trace_xchk_fblock_error(sc, ds->dargs.whichfork,
     100           0 :                         xfs_dir2_da_to_db(ds->dargs.geo,
     101           0 :                                 ds->state->path.blk[level].blkno),
     102             :                         __return_address);
     103           0 : }
     104             : 
     105             : /* Flag a da btree node in need of optimization. */
     106             : void
     107     1961565 : xchk_da_set_preen(
     108             :         struct xchk_da_btree    *ds,
     109             :         int                     level)
     110             : {
     111     1961565 :         struct xfs_scrub        *sc = ds->sc;
     112             : 
     113     1961565 :         sc->sm->sm_flags |= XFS_SCRUB_OFLAG_PREEN;
     114     3923718 :         trace_xchk_fblock_preen(sc, ds->dargs.whichfork,
     115     1958458 :                         xfs_dir2_da_to_db(ds->dargs.geo,
     116     1959513 :                                 ds->state->path.blk[level].blkno),
     117             :                         __return_address);
     118     1963069 : }
     119             : 
     120             : /* Find an entry at a certain level in a da btree. */
     121             : static struct xfs_da_node_entry *
     122    79202076 : xchk_da_btree_node_entry(
     123             :         struct xchk_da_btree            *ds,
     124             :         int                             level)
     125             : {
     126    79202076 :         struct xfs_da_state_blk         *blk = &ds->state->path.blk[level];
     127    79172687 :         struct xfs_da3_icnode_hdr       hdr;
     128             : 
     129    79172687 :         ASSERT(blk->magic == XFS_DA_NODE_MAGIC);
     130             : 
     131    79172687 :         xfs_da3_node_hdr_from_disk(ds->sc->mp, &hdr, blk->bp->b_addr);
     132    79183749 :         return hdr.btree + blk->index;
     133             : }
     134             : 
     135             : /* Scrub a da btree hash (key). */
     136             : int
     137   121067577 : xchk_da_btree_hash(
     138             :         struct xchk_da_btree            *ds,
     139             :         int                             level,
     140             :         __be32                          *hashp)
     141             : {
     142   121067577 :         struct xfs_da_node_entry        *entry;
     143   121067577 :         xfs_dahash_t                    hash;
     144   121067577 :         xfs_dahash_t                    parent_hash;
     145             : 
     146             :         /* Is this hash in order? */
     147   121067577 :         hash = be32_to_cpu(*hashp);
     148   121067577 :         if (hash < ds->hashes[level])
     149           0 :                 xchk_da_set_corrupt(ds, level);
     150   120985616 :         ds->hashes[level] = hash;
     151             : 
     152   120989896 :         if (level == 0)
     153             :                 return 0;
     154             : 
     155             :         /* Is this hash no larger than the parent hash? */
     156    78196431 :         entry = xchk_da_btree_node_entry(ds, level - 1);
     157    78251463 :         parent_hash = be32_to_cpu(entry->hashval);
     158    78251463 :         if (parent_hash < hash)
     159           0 :                 xchk_da_set_corrupt(ds, level);
     160             : 
     161             :         return 0;
     162             : }
     163             : 
     164             : /*
     165             :  * Check a da btree pointer.  Returns true if it's ok to use this
     166             :  * pointer.
     167             :  */
     168             : STATIC bool
     169     3025820 : xchk_da_btree_ptr_ok(
     170             :         struct xchk_da_btree    *ds,
     171             :         int                     level,
     172             :         xfs_dablk_t             blkno)
     173             : {
     174     3025820 :         if (blkno < ds->lowest || (ds->highest != 0 && blkno >= ds->highest)) {
     175           0 :                 xchk_da_set_corrupt(ds, level);
     176           0 :                 return false;
     177             :         }
     178             : 
     179             :         return true;
     180             : }
     181             : 
     182             : /*
     183             :  * The da btree scrubber can handle leaf1 blocks as a degenerate
     184             :  * form of leafn blocks.  Since the regular da code doesn't handle
     185             :  * leaf1, we must multiplex the verifiers.
     186             :  */
     187             : static void
     188       14109 : xchk_da_btree_read_verify(
     189             :         struct xfs_buf          *bp)
     190             : {
     191       14109 :         struct xfs_da_blkinfo   *info = bp->b_addr;
     192             : 
     193       14109 :         switch (be16_to_cpu(info->magic)) {
     194         391 :         case XFS_DIR2_LEAF1_MAGIC:
     195             :         case XFS_DIR3_LEAF1_MAGIC:
     196         391 :                 bp->b_ops = &xfs_dir3_leaf1_buf_ops;
     197         391 :                 bp->b_ops->verify_read(bp);
     198         391 :                 return;
     199       13718 :         default:
     200             :                 /*
     201             :                  * xfs_da3_node_buf_ops already know how to handle
     202             :                  * DA*_NODE, ATTR*_LEAF, and DIR*_LEAFN blocks.
     203             :                  */
     204       13718 :                 bp->b_ops = &xfs_da3_node_buf_ops;
     205       13718 :                 bp->b_ops->verify_read(bp);
     206       13718 :                 return;
     207             :         }
     208             : }
     209             : static void
     210           0 : xchk_da_btree_write_verify(
     211             :         struct xfs_buf          *bp)
     212             : {
     213           0 :         struct xfs_da_blkinfo   *info = bp->b_addr;
     214             : 
     215           0 :         switch (be16_to_cpu(info->magic)) {
     216           0 :         case XFS_DIR2_LEAF1_MAGIC:
     217             :         case XFS_DIR3_LEAF1_MAGIC:
     218           0 :                 bp->b_ops = &xfs_dir3_leaf1_buf_ops;
     219           0 :                 bp->b_ops->verify_write(bp);
     220           0 :                 return;
     221           0 :         default:
     222             :                 /*
     223             :                  * xfs_da3_node_buf_ops already know how to handle
     224             :                  * DA*_NODE, ATTR*_LEAF, and DIR*_LEAFN blocks.
     225             :                  */
     226           0 :                 bp->b_ops = &xfs_da3_node_buf_ops;
     227           0 :                 bp->b_ops->verify_write(bp);
     228           0 :                 return;
     229             :         }
     230             : }
     231             : static void *
     232           0 : xchk_da_btree_verify(
     233             :         struct xfs_buf          *bp)
     234             : {
     235           0 :         struct xfs_da_blkinfo   *info = bp->b_addr;
     236             : 
     237           0 :         switch (be16_to_cpu(info->magic)) {
     238           0 :         case XFS_DIR2_LEAF1_MAGIC:
     239             :         case XFS_DIR3_LEAF1_MAGIC:
     240           0 :                 bp->b_ops = &xfs_dir3_leaf1_buf_ops;
     241           0 :                 return bp->b_ops->verify_struct(bp);
     242           0 :         default:
     243           0 :                 bp->b_ops = &xfs_da3_node_buf_ops;
     244           0 :                 return bp->b_ops->verify_struct(bp);
     245             :         }
     246             : }
     247             : 
     248             : static const struct xfs_buf_ops xchk_da_btree_buf_ops = {
     249             :         .name = "xchk_da_btree",
     250             :         .verify_read = xchk_da_btree_read_verify,
     251             :         .verify_write = xchk_da_btree_write_verify,
     252             :         .verify_struct = xchk_da_btree_verify,
     253             : };
     254             : 
     255             : /* Check a block's sibling. */
     256             : STATIC int
     257      951122 : xchk_da_btree_block_check_sibling(
     258             :         struct xchk_da_btree    *ds,
     259             :         int                     level,
     260             :         int                     direction,
     261             :         xfs_dablk_t             sibling)
     262             : {
     263      951122 :         struct xfs_da_state_path *path = &ds->state->path;
     264      951122 :         struct xfs_da_state_path *altpath = &ds->state->altpath;
     265      951122 :         int                     retval;
     266      951122 :         int                     plevel;
     267      951122 :         int                     error;
     268             : 
     269     1902244 :         memcpy(altpath, path, sizeof(ds->state->altpath));
     270             : 
     271             :         /*
     272             :          * If the pointer is null, we shouldn't be able to move the upper
     273             :          * level pointer anywhere.
     274             :          */
     275      951122 :         if (sibling == 0) {
     276      132467 :                 error = xfs_da3_path_shift(ds->state, altpath, direction,
     277             :                                 false, &retval);
     278      132465 :                 if (error == 0 && retval == 0)
     279           0 :                         xchk_da_set_corrupt(ds, level);
     280      132465 :                 error = 0;
     281      132465 :                 goto out;
     282             :         }
     283             : 
     284             :         /* Move the alternate cursor one block in the direction given. */
     285      818655 :         error = xfs_da3_path_shift(ds->state, altpath, direction, false,
     286             :                         &retval);
     287      818654 :         if (!xchk_da_process_error(ds, level, &error))
     288           0 :                 goto out;
     289      818650 :         if (retval) {
     290           0 :                 xchk_da_set_corrupt(ds, level);
     291           0 :                 goto out;
     292             :         }
     293      818650 :         if (altpath->blk[level].bp)
     294      818652 :                 xchk_buffer_recheck(ds->sc, altpath->blk[level].bp);
     295             : 
     296             :         /* Compare upper level pointer to sibling pointer. */
     297      818664 :         if (altpath->blk[level].blkno != sibling)
     298           0 :                 xchk_da_set_corrupt(ds, level);
     299             : 
     300      818664 : out:
     301             :         /* Free all buffers in the altpath that aren't referenced from path. */
     302     3094247 :         for (plevel = 0; plevel < altpath->active; plevel++) {
     303     2143122 :                 if (altpath->blk[plevel].bp == NULL ||
     304     2143104 :                     (plevel < path->active &&
     305     2143104 :                      altpath->blk[plevel].bp == path->blk[plevel].bp))
     306     1323668 :                         continue;
     307             : 
     308      819436 :                 xfs_trans_brelse(ds->dargs.trans, altpath->blk[plevel].bp);
     309      819450 :                 altpath->blk[plevel].bp = NULL;
     310             :         }
     311             : 
     312      951125 :         return error;
     313             : }
     314             : 
     315             : /* Check a block's sibling pointers. */
     316             : STATIC int
     317     2749643 : xchk_da_btree_block_check_siblings(
     318             :         struct xchk_da_btree    *ds,
     319             :         int                     level,
     320             :         struct xfs_da_blkinfo   *hdr)
     321             : {
     322     2749643 :         xfs_dablk_t             forw;
     323     2749643 :         xfs_dablk_t             back;
     324     2749643 :         int                     error = 0;
     325             : 
     326     2749643 :         forw = be32_to_cpu(hdr->forw);
     327     2749643 :         back = be32_to_cpu(hdr->back);
     328             : 
     329             :         /* Top level blocks should not have sibling pointers. */
     330     2749643 :         if (level == 0) {
     331     2274073 :                 if (forw != 0 || back != 0)
     332           0 :                         xchk_da_set_corrupt(ds, level);
     333     2274073 :                 return 0;
     334             :         }
     335             : 
     336             :         /*
     337             :          * Check back (left) and forw (right) pointers.  These functions
     338             :          * absorb error codes for us.
     339             :          */
     340      475570 :         error = xchk_da_btree_block_check_sibling(ds, level, 0, back);
     341      475554 :         if (error)
     342           0 :                 goto out;
     343      475554 :         error = xchk_da_btree_block_check_sibling(ds, level, 1, forw);
     344             : 
     345      475570 : out:
     346      475570 :         memset(&ds->state->altpath, 0, sizeof(ds->state->altpath));
     347      475570 :         return error;
     348             : }
     349             : 
     350             : /* Load a dir/attribute block from a btree. */
     351             : STATIC int
     352     3030605 : xchk_da_btree_block(
     353             :         struct xchk_da_btree            *ds,
     354             :         int                             level,
     355             :         xfs_dablk_t                     blkno)
     356             : {
     357     3030605 :         struct xfs_da_state_blk         *blk;
     358     3030605 :         struct xfs_da_intnode           *node;
     359     3030605 :         struct xfs_da_node_entry        *btree;
     360     3030605 :         struct xfs_da3_blkinfo          *hdr3;
     361     3030605 :         struct xfs_da_args              *dargs = &ds->dargs;
     362     3030605 :         struct xfs_inode                *ip = ds->dargs.dp;
     363     3030605 :         xfs_failaddr_t                  fa;
     364     3030605 :         xfs_ino_t                       owner;
     365     3030605 :         int                             *pmaxrecs;
     366     3030605 :         struct xfs_da3_icnode_hdr       nodehdr;
     367     3030605 :         int                             error = 0;
     368             : 
     369     3030605 :         blk = &ds->state->path.blk[level];
     370     3022317 :         ds->state->path.active = level + 1;
     371             : 
     372             :         /* Release old block. */
     373     3022317 :         if (blk->bp) {
     374      409328 :                 xfs_trans_brelse(dargs->trans, blk->bp);
     375      409333 :                 blk->bp = NULL;
     376             :         }
     377             : 
     378             :         /* Check the pointer. */
     379     3022322 :         blk->blkno = blkno;
     380     3022322 :         if (!xchk_da_btree_ptr_ok(ds, level, blkno))
     381           0 :                 goto out_nobuf;
     382             : 
     383             :         /* Read the buffer. */
     384     3018032 :         error = xfs_da_read_buf(dargs->trans, dargs->dp, blk->blkno,
     385             :                         XFS_DABUF_MAP_HOLE_OK, &blk->bp, dargs->whichfork,
     386             :                         &xchk_da_btree_buf_ops);
     387     3025713 :         if (!xchk_da_process_error(ds, level, &error))
     388           0 :                 goto out_nobuf;
     389     3019603 :         if (blk->bp)
     390     2737450 :                 xchk_buffer_recheck(ds->sc, blk->bp);
     391             : 
     392             :         /*
     393             :          * We didn't find a dir btree root block, which means that
     394             :          * there's no LEAF1/LEAFN tree (at least not where it's supposed
     395             :          * to be), so jump out now.
     396             :          */
     397     3033747 :         if (ds->dargs.whichfork == XFS_DATA_FORK && level == 0 &&
     398      327903 :                         blk->bp == NULL)
     399      282156 :                 goto out_nobuf;
     400             : 
     401             :         /* It's /not/ ok for attr trees not to have a da btree. */
     402     2751591 :         if (blk->bp == NULL) {
     403           0 :                 xchk_da_set_corrupt(ds, level);
     404           0 :                 goto out_nobuf;
     405             :         }
     406             : 
     407     2751591 :         hdr3 = blk->bp->b_addr;
     408     2751591 :         blk->magic = be16_to_cpu(hdr3->hdr.magic);
     409     2751591 :         pmaxrecs = &ds->maxrecs[level];
     410             : 
     411             :         /* We only started zeroing the header on v5 filesystems. */
     412     2751225 :         if (xfs_has_crc(ds->sc->mp) && hdr3->hdr.pad)
     413           0 :                 xchk_da_set_corrupt(ds, level);
     414             : 
     415             :         /* Check the owner. */
     416     2751225 :         if (xfs_has_crc(ip->i_mount)) {
     417     2750289 :                 owner = be64_to_cpu(hdr3->owner);
     418     2750289 :                 if (owner != ip->i_ino)
     419           0 :                         xchk_da_set_corrupt(ds, level);
     420             :         }
     421             : 
     422             :         /* Check the siblings. */
     423     2751225 :         error = xchk_da_btree_block_check_siblings(ds, level, &hdr3->hdr);
     424     2746547 :         if (error)
     425           0 :                 goto out;
     426             : 
     427             :         /* Interpret the buffer. */
     428     2746547 :         switch (blk->magic) {
     429     2432273 :         case XFS_ATTR_LEAF_MAGIC:
     430             :         case XFS_ATTR3_LEAF_MAGIC:
     431     2432273 :                 xfs_trans_buf_set_type(dargs->trans, blk->bp,
     432             :                                 XFS_BLFT_ATTR_LEAF_BUF);
     433     2427471 :                 blk->magic = XFS_ATTR_LEAF_MAGIC;
     434     2427471 :                 blk->hashval = xfs_attr_leaf_lasthash(blk->bp, pmaxrecs);
     435     2430780 :                 if (ds->tree_level != 0)
     436           0 :                         xchk_da_set_corrupt(ds, level);
     437             :                 break;
     438      227799 :         case XFS_DIR2_LEAFN_MAGIC:
     439             :         case XFS_DIR3_LEAFN_MAGIC:
     440      227799 :                 xfs_trans_buf_set_type(dargs->trans, blk->bp,
     441             :                                 XFS_BLFT_DIR_LEAFN_BUF);
     442      227797 :                 blk->magic = XFS_DIR2_LEAFN_MAGIC;
     443      227797 :                 blk->hashval = xfs_dir2_leaf_lasthash(ip, blk->bp, pmaxrecs);
     444      227797 :                 if (ds->tree_level != 0)
     445           0 :                         xchk_da_set_corrupt(ds, level);
     446             :                 break;
     447       19851 :         case XFS_DIR2_LEAF1_MAGIC:
     448             :         case XFS_DIR3_LEAF1_MAGIC:
     449       19851 :                 xfs_trans_buf_set_type(dargs->trans, blk->bp,
     450             :                                 XFS_BLFT_DIR_LEAF1_BUF);
     451       19851 :                 blk->magic = XFS_DIR2_LEAF1_MAGIC;
     452       19851 :                 blk->hashval = xfs_dir2_leaf_lasthash(ip, blk->bp, pmaxrecs);
     453       19851 :                 if (ds->tree_level != 0)
     454           0 :                         xchk_da_set_corrupt(ds, level);
     455             :                 break;
     456       66624 :         case XFS_DA_NODE_MAGIC:
     457             :         case XFS_DA3_NODE_MAGIC:
     458       66624 :                 xfs_trans_buf_set_type(dargs->trans, blk->bp,
     459             :                                 XFS_BLFT_DA_NODE_BUF);
     460       66619 :                 blk->magic = XFS_DA_NODE_MAGIC;
     461       66619 :                 node = blk->bp->b_addr;
     462       66619 :                 xfs_da3_node_hdr_from_disk(ip->i_mount, &nodehdr, node);
     463       66622 :                 btree = nodehdr.btree;
     464       66622 :                 *pmaxrecs = nodehdr.count;
     465       66622 :                 blk->hashval = be32_to_cpu(btree[*pmaxrecs - 1].hashval);
     466       66622 :                 if (level == 0) {
     467       66173 :                         if (nodehdr.level >= XFS_DA_NODE_MAXDEPTH) {
     468           0 :                                 xchk_da_set_corrupt(ds, level);
     469           0 :                                 goto out_freebp;
     470             :                         }
     471       66173 :                         ds->tree_level = nodehdr.level;
     472             :                 } else {
     473         449 :                         if (ds->tree_level != nodehdr.level) {
     474           0 :                                 xchk_da_set_corrupt(ds, level);
     475           0 :                                 goto out_freebp;
     476             :                         }
     477             :                 }
     478             : 
     479             :                 /* XXX: Check hdr3.pad32 once we know how to fix it. */
     480             :                 break;
     481           0 :         default:
     482           0 :                 xchk_da_set_corrupt(ds, level);
     483           0 :                 goto out_freebp;
     484             :         }
     485             : 
     486     2745050 :         fa = xfs_da3_header_check(blk->bp, dargs->owner);
     487     2739776 :         if (fa) {
     488           0 :                 xchk_da_set_corrupt(ds, level);
     489           0 :                 goto out_freebp;
     490             :         }
     491             : 
     492             :         /*
     493             :          * If we've been handed a block that is below the dabtree root, does
     494             :          * its hashval match what the parent block expected to see?
     495             :          */
     496     2739776 :         if (level > 0) {
     497      475557 :                 struct xfs_da_node_entry        *key;
     498             : 
     499      475557 :                 key = xchk_da_btree_node_entry(ds, level - 1);
     500      475551 :                 if (be32_to_cpu(key->hashval) != blk->hashval) {
     501           0 :                         xchk_da_set_corrupt(ds, level);
     502           0 :                         goto out_freebp;
     503             :                 }
     504             :         }
     505             : 
     506     2739770 : out:
     507             :         return error;
     508           0 : out_freebp:
     509           0 :         xfs_trans_brelse(dargs->trans, blk->bp);
     510           0 :         blk->bp = NULL;
     511      282156 : out_nobuf:
     512      282156 :         blk->blkno = 0;
     513      282156 :         return error;
     514             : }
     515             : 
     516             : /* Visit all nodes and leaves of a da btree. */
     517             : int
     518    21554659 : xchk_da_btree(
     519             :         struct xfs_scrub                *sc,
     520             :         int                             whichfork,
     521             :         xchk_da_btree_rec_fn            scrub_fn,
     522             :         void                            *private)
     523             : {
     524    21554659 :         struct xchk_da_btree            *ds;
     525    21554659 :         struct xfs_mount                *mp = sc->mp;
     526    21554659 :         struct xfs_da_state_blk         *blks;
     527    21554659 :         struct xfs_da_node_entry        *key;
     528    21554659 :         xfs_dablk_t                     blkno;
     529    21554659 :         int                             level;
     530    21554659 :         int                             error;
     531             : 
     532             :         /* Skip short format data structures; no btree to scan. */
     533    21554659 :         if (!xfs_ifork_has_extents(xfs_ifork_ptr(sc->ip, whichfork)))
     534             :                 return 0;
     535             : 
     536             :         /* Set up initial da state. */
     537     2546274 :         ds = kzalloc(sizeof(struct xchk_da_btree), XCHK_GFP_FLAGS);
     538     2551842 :         if (!ds)
     539             :                 return -ENOMEM;
     540     2551842 :         ds->dargs.dp = sc->ip;
     541     2551842 :         ds->dargs.whichfork = whichfork;
     542     2551842 :         ds->dargs.trans = sc->tp;
     543     2551842 :         ds->dargs.op_flags = XFS_DA_OP_OKNOENT;
     544     2551842 :         ds->dargs.owner = sc->ip->i_ino;
     545     2551842 :         ds->state = xfs_da_state_alloc(&ds->dargs);
     546     2551958 :         ds->sc = sc;
     547     2551958 :         ds->private = private;
     548     2551958 :         if (whichfork == XFS_ATTR_FORK) {
     549     2224028 :                 ds->dargs.geo = mp->m_attr_geo;
     550     2224028 :                 ds->lowest = 0;
     551     2224028 :                 ds->highest = 0;
     552             :         } else {
     553      327930 :                 ds->dargs.geo = mp->m_dir_geo;
     554      327930 :                 ds->lowest = ds->dargs.geo->leafblk;
     555      327930 :                 ds->highest = ds->dargs.geo->freeblk;
     556             :         }
     557     2551958 :         blkno = ds->lowest;
     558     2551958 :         level = 0;
     559             : 
     560             :         /* Find the root of the da tree, if present. */
     561     2551958 :         blks = ds->state->path.blk;
     562     2551958 :         error = xchk_da_btree_block(ds, level, blkno);
     563     2547679 :         if (error)
     564           0 :                 goto out_state;
     565             :         /*
     566             :          * We didn't find a block at ds->lowest, which means that there's
     567             :          * no LEAF1/LEAFN tree (at least not where it's supposed to be),
     568             :          * so jump out now.
     569             :          */
     570     2547679 :         if (blks[level].bp == NULL)
     571      282155 :                 goto out_state;
     572             : 
     573     2265524 :         blks[level].index = 0;
     574   126115569 :         while (level >= 0 && level < XFS_DA_NODE_MAXDEPTH) {
     575             :                 /* Handle leaf block. */
     576   123838160 :                 if (blks[level].magic != XFS_DA_NODE_MAGIC) {
     577             :                         /* End of leaf, pop back towards the root. */
     578   123295974 :                         if (blks[level].index >= ds->maxrecs[level]) {
     579     2686729 :                                 if (level > 0)
     580      475119 :                                         blks[level - 1].index++;
     581     2686729 :                                 ds->tree_level++;
     582     2686729 :                                 level--;
     583     2686729 :                                 continue;
     584             :                         }
     585             : 
     586             :                         /* Dispatch record scrubbing. */
     587   120641175 :                         error = scrub_fn(ds, level);
     588   120646694 :                         if (error)
     589             :                                 break;
     590   120646694 :                         if (xchk_should_terminate(sc, &error) ||
     591   120621138 :                             (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT))
     592             :                                 break;
     593             : 
     594   120621138 :                         blks[level].index++;
     595   120621138 :                         continue;
     596             :                 }
     597             : 
     598             : 
     599             :                 /* End of node, pop back towards the root. */
     600      542186 :                 if (blks[level].index >= ds->maxrecs[level]) {
     601       66626 :                         if (level > 0)
     602         449 :                                 blks[level - 1].index++;
     603       66626 :                         ds->tree_level++;
     604       66626 :                         level--;
     605       66626 :                         continue;
     606             :                 }
     607             : 
     608             :                 /* Hashes in order for scrub? */
     609      475559 :                 key = xchk_da_btree_node_entry(ds, level);
     610      475552 :                 error = xchk_da_btree_hash(ds, level, &key->hashval);
     611      475555 :                 if (error)
     612           0 :                         goto out;
     613             : 
     614             :                 /* Drill another level deeper. */
     615      475555 :                 blkno = be32_to_cpu(key->before);
     616      475555 :                 level++;
     617      475555 :                 if (level >= XFS_DA_NODE_MAXDEPTH) {
     618             :                         /* Too deep! */
     619           0 :                         xchk_da_set_corrupt(ds, level - 1);
     620           0 :                         break;
     621             :                 }
     622      475555 :                 ds->tree_level--;
     623      475555 :                 error = xchk_da_btree_block(ds, level, blkno);
     624      475552 :                 if (error)
     625           0 :                         goto out;
     626      475552 :                 if (blks[level].bp == NULL)
     627           0 :                         goto out;
     628             : 
     629      475552 :                 blks[level].index = 0;
     630             :         }
     631             : 
     632     2277416 : out:
     633             :         /* Release all the buffers we're tracking. */
     634    13645924 :         for (level = 0; level < XFS_DA_NODE_MAXDEPTH; level++) {
     635    11371853 :                 if (blks[level].bp == NULL)
     636     9028270 :                         continue;
     637     2343583 :                 xfs_trans_brelse(sc->tp, blks[level].bp);
     638     2340238 :                 blks[level].bp = NULL;
     639             :         }
     640             : 
     641     2274071 : out_state:
     642     2556226 :         xfs_da_state_free(ds->state);
     643     2552839 :         kfree(ds);
     644     2555873 :         return error;
     645             : }

Generated by: LCOV version 1.14