LCOV - code coverage report
Current view: top level - fs/xfs/scrub - dabtree.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc3-acha @ Mon Jul 31 20:08:06 PDT 2023 Lines: 231 325 71.1 %
Date: 2023-07-31 20:08:07 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     2260635 : xchk_da_process_error(
      31             :         struct xchk_da_btree    *ds,
      32             :         int                     level,
      33             :         int                     *error)
      34             : {
      35     2260635 :         struct xfs_scrub        *sc = ds->sc;
      36             : 
      37     2260635 :         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     1051994 : xchk_da_set_preen(
     108             :         struct xchk_da_btree    *ds,
     109             :         int                     level)
     110             : {
     111     1051994 :         struct xfs_scrub        *sc = ds->sc;
     112             : 
     113     1051994 :         sc->sm->sm_flags |= XFS_SCRUB_OFLAG_PREEN;
     114     1051995 :         trace_xchk_fblock_preen(sc, ds->dargs.whichfork,
     115     1051994 :                         xfs_dir2_da_to_db(ds->dargs.geo,
     116     1051994 :                                 ds->state->path.blk[level].blkno),
     117             :                         __return_address);
     118     1051999 : }
     119             : 
     120             : /* Find an entry at a certain level in a da btree. */
     121             : static struct xfs_da_node_entry *
     122    61044151 : xchk_da_btree_node_entry(
     123             :         struct xchk_da_btree            *ds,
     124             :         int                             level)
     125             : {
     126    61044151 :         struct xfs_da_state_blk         *blk = &ds->state->path.blk[level];
     127    61044151 :         struct xfs_da3_icnode_hdr       hdr;
     128             : 
     129    61044151 :         ASSERT(blk->magic == XFS_DA_NODE_MAGIC);
     130             : 
     131    61044151 :         xfs_da3_node_hdr_from_disk(ds->sc->mp, &hdr, blk->bp->b_addr);
     132    61045221 :         return hdr.btree + blk->index;
     133             : }
     134             : 
     135             : /* Scrub a da btree hash (key). */
     136             : int
     137    83926238 : xchk_da_btree_hash(
     138             :         struct xchk_da_btree            *ds,
     139             :         int                             level,
     140             :         __be32                          *hashp)
     141             : {
     142    83926238 :         struct xfs_da_node_entry        *entry;
     143    83926238 :         xfs_dahash_t                    hash;
     144    83926238 :         xfs_dahash_t                    parent_hash;
     145             : 
     146             :         /* Is this hash in order? */
     147    83926238 :         hash = be32_to_cpu(*hashp);
     148    83926238 :         if (hash < ds->hashes[level])
     149           0 :                 xchk_da_set_corrupt(ds, level);
     150    83926238 :         ds->hashes[level] = hash;
     151             : 
     152    83926238 :         if (level == 0)
     153             :                 return 0;
     154             : 
     155             :         /* Is this hash no larger than the parent hash? */
     156    60529186 :         entry = xchk_da_btree_node_entry(ds, level - 1);
     157    60529668 :         parent_hash = be32_to_cpu(entry->hashval);
     158    60529668 :         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     1822255 : xchk_da_btree_ptr_ok(
     170             :         struct xchk_da_btree    *ds,
     171             :         int                     level,
     172             :         xfs_dablk_t             blkno)
     173             : {
     174     1822255 :         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       14031 : xchk_da_btree_read_verify(
     189             :         struct xfs_buf          *bp)
     190             : {
     191       14031 :         struct xfs_da_blkinfo   *info = bp->b_addr;
     192             : 
     193       14031 :         switch (be16_to_cpu(info->magic)) {
     194          52 :         case XFS_DIR2_LEAF1_MAGIC:
     195             :         case XFS_DIR3_LEAF1_MAGIC:
     196          52 :                 bp->b_ops = &xfs_dir3_leaf1_buf_ops;
     197          52 :                 bp->b_ops->verify_read(bp);
     198          52 :                 return;
     199       13979 :         default:
     200             :                 /*
     201             :                  * xfs_da3_node_buf_ops already know how to handle
     202             :                  * DA*_NODE, ATTR*_LEAF, and DIR*_LEAFN blocks.
     203             :                  */
     204       13979 :                 bp->b_ops = &xfs_da3_node_buf_ops;
     205       13979 :                 bp->b_ops->verify_read(bp);
     206       13979 :                 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      515955 : 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      515955 :         struct xfs_da_state_path *path = &ds->state->path;
     264      515955 :         struct xfs_da_state_path *altpath = &ds->state->altpath;
     265      515955 :         int                     retval;
     266      515955 :         int                     plevel;
     267      515955 :         int                     error;
     268             : 
     269     1031910 :         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      515955 :         if (sibling == 0) {
     276       77577 :                 error = xfs_da3_path_shift(ds->state, altpath, direction,
     277             :                                 false, &retval);
     278       77576 :                 if (error == 0 && retval == 0)
     279           0 :                         xchk_da_set_corrupt(ds, level);
     280       77576 :                 error = 0;
     281       77576 :                 goto out;
     282             :         }
     283             : 
     284             :         /* Move the alternate cursor one block in the direction given. */
     285      438378 :         error = xfs_da3_path_shift(ds->state, altpath, direction, false,
     286             :                         &retval);
     287      438377 :         if (!xchk_da_process_error(ds, level, &error))
     288           0 :                 goto out;
     289      438378 :         if (retval) {
     290           0 :                 xchk_da_set_corrupt(ds, level);
     291           0 :                 goto out;
     292             :         }
     293      438378 :         if (altpath->blk[level].bp)
     294      438378 :                 xchk_buffer_recheck(ds->sc, altpath->blk[level].bp);
     295             : 
     296             :         /* Compare upper level pointer to sibling pointer. */
     297      438378 :         if (altpath->blk[level].blkno != sibling)
     298           0 :                 xchk_da_set_corrupt(ds, level);
     299             : 
     300      438378 : out:
     301             :         /* Free all buffers in the altpath that aren't referenced from path. */
     302     1572889 :         for (plevel = 0; plevel < altpath->active; plevel++) {
     303     1056934 :                 if (altpath->blk[plevel].bp == NULL ||
     304     1056934 :                     (plevel < path->active &&
     305     1056934 :                      altpath->blk[plevel].bp == path->blk[plevel].bp))
     306      618492 :                         continue;
     307             : 
     308      438442 :                 xfs_trans_brelse(ds->dargs.trans, altpath->blk[plevel].bp);
     309      438443 :                 altpath->blk[plevel].bp = NULL;
     310             :         }
     311             : 
     312      515955 :         return error;
     313             : }
     314             : 
     315             : /* Check a block's sibling pointers. */
     316             : STATIC int
     317     1551465 : xchk_da_btree_block_check_siblings(
     318             :         struct xchk_da_btree    *ds,
     319             :         int                     level,
     320             :         struct xfs_da_blkinfo   *hdr)
     321             : {
     322     1551465 :         xfs_dablk_t             forw;
     323     1551465 :         xfs_dablk_t             back;
     324     1551465 :         int                     error = 0;
     325             : 
     326     1551465 :         forw = be32_to_cpu(hdr->forw);
     327     1551465 :         back = be32_to_cpu(hdr->back);
     328             : 
     329             :         /* Top level blocks should not have sibling pointers. */
     330     1551465 :         if (level == 0) {
     331     1293488 :                 if (forw != 0 || back != 0)
     332           0 :                         xchk_da_set_corrupt(ds, level);
     333     1293488 :                 return 0;
     334             :         }
     335             : 
     336             :         /*
     337             :          * Check back (left) and forw (right) pointers.  These functions
     338             :          * absorb error codes for us.
     339             :          */
     340      257977 :         error = xchk_da_btree_block_check_sibling(ds, level, 0, back);
     341      257978 :         if (error)
     342           0 :                 goto out;
     343      257978 :         error = xchk_da_btree_block_check_sibling(ds, level, 1, forw);
     344             : 
     345      257978 : out:
     346      257978 :         memset(&ds->state->altpath, 0, sizeof(ds->state->altpath));
     347      257978 :         return error;
     348             : }
     349             : 
     350             : /* Load a dir/attribute block from a btree. */
     351             : STATIC int
     352     1822260 : xchk_da_btree_block(
     353             :         struct xchk_da_btree            *ds,
     354             :         int                             level,
     355             :         xfs_dablk_t                     blkno)
     356             : {
     357     1822260 :         struct xfs_da_state_blk         *blk;
     358     1822260 :         struct xfs_da_intnode           *node;
     359     1822260 :         struct xfs_da_node_entry        *btree;
     360     1822260 :         struct xfs_da3_blkinfo          *hdr3;
     361     1822260 :         struct xfs_da_args              *dargs = &ds->dargs;
     362     1822260 :         struct xfs_inode                *ip = ds->dargs.dp;
     363     1822260 :         xfs_failaddr_t                  fa;
     364     1822260 :         xfs_ino_t                       owner;
     365     1822260 :         int                             *pmaxrecs;
     366     1822260 :         struct xfs_da3_icnode_hdr       nodehdr;
     367     1822260 :         int                             error = 0;
     368             : 
     369     1822260 :         blk = &ds->state->path.blk[level];
     370     1822260 :         ds->state->path.active = level + 1;
     371             : 
     372             :         /* Release old block. */
     373     1822260 :         if (blk->bp) {
     374      219189 :                 xfs_trans_brelse(dargs->trans, blk->bp);
     375      219189 :                 blk->bp = NULL;
     376             :         }
     377             : 
     378             :         /* Check the pointer. */
     379     1822260 :         blk->blkno = blkno;
     380     1822260 :         if (!xchk_da_btree_ptr_ok(ds, level, blkno))
     381           0 :                 goto out_nobuf;
     382             : 
     383             :         /* Read the buffer. */
     384     1822255 :         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     1822265 :         if (!xchk_da_process_error(ds, level, &error))
     388           0 :                 goto out_nobuf;
     389     1822268 :         if (blk->bp)
     390     1551515 :                 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     1822211 :         if (ds->dargs.whichfork == XFS_DATA_FORK && level == 0 &&
     398      293622 :                         blk->bp == NULL)
     399      270753 :                 goto out_nobuf;
     400             : 
     401             :         /* It's /not/ ok for attr trees not to have a da btree. */
     402     1551458 :         if (blk->bp == NULL) {
     403           0 :                 xchk_da_set_corrupt(ds, level);
     404           0 :                 goto out_nobuf;
     405             :         }
     406             : 
     407     1551458 :         hdr3 = blk->bp->b_addr;
     408     1551458 :         blk->magic = be16_to_cpu(hdr3->hdr.magic);
     409     1551458 :         pmaxrecs = &ds->maxrecs[level];
     410             : 
     411             :         /* We only started zeroing the header on v5 filesystems. */
     412     1551458 :         if (xfs_has_crc(ds->sc->mp) && hdr3->hdr.pad)
     413           0 :                 xchk_da_set_corrupt(ds, level);
     414             : 
     415             :         /* Check the owner. */
     416     1551458 :         if (xfs_has_crc(ip->i_mount)) {
     417     1551467 :                 owner = be64_to_cpu(hdr3->owner);
     418     1551467 :                 if (owner != ip->i_ino)
     419           0 :                         xchk_da_set_corrupt(ds, level);
     420             :         }
     421             : 
     422             :         /* Check the siblings. */
     423     1551458 :         error = xchk_da_btree_block_check_siblings(ds, level, &hdr3->hdr);
     424     1551455 :         if (error)
     425           0 :                 goto out;
     426             : 
     427             :         /* Interpret the buffer. */
     428     1551455 :         switch (blk->magic) {
     429     1319932 :         case XFS_ATTR_LEAF_MAGIC:
     430             :         case XFS_ATTR3_LEAF_MAGIC:
     431     1319932 :                 xfs_trans_buf_set_type(dargs->trans, blk->bp,
     432             :                                 XFS_BLFT_ATTR_LEAF_BUF);
     433     1319948 :                 blk->magic = XFS_ATTR_LEAF_MAGIC;
     434     1319948 :                 blk->hashval = xfs_attr_leaf_lasthash(blk->bp, pmaxrecs);
     435     1319944 :                 if (ds->tree_level != 0)
     436           0 :                         xchk_da_set_corrupt(ds, level);
     437             :                 break;
     438      186458 :         case XFS_DIR2_LEAFN_MAGIC:
     439             :         case XFS_DIR3_LEAFN_MAGIC:
     440      186458 :                 xfs_trans_buf_set_type(dargs->trans, blk->bp,
     441             :                                 XFS_BLFT_DIR_LEAFN_BUF);
     442      186458 :                 blk->magic = XFS_DIR2_LEAFN_MAGIC;
     443      186458 :                 blk->hashval = xfs_dir2_leaf_lasthash(ip, blk->bp, pmaxrecs);
     444      186458 :                 if (ds->tree_level != 0)
     445           0 :                         xchk_da_set_corrupt(ds, level);
     446             :                 break;
     447        6244 :         case XFS_DIR2_LEAF1_MAGIC:
     448             :         case XFS_DIR3_LEAF1_MAGIC:
     449        6244 :                 xfs_trans_buf_set_type(dargs->trans, blk->bp,
     450             :                                 XFS_BLFT_DIR_LEAF1_BUF);
     451        6244 :                 blk->magic = XFS_DIR2_LEAF1_MAGIC;
     452        6244 :                 blk->hashval = xfs_dir2_leaf_lasthash(ip, blk->bp, pmaxrecs);
     453        6244 :                 if (ds->tree_level != 0)
     454           0 :                         xchk_da_set_corrupt(ds, level);
     455             :                 break;
     456       38821 :         case XFS_DA_NODE_MAGIC:
     457             :         case XFS_DA3_NODE_MAGIC:
     458       38821 :                 xfs_trans_buf_set_type(dargs->trans, blk->bp,
     459             :                                 XFS_BLFT_DA_NODE_BUF);
     460       38821 :                 blk->magic = XFS_DA_NODE_MAGIC;
     461       38821 :                 node = blk->bp->b_addr;
     462       38821 :                 xfs_da3_node_hdr_from_disk(ip->i_mount, &nodehdr, node);
     463       38821 :                 btree = nodehdr.btree;
     464       38821 :                 *pmaxrecs = nodehdr.count;
     465       38821 :                 blk->hashval = be32_to_cpu(btree[*pmaxrecs - 1].hashval);
     466       38821 :                 if (level == 0) {
     467       38784 :                         if (nodehdr.level >= XFS_DA_NODE_MAXDEPTH) {
     468           0 :                                 xchk_da_set_corrupt(ds, level);
     469           0 :                                 goto out_freebp;
     470             :                         }
     471       38784 :                         ds->tree_level = nodehdr.level;
     472             :                 } else {
     473          37 :                         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     1551467 :         fa = xfs_da3_header_check(blk->bp, dargs->owner);
     487     1551494 :         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     1551494 :         if (level > 0) {
     497      257978 :                 struct xfs_da_node_entry        *key;
     498             : 
     499      257978 :                 key = xchk_da_btree_node_entry(ds, level - 1);
     500      515956 :                 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     1551494 : out:
     507             :         return error;
     508           0 : out_freebp:
     509           0 :         xfs_trans_brelse(dargs->trans, blk->bp);
     510           0 :         blk->bp = NULL;
     511      270753 : out_nobuf:
     512      270753 :         blk->blkno = 0;
     513      270753 :         return error;
     514             : }
     515             : 
     516             : /* Visit all nodes and leaves of a da btree. */
     517             : int
     518    15574498 : xchk_da_btree(
     519             :         struct xfs_scrub                *sc,
     520             :         int                             whichfork,
     521             :         xchk_da_btree_rec_fn            scrub_fn,
     522             :         void                            *private)
     523             : {
     524    15574498 :         struct xchk_da_btree            *ds;
     525    15574498 :         struct xfs_mount                *mp = sc->mp;
     526    15574498 :         struct xfs_da_state_blk         *blks;
     527    15574498 :         struct xfs_da_node_entry        *key;
     528    15574498 :         xfs_dablk_t                     blkno;
     529    15574498 :         int                             level;
     530    15574498 :         int                             error;
     531             : 
     532             :         /* Skip short format data structures; no btree to scan. */
     533    15574498 :         if (!xfs_ifork_has_extents(xfs_ifork_ptr(sc->ip, whichfork)))
     534             :                 return 0;
     535             : 
     536             :         /* Set up initial da state. */
     537     1564293 :         ds = kzalloc(sizeof(struct xchk_da_btree), XCHK_GFP_FLAGS);
     538     1564290 :         if (!ds)
     539             :                 return -ENOMEM;
     540     1564290 :         ds->dargs.dp = sc->ip;
     541     1564290 :         ds->dargs.whichfork = whichfork;
     542     1564290 :         ds->dargs.trans = sc->tp;
     543     1564290 :         ds->dargs.op_flags = XFS_DA_OP_OKNOENT;
     544     1564290 :         ds->dargs.owner = sc->ip->i_ino;
     545     1564290 :         ds->state = xfs_da_state_alloc(&ds->dargs);
     546     1564290 :         ds->sc = sc;
     547     1564290 :         ds->private = private;
     548     1564290 :         if (whichfork == XFS_ATTR_FORK) {
     549     1270668 :                 ds->dargs.geo = mp->m_attr_geo;
     550     1270668 :                 ds->lowest = 0;
     551     1270668 :                 ds->highest = 0;
     552             :         } else {
     553      293622 :                 ds->dargs.geo = mp->m_dir_geo;
     554      293622 :                 ds->lowest = ds->dargs.geo->leafblk;
     555      293622 :                 ds->highest = ds->dargs.geo->freeblk;
     556             :         }
     557     1564290 :         blkno = ds->lowest;
     558     1564290 :         level = 0;
     559             : 
     560             :         /* Find the root of the da tree, if present. */
     561     1564290 :         blks = ds->state->path.blk;
     562     1564290 :         error = xchk_da_btree_block(ds, level, blkno);
     563     1564257 :         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     1564257 :         if (blks[level].bp == NULL)
     571      270753 :                 goto out_state;
     572             : 
     573     1293504 :         blks[level].index = 0;
     574    86771064 :         while (level >= 0 && level < XFS_DA_NODE_MAXDEPTH) {
     575             :                 /* Handle leaf block. */
     576    85477564 :                 if (blks[level].magic != XFS_DA_NODE_MAGIC) {
     577             :                         /* End of leaf, pop back towards the root. */
     578    85180769 :                         if (blks[level].index >= ds->maxrecs[level]) {
     579     1512652 :                                 if (level > 0)
     580      257940 :                                         blks[level - 1].index++;
     581     1512652 :                                 ds->tree_level++;
     582     1512652 :                                 level--;
     583     1512652 :                                 continue;
     584             :                         }
     585             : 
     586             :                         /* Dispatch record scrubbing. */
     587    83668117 :                         error = scrub_fn(ds, level);
     588    83666175 :                         if (error)
     589             :                                 break;
     590    83666175 :                         if (xchk_should_terminate(sc, &error) ||
     591    83668110 :                             (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT))
     592             :                                 break;
     593             : 
     594    83668110 :                         blks[level].index++;
     595    83668110 :                         continue;
     596             :                 }
     597             : 
     598             : 
     599             :                 /* End of node, pop back towards the root. */
     600      296795 :                 if (blks[level].index >= ds->maxrecs[level]) {
     601       38820 :                         if (level > 0)
     602          37 :                                 blks[level - 1].index++;
     603       38820 :                         ds->tree_level++;
     604       38820 :                         level--;
     605       38820 :                         continue;
     606             :                 }
     607             : 
     608             :                 /* Hashes in order for scrub? */
     609      257975 :                 key = xchk_da_btree_node_entry(ds, level);
     610      257977 :                 error = xchk_da_btree_hash(ds, level, &key->hashval);
     611      257978 :                 if (error)
     612           0 :                         goto out;
     613             : 
     614             :                 /* Drill another level deeper. */
     615      257978 :                 blkno = be32_to_cpu(key->before);
     616      257978 :                 level++;
     617      257978 :                 if (level >= XFS_DA_NODE_MAXDEPTH) {
     618             :                         /* Too deep! */
     619           0 :                         xchk_da_set_corrupt(ds, level - 1);
     620           0 :                         break;
     621             :                 }
     622      257978 :                 ds->tree_level--;
     623      257978 :                 error = xchk_da_btree_block(ds, level, blkno);
     624      257978 :                 if (error)
     625           0 :                         goto out;
     626      257978 :                 if (blks[level].bp == NULL)
     627           0 :                         goto out;
     628             : 
     629      257978 :                 blks[level].index = 0;
     630             :         }
     631             : 
     632     1293501 : out:
     633             :         /* Release all the buffers we're tracking. */
     634     7761209 :         for (level = 0; level < XFS_DA_NODE_MAXDEPTH; level++) {
     635     6467666 :                 if (blks[level].bp == NULL)
     636     5135375 :                         continue;
     637     1332291 :                 xfs_trans_brelse(sc->tp, blks[level].bp);
     638     1332333 :                 blks[level].bp = NULL;
     639             :         }
     640             : 
     641     1293543 : out_state:
     642     1564296 :         xfs_da_state_free(ds->state);
     643     1564296 :         kfree(ds);
     644     1564296 :         return error;
     645             : }

Generated by: LCOV version 1.14