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

Generated by: LCOV version 1.14