LCOV - code coverage report
Current view: top level - fs/xfs/scrub - dir.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc3-achx @ Mon Jul 31 20:08:12 PDT 2023 Lines: 409 569 71.9 %
Date: 2023-07-31 20:08:12 Functions: 16 18 88.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_icache.h"
      16             : #include "xfs_dir2.h"
      17             : #include "xfs_dir2_priv.h"
      18             : #include "xfs_attr.h"
      19             : #include "xfs_parent.h"
      20             : #include "scrub/scrub.h"
      21             : #include "scrub/common.h"
      22             : #include "scrub/dabtree.h"
      23             : #include "scrub/readdir.h"
      24             : #include "scrub/repair.h"
      25             : #include "scrub/trace.h"
      26             : #include "scrub/xfile.h"
      27             : #include "scrub/xfarray.h"
      28             : #include "scrub/xfblob.h"
      29             : 
      30             : /* Set us up to scrub directories. */
      31             : int
      32    23116152 : xchk_setup_directory(
      33             :         struct xfs_scrub        *sc)
      34             : {
      35    23116152 :         int                     error;
      36             : 
      37    46232304 :         if (xchk_could_repair(sc)) {
      38      584906 :                 error = xrep_setup_directory(sc);
      39      584818 :                 if (error)
      40             :                         return error;
      41             :         }
      42             : 
      43    23115619 :         return xchk_setup_inode_contents(sc, 0);
      44             : }
      45             : 
      46             : /* Directories */
      47             : 
      48             : /* Deferred directory entry that we saved for later. */
      49             : struct xchk_dirent {
      50             :         /* Cookie for retrieval of the dirent name. */
      51             :         xfblob_cookie                   name_cookie;
      52             : 
      53             :         /* Child inode number. */
      54             :         xfs_ino_t                       ino;
      55             : 
      56             :         /* Length of the pptr name. */
      57             :         uint8_t                         namelen;
      58             : };
      59             : 
      60             : struct xchk_dir {
      61             :         struct xfs_scrub        *sc;
      62             : 
      63             :         /* Scratch buffer for scanning pptr xattrs */
      64             :         struct xfs_parent_name_irec pptr;
      65             : 
      66             :         /* xattr key and da args for parent pointer validation. */
      67             :         struct xfs_parent_scratch pptr_scratch;
      68             : 
      69             :         /* Fixed-size array of xchk_dirent structures. */
      70             :         struct xfarray          *dir_entries;
      71             : 
      72             :         /* Blobs containing dirent names. */
      73             :         struct xfblob           *dir_names;
      74             : 
      75             :         /* If we've cycled the ILOCK, we must revalidate deferred dirents. */
      76             :         bool                    need_revalidate;
      77             : 
      78             :         /* Name buffer for dirent revalidation. */
      79             :         uint8_t                 namebuf[MAXNAMELEN];
      80             : 
      81             : };
      82             : 
      83             : /* Scrub a directory entry. */
      84             : 
      85             : /* Check that an inode's mode matches a given XFS_DIR3_FT_* type. */
      86             : STATIC void
      87   232369782 : xchk_dir_check_ftype(
      88             :         struct xfs_scrub        *sc,
      89             :         xfs_fileoff_t           offset,
      90             :         struct xfs_inode        *ip,
      91             :         int                     ftype)
      92             : {
      93   232369782 :         struct xfs_mount        *mp = sc->mp;
      94             : 
      95   232369782 :         if (!xfs_has_ftype(mp)) {
      96           0 :                 if (ftype != XFS_DIR3_FT_UNKNOWN && ftype != XFS_DIR3_FT_DIR)
      97           0 :                         xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);
      98           0 :                 return;
      99             :         }
     100             : 
     101   232369782 :         if (xfs_mode_to_ftype(VFS_I(ip)->i_mode) != ftype)
     102           0 :                 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);
     103             : }
     104             : 
     105             : /*
     106             :  * Try to lock a child file for checking parent pointers.  Returns the inode
     107             :  * flags for the locks we now hold, or zero if we failed.
     108             :  */
     109             : STATIC unsigned int
     110   180352392 : xchk_dir_lock_child(
     111             :         struct xfs_scrub        *sc,
     112             :         struct xfs_inode        *ip)
     113             : {
     114   180352392 :         if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED))
     115             :                 return 0;
     116             : 
     117   179743261 :         if (!xfs_ilock_nowait(ip, XFS_ILOCK_SHARED)) {
     118         929 :                 xfs_iunlock(ip, XFS_IOLOCK_SHARED);
     119         929 :                 return 0;
     120             :         }
     121             : 
     122   359868788 :         if (!xfs_inode_has_attr_fork(ip) || !xfs_need_iread_extents(&ip->i_af))
     123   179926863 :                 return XFS_IOLOCK_SHARED | XFS_ILOCK_SHARED;
     124             : 
     125         117 :         xfs_iunlock(ip, XFS_ILOCK_SHARED);
     126             : 
     127         117 :         if (!xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) {
     128           0 :                 xfs_iunlock(ip, XFS_IOLOCK_SHARED);
     129           0 :                 return 0;
     130             :         }
     131             : 
     132             :         return XFS_IOLOCK_SHARED | XFS_ILOCK_EXCL;
     133             : }
     134             : 
     135             : /* Check the backwards link (parent pointer) associated with this dirent. */
     136             : STATIC int
     137   179841133 : xchk_dir_parent_pointer(
     138             :         struct xchk_dir         *sd,
     139             :         const struct xfs_name   *name,
     140             :         struct xfs_inode        *ip)
     141             : {
     142   179841133 :         struct xfs_scrub        *sc = sd->sc;
     143   179841133 :         int                     error;
     144             : 
     145   179841133 :         sd->pptr.p_ino = sc->ip->i_ino;
     146   179841133 :         sd->pptr.p_gen = VFS_I(sc->ip)->i_generation;
     147   179841133 :         sd->pptr.p_namelen = name->len;
     148   359682266 :         memcpy(sd->pptr.p_name, name->name, name->len);
     149   179841133 :         xfs_parent_irec_hashname(sc->mp, &sd->pptr);
     150             : 
     151   179754155 :         error = xfs_parent_lookup(sc->tp, ip, &sd->pptr, &sd->pptr_scratch);
     152   179830333 :         if (error == -ENOATTR)
     153           0 :                 xchk_fblock_xref_set_corrupt(sc, XFS_DATA_FORK, 0);
     154             : 
     155   179830333 :         return 0;
     156             : }
     157             : 
     158             : /* Look for a parent pointer matching this dirent, if the child isn't busy. */
     159             : STATIC int
     160   225272440 : xchk_dir_check_pptr_fast(
     161             :         struct xchk_dir         *sd,
     162             :         xfs_dir2_dataptr_t      dapos,
     163             :         const struct xfs_name   *name,
     164             :         struct xfs_inode        *ip)
     165             : {
     166   225272440 :         struct xfs_scrub        *sc = sd->sc;
     167   225272440 :         unsigned int            lockmode;
     168   225272440 :         int                     error;
     169             : 
     170             :         /* dot and dotdot entries do not have parent pointers */
     171   428094132 :         if (xfs_dir2_samename(name, &xfs_name_dot) ||
     172   202836314 :             xfs_dir2_samename(name, &xfs_name_dotdot))
     173    44900595 :                 return 0;
     174             : 
     175             :         /* Try to lock the inode. */
     176   180354797 :         lockmode = xchk_dir_lock_child(sc, ip);
     177   180390600 :         if (!lockmode) {
     178      525897 :                 struct xchk_dirent      save_de = {
     179      525897 :                         .namelen        = name->len,
     180      525897 :                         .ino            = ip->i_ino,
     181             :                 };
     182             : 
     183             :                 /* Couldn't lock the inode, so save the dirent for later. */
     184      525897 :                 trace_xchk_dir_defer(sc->ip, name->name, name->len, ip->i_ino);
     185             : 
     186     1051788 :                 error = xfblob_store(sd->dir_names, &save_de.name_cookie,
     187      525892 :                                 name->name, name->len);
     188      525896 :                 if (xchk_fblock_xref_process_error(sc, XFS_DATA_FORK, 0,
     189             :                                         &error))
     190      525897 :                         return error;
     191             : 
     192           0 :                 error = xfarray_append(sd->dir_entries, &save_de);
     193           0 :                 if (xchk_fblock_xref_process_error(sc, XFS_DATA_FORK, 0,
     194             :                                         &error))
     195           0 :                         return error;
     196             : 
     197             :                 return 0;
     198             :         }
     199             : 
     200   179864703 :         error = xchk_dir_parent_pointer(sd, name, ip);
     201   179866551 :         xfs_iunlock(ip, lockmode);
     202   179593724 :         return error;
     203             : }
     204             : 
     205             : /*
     206             :  * Scrub a single directory entry.
     207             :  *
     208             :  * Check the inode number to make sure it's sane, then we check that we can
     209             :  * look up this filename.  Finally, we check the ftype.
     210             :  */
     211             : STATIC int
     212   232255779 : xchk_dir_actor(
     213             :         struct xfs_scrub        *sc,
     214             :         struct xfs_inode        *dp,
     215             :         xfs_dir2_dataptr_t      dapos,
     216             :         const struct xfs_name   *name,
     217             :         xfs_ino_t               ino,
     218             :         void                    *priv)
     219             : {
     220   232255779 :         struct xfs_mount        *mp = dp->i_mount;
     221   232255779 :         struct xfs_inode        *ip;
     222   232255779 :         struct xchk_dir         *sd = priv;
     223   232255779 :         xfs_ino_t               lookup_ino;
     224   232255779 :         xfs_dablk_t             offset;
     225   232255779 :         int                     error = 0;
     226             : 
     227   232255779 :         offset = xfs_dir2_db_to_da(mp->m_dir_geo,
     228             :                         xfs_dir2_dataptr_to_db(mp->m_dir_geo, dapos));
     229             : 
     230   232175345 :         if (xchk_should_terminate(sc, &error))
     231           4 :                 return error;
     232             : 
     233             :         /* Does this inode number make sense? */
     234   232275173 :         if (!xfs_verify_dir_ino(mp, ino)) {
     235           0 :                 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);
     236           0 :                 return -ECANCELED;
     237             :         }
     238             : 
     239             :         /* Does this name make sense? */
     240   232128570 :         if (!xfs_dir2_namecheck(name->name, name->len)) {
     241          11 :                 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);
     242          11 :                 return -ECANCELED;
     243             :         }
     244             : 
     245   232063094 :         if (xfs_dir2_samename(name, &xfs_name_dot)) {
     246             :                 /* If this is "." then check that the inum matches the dir. */
     247    23105556 :                 if (ino != dp->i_ino)
     248           0 :                         xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);
     249   208977487 :         } else if (xfs_dir2_samename(name, &xfs_name_dotdot)) {
     250             :                 /*
     251             :                  * If this is ".." in the root inode, check that the inum
     252             :                  * matches this dir.
     253             :                  */
     254    23097946 :                 if (dp->i_ino == mp->m_sb.sb_rootino && ino != dp->i_ino)
     255           0 :                         xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);
     256             :         }
     257             : 
     258             :         /* Verify that we can look up this name by hash. */
     259   232013792 :         error = xchk_dir_lookup(sc, dp, name, &lookup_ino);
     260             :         /* ENOENT means the hash lookup failed and the dir is corrupt */
     261   232321080 :         if (error == -ENOENT)
     262           0 :                 error = -EFSCORRUPTED;
     263   232321080 :         if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, offset, &error))
     264           0 :                 goto out;
     265   232200930 :         if (lookup_ino != ino) {
     266           0 :                 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);
     267           0 :                 return -ECANCELED;
     268             :         }
     269             : 
     270             :         /*
     271             :          * Grab the inode pointed to by the dirent.  We release the inode
     272             :          * before we cancel the scrub transaction.
     273             :          *
     274             :          * If _iget returns -EINVAL or -ENOENT then the child inode number is
     275             :          * garbage and the directory is corrupt.  If the _iget returns
     276             :          * -EFSCORRUPTED or -EFSBADCRC then the child is corrupt which is a
     277             :          *  cross referencing error.  Any other error is an operational error.
     278             :          */
     279   232200930 :         error = xchk_iget(sc, ino, &ip);
     280   232462940 :         if (error == -EINVAL || error == -ENOENT) {
     281           0 :                 error = -EFSCORRUPTED;
     282           0 :                 xchk_fblock_process_error(sc, XFS_DATA_FORK, 0, &error);
     283           0 :                 goto out;
     284             :         }
     285   232462940 :         if (!xchk_fblock_xref_process_error(sc, XFS_DATA_FORK, offset, &error))
     286           0 :                 goto out;
     287             : 
     288   232384073 :         xchk_dir_check_ftype(sc, offset, ip, name->type);
     289             : 
     290   232242315 :         if (xfs_has_parent(mp)) {
     291   225232669 :                 error = xchk_dir_check_pptr_fast(sd, dapos, name, ip);
     292   225043021 :                 if (error)
     293             :                         goto out_rele;
     294             :         }
     295             : 
     296   232052667 : out_rele:
     297   232052667 :         xchk_irele(sc, ip);
     298   232398264 : out:
     299   232398264 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     300             :                 return -ECANCELED;
     301   232398264 :         return error;
     302             : }
     303             : 
     304             : /* Scrub a directory btree record. */
     305             : STATIC int
     306    98793744 : xchk_dir_rec(
     307             :         struct xchk_da_btree            *ds,
     308             :         int                             level)
     309             : {
     310    98793744 :         struct xfs_name                 dname = { };
     311    98793744 :         struct xfs_da_state_blk         *blk = &ds->state->path.blk[level];
     312    98788056 :         struct xfs_mount                *mp = ds->state->mp;
     313    98788056 :         struct xfs_inode                *dp = ds->dargs.dp;
     314    98788056 :         struct xfs_da_geometry          *geo = mp->m_dir_geo;
     315    98788056 :         struct xfs_dir2_data_entry      *dent;
     316    98788056 :         struct xfs_buf                  *bp;
     317    98788056 :         struct xfs_dir2_leaf_entry      *ent;
     318    98788056 :         unsigned int                    end;
     319    98788056 :         unsigned int                    iter_off;
     320    98788056 :         xfs_ino_t                       ino;
     321    98788056 :         xfs_dablk_t                     rec_bno;
     322    98788056 :         xfs_dir2_db_t                   db;
     323    98788056 :         xfs_dir2_data_aoff_t            off;
     324    98788056 :         xfs_dir2_dataptr_t              ptr;
     325    98788056 :         xfs_dahash_t                    calc_hash;
     326    98788056 :         xfs_dahash_t                    hash;
     327    98788056 :         struct xfs_dir3_icleaf_hdr      hdr;
     328    98788056 :         unsigned int                    tag;
     329    98788056 :         int                             error;
     330             : 
     331    98788056 :         ASSERT(blk->magic == XFS_DIR2_LEAF1_MAGIC ||
     332             :                blk->magic == XFS_DIR2_LEAFN_MAGIC);
     333             : 
     334    98788056 :         xfs_dir2_leaf_hdr_from_disk(mp, &hdr, blk->bp->b_addr);
     335    98757418 :         ent = hdr.ents + blk->index;
     336             : 
     337             :         /* Check the hash of the entry. */
     338    98757418 :         error = xchk_da_btree_hash(ds, level, &ent->hashval);
     339    98757877 :         if (error)
     340           0 :                 goto out;
     341             : 
     342             :         /* Valid hash pointer? */
     343    98757877 :         ptr = be32_to_cpu(ent->address);
     344    98757877 :         if (ptr == 0)
     345             :                 return 0;
     346             : 
     347             :         /* Find the directory entry's location. */
     348    87566808 :         db = xfs_dir2_dataptr_to_db(geo, ptr);
     349    87541038 :         off = xfs_dir2_dataptr_to_off(geo, ptr);
     350    87541038 :         rec_bno = xfs_dir2_db_to_da(geo, db);
     351             : 
     352    87537542 :         if (rec_bno >= geo->leafblk) {
     353           0 :                 xchk_da_set_corrupt(ds, level);
     354           0 :                 goto out;
     355             :         }
     356    87537542 :         error = xfs_dir3_data_read(ds->dargs.trans, dp, ds->dargs.owner,
     357             :                         rec_bno, XFS_DABUF_MAP_HOLE_OK, &bp);
     358    87428005 :         if (!xchk_fblock_process_error(ds->sc, XFS_DATA_FORK, rec_bno,
     359             :                         &error))
     360           0 :                 goto out;
     361    87412074 :         if (!bp) {
     362           0 :                 xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno);
     363           0 :                 goto out;
     364             :         }
     365    87412074 :         xchk_buffer_recheck(ds->sc, bp);
     366             : 
     367    87565996 :         if (ds->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     368           0 :                 goto out_relse;
     369             : 
     370    87565996 :         dent = bp->b_addr + off;
     371             : 
     372             :         /* Make sure we got a real directory entry. */
     373    87565996 :         iter_off = geo->data_entry_offset;
     374    87565996 :         end = xfs_dir3_data_end_offset(geo, bp->b_addr);
     375    87614976 :         if (!end) {
     376           0 :                 xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno);
     377           0 :                 goto out_relse;
     378             :         }
     379  9061805555 :         for (;;) {
     380  9061805555 :                 struct xfs_dir2_data_entry      *dep = bp->b_addr + iter_off;
     381  9061805555 :                 struct xfs_dir2_data_unused     *dup = bp->b_addr + iter_off;
     382             : 
     383  9061805555 :                 if (iter_off >= end) {
     384           0 :                         xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno);
     385           0 :                         goto out_relse;
     386             :                 }
     387             : 
     388  9061805555 :                 if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
     389   314187883 :                         iter_off += be16_to_cpu(dup->length);
     390   314187883 :                         continue;
     391             :                 }
     392  8747617672 :                 if (dep == dent)
     393             :                         break;
     394 17318100855 :                 iter_off += xfs_dir2_data_entsize(mp, dep->namelen);
     395             :         }
     396             : 
     397             :         /* Retrieve the entry, sanity check it, and compare hashes. */
     398    87614976 :         ino = be64_to_cpu(dent->inumber);
     399    87614976 :         hash = be32_to_cpu(ent->hashval);
     400    87614976 :         tag = be16_to_cpup(xfs_dir2_data_entry_tag_p(mp, dent));
     401    87597283 :         if (!xfs_verify_dir_ino(mp, ino) || tag != off)
     402           8 :                 xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno);
     403    87582947 :         if (dent->namelen == 0) {
     404           0 :                 xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno);
     405           0 :                 goto out_relse;
     406             :         }
     407             : 
     408             :         /* Does the directory hash match? */
     409    87582947 :         dname.name = dent->name;
     410    87582947 :         dname.len = dent->namelen;
     411    87582947 :         calc_hash = xfs_dir2_hashname(mp, &dname);
     412    87582974 :         if (calc_hash != hash)
     413           0 :                 xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno);
     414             : 
     415    87582974 : out_relse:
     416    87582974 :         xfs_trans_brelse(ds->dargs.trans, bp);
     417    87588461 : out:
     418    87588461 :         return error;
     419             : }
     420             : 
     421             : /*
     422             :  * Is this unused entry either in the bestfree or smaller than all of
     423             :  * them?  We've already checked that the bestfrees are sorted longest to
     424             :  * shortest, and that there aren't any bogus entries.
     425             :  */
     426             : STATIC void
     427     6495181 : xchk_directory_check_free_entry(
     428             :         struct xfs_scrub                *sc,
     429             :         xfs_dablk_t                     lblk,
     430             :         struct xfs_dir2_data_free       *bf,
     431             :         struct xfs_dir2_data_unused     *dup)
     432             : {
     433     6495181 :         struct xfs_dir2_data_free       *dfp;
     434     6495181 :         unsigned int                    dup_length;
     435             : 
     436     6495181 :         dup_length = be16_to_cpu(dup->length);
     437             : 
     438             :         /* Unused entry is shorter than any of the bestfrees */
     439     6495181 :         if (dup_length < be16_to_cpu(bf[XFS_DIR2_DATA_FD_COUNT - 1].length))
     440             :                 return;
     441             : 
     442     5785310 :         for (dfp = &bf[XFS_DIR2_DATA_FD_COUNT - 1]; dfp >= bf; dfp--)
     443     5785310 :                 if (dup_length == be16_to_cpu(dfp->length))
     444             :                         return;
     445             : 
     446             :         /* Unused entry should be in the bestfrees but wasn't found. */
     447           0 :         xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
     448             : }
     449             : 
     450             : /* Check free space info in a directory data block. */
     451             : STATIC int
     452      940617 : xchk_directory_data_bestfree(
     453             :         struct xfs_scrub                *sc,
     454             :         xfs_dablk_t                     lblk,
     455             :         bool                            is_block)
     456             : {
     457      940617 :         struct xfs_dir2_data_unused     *dup;
     458      940617 :         struct xfs_dir2_data_free       *dfp;
     459      940617 :         struct xfs_buf                  *bp;
     460      940617 :         struct xfs_dir2_data_free       *bf;
     461      940617 :         struct xfs_mount                *mp = sc->mp;
     462      940617 :         u16                             tag;
     463      940617 :         unsigned int                    nr_bestfrees = 0;
     464      940617 :         unsigned int                    nr_frees = 0;
     465      940617 :         unsigned int                    smallest_bestfree;
     466      940617 :         int                             newlen;
     467      940617 :         unsigned int                    offset;
     468      940617 :         unsigned int                    end;
     469      940617 :         int                             error;
     470             : 
     471      940617 :         if (is_block) {
     472             :                 /* dir block format */
     473      364418 :                 if (lblk != XFS_B_TO_FSBT(mp, XFS_DIR2_DATA_OFFSET))
     474           0 :                         xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
     475      364418 :                 error = xfs_dir3_block_read(sc->tp, sc->ip, sc->ip->i_ino, &bp);
     476             :         } else {
     477             :                 /* dir data format */
     478      576199 :                 error = xfs_dir3_data_read(sc->tp, sc->ip, sc->ip->i_ino, lblk,
     479             :                                 0, &bp);
     480             :         }
     481      940664 :         if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk, &error))
     482           0 :                 goto out;
     483      940651 :         xchk_buffer_recheck(sc, bp);
     484             : 
     485             :         /* XXX: Check xfs_dir3_data_hdr.pad is zero once we start setting it. */
     486             : 
     487      940661 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     488           0 :                 goto out_buf;
     489             : 
     490             :         /* Do the bestfrees correspond to actual free space? */
     491      940661 :         bf = xfs_dir2_data_bestfree_p(mp, bp->b_addr);
     492      940661 :         smallest_bestfree = UINT_MAX;
     493     4703247 :         for (dfp = &bf[0]; dfp < &bf[XFS_DIR2_DATA_FD_COUNT]; dfp++) {
     494     2821940 :                 offset = be16_to_cpu(dfp->offset);
     495     2821940 :                 if (offset == 0)
     496     1135191 :                         continue;
     497     1686749 :                 if (offset >= mp->m_dir_geo->blksize) {
     498           0 :                         xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
     499           0 :                         goto out_buf;
     500             :                 }
     501     1686749 :                 dup = bp->b_addr + offset;
     502     1686749 :                 tag = be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup));
     503             : 
     504             :                 /* bestfree doesn't match the entry it points at? */
     505     1686749 :                 if (dup->freetag != cpu_to_be16(XFS_DIR2_DATA_FREE_TAG) ||
     506     1686749 :                     be16_to_cpu(dup->length) != be16_to_cpu(dfp->length) ||
     507             :                     tag != offset) {
     508           0 :                         xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
     509           0 :                         goto out_buf;
     510             :                 }
     511             : 
     512             :                 /* bestfree records should be ordered largest to smallest */
     513     1686749 :                 if (smallest_bestfree < be16_to_cpu(dfp->length)) {
     514           0 :                         xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
     515           0 :                         goto out_buf;
     516             :                 }
     517             : 
     518     1686749 :                 smallest_bestfree = be16_to_cpu(dfp->length);
     519     1686749 :                 nr_bestfrees++;
     520             :         }
     521             : 
     522             :         /* Make sure the bestfrees are actually the best free spaces. */
     523      940646 :         offset = mp->m_dir_geo->data_entry_offset;
     524      940646 :         end = xfs_dir3_data_end_offset(mp->m_dir_geo, bp->b_addr);
     525             : 
     526             :         /* Iterate the entries, stopping when we hit or go past the end. */
     527   102748701 :         while (offset < end) {
     528   101808020 :                 dup = bp->b_addr + offset;
     529             : 
     530             :                 /* Skip real entries */
     531   101808020 :                 if (dup->freetag != cpu_to_be16(XFS_DIR2_DATA_FREE_TAG)) {
     532    95312981 :                         struct xfs_dir2_data_entry *dep = bp->b_addr + offset;
     533             : 
     534    95312981 :                         newlen = xfs_dir2_data_entsize(mp, dep->namelen);
     535    95312981 :                         if (newlen <= 0) {
     536             :                                 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK,
     537             :                                                 lblk);
     538             :                                 goto out_buf;
     539             :                         }
     540    95312981 :                         offset += newlen;
     541    95312981 :                         continue;
     542             :                 }
     543             : 
     544             :                 /* Spot check this free entry */
     545     6495039 :                 tag = be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup));
     546     6495039 :                 if (tag != offset) {
     547           0 :                         xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
     548           0 :                         goto out_buf;
     549             :                 }
     550             : 
     551             :                 /*
     552             :                  * Either this entry is a bestfree or it's smaller than
     553             :                  * any of the bestfrees.
     554             :                  */
     555     6495039 :                 xchk_directory_check_free_entry(sc, lblk, bf, dup);
     556     6495074 :                 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     557           0 :                         goto out_buf;
     558             : 
     559             :                 /* Move on. */
     560     6495074 :                 newlen = be16_to_cpu(dup->length);
     561     6495074 :                 if (newlen <= 0) {
     562           0 :                         xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
     563           0 :                         goto out_buf;
     564             :                 }
     565     6495074 :                 offset += newlen;
     566     6495074 :                 if (offset <= end)
     567     6495069 :                         nr_frees++;
     568             :         }
     569             : 
     570             :         /* We're required to fill all the space. */
     571      940677 :         if (offset != end)
     572           0 :                 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
     573             : 
     574             :         /* Did we see at least as many free slots as there are bestfrees? */
     575      940677 :         if (nr_frees < nr_bestfrees)
     576           0 :                 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
     577      940677 : out_buf:
     578      940677 :         xfs_trans_brelse(sc->tp, bp);
     579      940671 : out:
     580      940671 :         return error;
     581             : }
     582             : 
     583             : /*
     584             :  * Does the free space length in the free space index block ($len) match
     585             :  * the longest length in the directory data block's bestfree array?
     586             :  * Assume that we've already checked that the data block's bestfree
     587             :  * array is in order.
     588             :  */
     589             : STATIC void
     590      576202 : xchk_directory_check_freesp(
     591             :         struct xfs_scrub                *sc,
     592             :         xfs_dablk_t                     lblk,
     593             :         struct xfs_buf                  *dbp,
     594             :         unsigned int                    len)
     595             : {
     596      576202 :         struct xfs_dir2_data_free       *dfp;
     597             : 
     598      576202 :         dfp = xfs_dir2_data_bestfree_p(sc->mp, dbp->b_addr);
     599             : 
     600      576202 :         if (len != be16_to_cpu(dfp->length))
     601           0 :                 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
     602             : 
     603      576202 :         if (len > 0 && be16_to_cpu(dfp->offset) == 0)
     604           0 :                 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
     605      576202 : }
     606             : 
     607             : /* Check free space info in a directory leaf1 block. */
     608             : STATIC int
     609       20835 : xchk_directory_leaf1_bestfree(
     610             :         struct xfs_scrub                *sc,
     611             :         struct xfs_da_args              *args,
     612             :         xfs_dir2_db_t                   last_data_db,
     613             :         xfs_dablk_t                     lblk)
     614             : {
     615       20835 :         struct xfs_dir3_icleaf_hdr      leafhdr;
     616       20835 :         struct xfs_dir2_leaf_tail       *ltp;
     617       20835 :         struct xfs_dir2_leaf            *leaf;
     618       20835 :         struct xfs_buf                  *dbp;
     619       20835 :         struct xfs_buf                  *bp;
     620       20835 :         struct xfs_da_geometry          *geo = sc->mp->m_dir_geo;
     621       20835 :         __be16                          *bestp;
     622       20835 :         __u16                           best;
     623       20835 :         __u32                           hash;
     624       20835 :         __u32                           lasthash = 0;
     625       20835 :         __u32                           bestcount;
     626       20835 :         unsigned int                    stale = 0;
     627       20835 :         int                             i;
     628       20835 :         int                             error;
     629             : 
     630             :         /* Read the free space block. */
     631       20835 :         error = xfs_dir3_leaf_read(sc->tp, sc->ip, sc->ip->i_ino, lblk, &bp);
     632       20835 :         if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk, &error))
     633           0 :                 return error;
     634       20835 :         xchk_buffer_recheck(sc, bp);
     635             : 
     636       20835 :         leaf = bp->b_addr;
     637       20835 :         xfs_dir2_leaf_hdr_from_disk(sc->ip->i_mount, &leafhdr, leaf);
     638       20835 :         ltp = xfs_dir2_leaf_tail_p(geo, leaf);
     639       20835 :         bestcount = be32_to_cpu(ltp->bestcount);
     640       20835 :         bestp = xfs_dir2_leaf_bests_p(ltp);
     641             : 
     642       20835 :         if (xfs_has_crc(sc->mp)) {
     643       20835 :                 struct xfs_dir3_leaf_hdr        *hdr3 = bp->b_addr;
     644             : 
     645       20835 :                 if (hdr3->pad != cpu_to_be32(0))
     646           0 :                         xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
     647             :         }
     648             : 
     649             :         /*
     650             :          * There must be enough bestfree slots to cover all the directory data
     651             :          * blocks that we scanned.  It is possible for there to be a hole
     652             :          * between the last data block and i_disk_size.  This seems like an
     653             :          * oversight to the scrub author, but as we have been writing out
     654             :          * directories like this (and xfs_repair doesn't mind them) for years,
     655             :          * that's what we have to check.
     656             :          */
     657       20835 :         if (bestcount != last_data_db + 1) {
     658           0 :                 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
     659           0 :                 goto out;
     660             :         }
     661             : 
     662             :         /* Is the leaf count even remotely sane? */
     663       20835 :         if (leafhdr.count > geo->leaf_max_ents) {
     664           0 :                 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
     665           0 :                 goto out;
     666             :         }
     667             : 
     668             :         /* Leaves and bests don't overlap in leaf format. */
     669       20835 :         if ((char *)&leafhdr.ents[leafhdr.count] > (char *)bestp) {
     670           0 :                 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
     671           0 :                 goto out;
     672             :         }
     673             : 
     674             :         /* Check hash value order, count stale entries.  */
     675     5071657 :         for (i = 0; i < leafhdr.count; i++) {
     676     5050822 :                 hash = be32_to_cpu(leafhdr.ents[i].hashval);
     677     5050822 :                 if (i > 0 && lasthash > hash)
     678           0 :                         xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
     679     5050822 :                 lasthash = hash;
     680     5050822 :                 if (leafhdr.ents[i].address ==
     681             :                     cpu_to_be32(XFS_DIR2_NULL_DATAPTR))
     682      593628 :                         stale++;
     683             :         }
     684       20835 :         if (leafhdr.stale != stale)
     685           0 :                 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
     686       20835 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     687           0 :                 goto out;
     688             : 
     689             :         /* Check all the bestfree entries. */
     690       69692 :         for (i = 0; i < bestcount; i++, bestp++) {
     691       48857 :                 best = be16_to_cpu(*bestp);
     692       48857 :                 error = xfs_dir3_data_read(sc->tp, sc->ip, args->owner,
     693             :                                 xfs_dir2_db_to_da(args->geo, i),
     694             :                                 XFS_DABUF_MAP_HOLE_OK, &dbp);
     695       48857 :                 if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk,
     696             :                                 &error))
     697             :                         break;
     698             : 
     699       48857 :                 if (!dbp) {
     700         264 :                         if (best != NULLDATAOFF) {
     701           0 :                                 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK,
     702             :                                                 lblk);
     703           0 :                                 break;
     704             :                         }
     705         264 :                         continue;
     706             :                 }
     707             : 
     708       48593 :                 if (best == NULLDATAOFF)
     709           0 :                         xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
     710             :                 else
     711       48593 :                         xchk_directory_check_freesp(sc, lblk, dbp, best);
     712       48593 :                 xfs_trans_brelse(sc->tp, dbp);
     713       48593 :                 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     714             :                         break;
     715             :         }
     716       20835 : out:
     717       20835 :         xfs_trans_brelse(sc->tp, bp);
     718       20835 :         return error;
     719             : }
     720             : 
     721             : /* Check free space info in a directory freespace block. */
     722             : STATIC int
     723       32292 : xchk_directory_free_bestfree(
     724             :         struct xfs_scrub                *sc,
     725             :         struct xfs_da_args              *args,
     726             :         xfs_dablk_t                     lblk)
     727             : {
     728       32292 :         struct xfs_dir3_icfree_hdr      freehdr;
     729       32292 :         struct xfs_buf                  *dbp;
     730       32292 :         struct xfs_buf                  *bp;
     731       32292 :         __u16                           best;
     732       32292 :         unsigned int                    stale = 0;
     733       32292 :         int                             i;
     734       32292 :         int                             error;
     735             : 
     736             :         /* Read the free space block */
     737       32292 :         error = xfs_dir2_free_read(sc->tp, sc->ip, sc->ip->i_ino, lblk, &bp);
     738       32292 :         if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk, &error))
     739           0 :                 return error;
     740       32292 :         xchk_buffer_recheck(sc, bp);
     741             : 
     742       32292 :         if (xfs_has_crc(sc->mp)) {
     743       32292 :                 struct xfs_dir3_free_hdr        *hdr3 = bp->b_addr;
     744             : 
     745       32292 :                 if (hdr3->pad != cpu_to_be32(0))
     746           0 :                         xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
     747             :         }
     748             : 
     749             :         /* Check all the entries. */
     750       32292 :         xfs_dir2_free_hdr_from_disk(sc->ip->i_mount, &freehdr, bp->b_addr);
     751      606513 :         for (i = 0; i < freehdr.nvalid; i++) {
     752      541929 :                 best = be16_to_cpu(freehdr.bests[i]);
     753      541929 :                 if (best == NULLDATAOFF) {
     754       14321 :                         stale++;
     755       14321 :                         continue;
     756             :                 }
     757     1055217 :                 error = xfs_dir3_data_read(sc->tp, sc->ip, args->owner,
     758      527608 :                                 (freehdr.firstdb + i) * args->geo->fsbcount,
     759             :                                 0, &dbp);
     760      527609 :                 if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk,
     761             :                                 &error))
     762           0 :                         goto out;
     763      527609 :                 xchk_directory_check_freesp(sc, lblk, dbp, best);
     764      527609 :                 xfs_trans_brelse(sc->tp, dbp);
     765             :         }
     766             : 
     767       32292 :         if (freehdr.nused + stale != freehdr.nvalid)
     768           0 :                 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
     769       32292 : out:
     770       32292 :         xfs_trans_brelse(sc->tp, bp);
     771       32292 :         return error;
     772             : }
     773             : 
     774             : /* Check free space information in directories. */
     775             : STATIC int
     776    23115228 : xchk_directory_blocks(
     777             :         struct xfs_scrub        *sc)
     778             : {
     779    23115228 :         struct xfs_bmbt_irec    got;
     780    23115228 :         struct xfs_da_args      args = {
     781    23115228 :                 .dp             = sc->ip,
     782             :                 .whichfork      = XFS_DATA_FORK,
     783    23115228 :                 .geo            = sc->mp->m_dir_geo,
     784    23115228 :                 .trans          = sc->tp,
     785    23115228 :                 .owner          = sc->ip->i_ino,
     786             :         };
     787    23115228 :         struct xfs_ifork        *ifp = xfs_ifork_ptr(sc->ip, XFS_DATA_FORK);
     788    23115228 :         struct xfs_mount        *mp = sc->mp;
     789    23115228 :         xfs_fileoff_t           leaf_lblk;
     790    23115228 :         xfs_fileoff_t           free_lblk;
     791    23115228 :         xfs_fileoff_t           lblk;
     792    23115228 :         struct xfs_iext_cursor  icur;
     793    23115228 :         xfs_dablk_t             dabno;
     794    23115228 :         xfs_dir2_db_t           last_data_db = 0;
     795    23115228 :         bool                    found;
     796    23115228 :         bool                    is_block = false;
     797    23115228 :         int                     error;
     798             : 
     799             :         /* Ignore local format directories. */
     800    23115228 :         if (ifp->if_format != XFS_DINODE_FMT_EXTENTS &&
     801             :             ifp->if_format != XFS_DINODE_FMT_BTREE)
     802             :                 return 0;
     803             : 
     804      417549 :         lblk = XFS_B_TO_FSB(mp, XFS_DIR2_DATA_OFFSET);
     805      417549 :         leaf_lblk = XFS_B_TO_FSB(mp, XFS_DIR2_LEAF_OFFSET);
     806      417549 :         free_lblk = XFS_B_TO_FSB(mp, XFS_DIR2_FREE_OFFSET);
     807             : 
     808             :         /* Is this a block dir? */
     809      417549 :         error = xfs_dir2_isblock(&args, &is_block);
     810      417542 :         if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk, &error))
     811           0 :                 goto out;
     812             : 
     813             :         /* Iterate all the data extents in the directory... */
     814      417506 :         found = xfs_iext_lookup_extent(sc->ip, ifp, lblk, &icur, &got);
     815     1217661 :         while (found && !(sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)) {
     816             :                 /* No more data blocks... */
     817      853214 :                 if (got.br_startoff >= leaf_lblk)
     818             :                         break;
     819             : 
     820             :                 /*
     821             :                  * Check each data block's bestfree data.
     822             :                  *
     823             :                  * Iterate all the fsbcount-aligned block offsets in
     824             :                  * this directory.  The directory block reading code is
     825             :                  * smart enough to do its own bmap lookups to handle
     826             :                  * discontiguous directory blocks.  When we're done
     827             :                  * with the extent record, re-query the bmap at the
     828             :                  * next fsbcount-aligned offset to avoid redundant
     829             :                  * block checks.
     830             :                  */
     831      800116 :                 for (lblk = roundup((xfs_dablk_t)got.br_startoff,
     832             :                                 args.geo->fsbcount);
     833     1740787 :                      lblk < got.br_startoff + got.br_blockcount;
     834      940671 :                      lblk += args.geo->fsbcount) {
     835      940645 :                         last_data_db = xfs_dir2_da_to_db(args.geo, lblk);
     836      940607 :                         error = xchk_directory_data_bestfree(sc, lblk,
     837             :                                         is_block);
     838      940671 :                         if (error)
     839           0 :                                 goto out;
     840             :                 }
     841      800142 :                 dabno = got.br_startoff + got.br_blockcount;
     842      800142 :                 lblk = roundup(dabno, args.geo->fsbcount);
     843      800142 :                 found = xfs_iext_lookup_extent(sc->ip, ifp, lblk, &icur, &got);
     844             :         }
     845             : 
     846      417566 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     847           0 :                 goto out;
     848             : 
     849             :         /* Look for a leaf1 block, which has free info. */
     850      417566 :         if (xfs_iext_lookup_extent(sc->ip, ifp, leaf_lblk, &icur, &got) &&
     851       53098 :             got.br_startoff == leaf_lblk &&
     852      106195 :             got.br_blockcount == args.geo->fsbcount &&
     853       53097 :             !xfs_iext_next_extent(ifp, &icur, &got)) {
     854       20835 :                 if (is_block) {
     855           0 :                         xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
     856           0 :                         goto out;
     857             :                 }
     858       20835 :                 error = xchk_directory_leaf1_bestfree(sc, &args, last_data_db,
     859             :                                 leaf_lblk);
     860       20835 :                 if (error)
     861           0 :                         goto out;
     862             :         }
     863             : 
     864      417546 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     865           0 :                 goto out;
     866             : 
     867             :         /* Scan for free blocks */
     868      417546 :         lblk = free_lblk;
     869      417546 :         found = xfs_iext_lookup_extent(sc->ip, ifp, lblk, &icur, &got);
     870      449836 :         while (found && !(sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)) {
     871             :                 /*
     872             :                  * Dirs can't have blocks mapped above 2^32.
     873             :                  * Single-block dirs shouldn't even be here.
     874             :                  */
     875       32292 :                 lblk = got.br_startoff;
     876       32292 :                 if (lblk & ~0xFFFFFFFFULL) {
     877           0 :                         xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
     878           0 :                         goto out;
     879             :                 }
     880       32292 :                 if (is_block) {
     881           0 :                         xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
     882           0 :                         goto out;
     883             :                 }
     884             : 
     885             :                 /*
     886             :                  * Check each dir free block's bestfree data.
     887             :                  *
     888             :                  * Iterate all the fsbcount-aligned block offsets in
     889             :                  * this directory.  The directory block reading code is
     890             :                  * smart enough to do its own bmap lookups to handle
     891             :                  * discontiguous directory blocks.  When we're done
     892             :                  * with the extent record, re-query the bmap at the
     893             :                  * next fsbcount-aligned offset to avoid redundant
     894             :                  * block checks.
     895             :                  */
     896       32292 :                 for (lblk = roundup((xfs_dablk_t)got.br_startoff,
     897             :                                 args.geo->fsbcount);
     898       64584 :                      lblk < got.br_startoff + got.br_blockcount;
     899       32292 :                      lblk += args.geo->fsbcount) {
     900       32292 :                         error = xchk_directory_free_bestfree(sc, &args,
     901             :                                         lblk);
     902       32292 :                         if (error)
     903           0 :                                 goto out;
     904             :                 }
     905       32292 :                 dabno = got.br_startoff + got.br_blockcount;
     906       32292 :                 lblk = roundup(dabno, args.geo->fsbcount);
     907       32292 :                 found = xfs_iext_lookup_extent(sc->ip, ifp, lblk, &icur, &got);
     908             :         }
     909      417561 : out:
     910      417561 :         return error;
     911             : }
     912             : 
     913             : /*
     914             :  * Revalidate a dirent that we collected in the past but couldn't check because
     915             :  * of lock contention.  Returns 0 if the dirent is still valid, -ENOENT if it
     916             :  * has gone away on us, or a negative errno.
     917             :  */
     918             : STATIC int
     919           0 : xchk_dir_revalidate_dirent(
     920             :         struct xchk_dir         *sd,
     921             :         const struct xfs_name   *xname,
     922             :         xfs_ino_t               ino)
     923             : {
     924           0 :         struct xfs_scrub        *sc = sd->sc;
     925           0 :         xfs_ino_t               child_ino;
     926           0 :         int                     error;
     927             : 
     928             :         /*
     929             :          * Look up the directory entry.  If we get -ENOENT, the directory entry
     930             :          * went away and there's nothing to revalidate.  Return any other
     931             :          * error.
     932             :          */
     933           0 :         error = xchk_dir_lookup(sc, sc->ip, xname, &child_ino);
     934           0 :         if (error)
     935             :                 return error;
     936             : 
     937             :         /* The inode number changed, nothing to revalidate. */
     938           0 :         if (ino != child_ino)
     939           0 :                 return -ENOENT;
     940             : 
     941             :         return 0;
     942             : }
     943             : 
     944             : /*
     945             :  * Check a directory entry's parent pointers the slow way, which means we cycle
     946             :  * locks a bunch and put up with revalidation until we get it done.
     947             :  */
     948             : STATIC int
     949           0 : xchk_dir_slow_dirent(
     950             :         struct xchk_dir         *sd,
     951             :         struct xchk_dirent      *dirent)
     952             : {
     953           0 :         struct xfs_name         xname = {
     954           0 :                 .name           = sd->namebuf,
     955           0 :                 .len            = dirent->namelen,
     956             :         };
     957           0 :         struct xfs_scrub        *sc = sd->sc;
     958           0 :         struct xfs_inode        *ip;
     959           0 :         unsigned int            lockmode;
     960           0 :         int                     error;
     961             : 
     962             :         /* Check that the deferred dirent still exists. */
     963           0 :         if (sd->need_revalidate) {
     964           0 :                 error = xchk_dir_revalidate_dirent(sd, &xname, dirent->ino);
     965           0 :                 if (error == -ENOENT)
     966             :                         return 0;
     967           0 :                 if (!xchk_fblock_xref_process_error(sc, XFS_DATA_FORK, 0,
     968             :                                         &error))
     969           0 :                         return error;
     970             :         }
     971             : 
     972           0 :         error = xchk_iget(sc, dirent->ino, &ip);
     973           0 :         if (error == -EINVAL || error == -ENOENT) {
     974           0 :                 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
     975           0 :                 return 0;
     976             :         }
     977           0 :         if (!xchk_fblock_xref_process_error(sc, XFS_DATA_FORK, 0, &error))
     978           0 :                 return error;
     979             : 
     980             :         /*
     981             :          * If we can grab both IOLOCK and ILOCK of the alleged child, we can
     982             :          * proceed with the validation.
     983             :          */
     984           0 :         lockmode = xchk_dir_lock_child(sc, ip);
     985           0 :         if (lockmode)
     986           0 :                 goto check_pptr;
     987             : 
     988             :         /*
     989             :          * We couldn't lock the child file.  Drop all the locks and try to
     990             :          * get them again, one at a time.
     991             :          */
     992           0 :         xchk_iunlock(sc, sc->ilock_flags);
     993           0 :         sd->need_revalidate = true;
     994             : 
     995           0 :         trace_xchk_dir_slowpath(sc->ip, xname.name, xname.len, ip->i_ino);
     996             : 
     997           0 :         while (true) {
     998           0 :                 xchk_ilock(sc, XFS_IOLOCK_EXCL);
     999           0 :                 if (xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED)) {
    1000           0 :                         xchk_ilock(sc, XFS_ILOCK_EXCL);
    1001           0 :                         if (xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) {
    1002             :                                 break;
    1003             :                         }
    1004           0 :                         xchk_iunlock(sc, XFS_ILOCK_EXCL);
    1005             :                 }
    1006           0 :                 xchk_iunlock(sc, XFS_IOLOCK_EXCL);
    1007             : 
    1008           0 :                 if (xchk_should_terminate(sc, &error))
    1009           0 :                         goto out_rele;
    1010             : 
    1011           0 :                 delay(1);
    1012             :         }
    1013           0 :         lockmode = XFS_IOLOCK_SHARED | XFS_ILOCK_EXCL;
    1014             : 
    1015             :         /* Revalidate, since we just cycled the locks. */
    1016           0 :         error = xchk_dir_revalidate_dirent(sd, &xname, dirent->ino);
    1017           0 :         if (error == -ENOENT)
    1018           0 :                 goto out_unlock;
    1019           0 :         if (!xchk_fblock_xref_process_error(sc, XFS_DATA_FORK, 0, &error))
    1020           0 :                 goto out_unlock;
    1021             : 
    1022           0 : check_pptr:
    1023           0 :         error = xchk_dir_parent_pointer(sd, &xname, ip);
    1024           0 : out_unlock:
    1025           0 :         xfs_iunlock(ip, lockmode);
    1026           0 : out_rele:
    1027           0 :         xchk_irele(sc, ip);
    1028           0 :         return error;
    1029             : }
    1030             : 
    1031             : /* Check all the dirents that we deferred the first time around. */
    1032             : STATIC int
    1033    22482506 : xchk_dir_finish_slow_dirents(
    1034             :         struct xchk_dir         *sd)
    1035             : {
    1036    22482506 :         xfarray_idx_t           array_cur;
    1037    22482506 :         int                     error;
    1038             : 
    1039    22482506 :         foreach_xfarray_idx(sd->dir_entries, array_cur) {
    1040           0 :                 struct xchk_dirent      dirent;
    1041             : 
    1042           0 :                 if (sd->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
    1043           0 :                         return 0;
    1044             : 
    1045           0 :                 error = xfarray_load(sd->dir_entries, array_cur, &dirent);
    1046           0 :                 if (error)
    1047           0 :                         return error;
    1048             : 
    1049           0 :                 error = xfblob_load(sd->dir_names, dirent.name_cookie,
    1050           0 :                                 sd->namebuf, dirent.namelen);
    1051           0 :                 if (error)
    1052           0 :                         return error;
    1053           0 :                 sd->namebuf[MAXNAMELEN - 1] = 0;
    1054             : 
    1055           0 :                 error = xchk_dir_slow_dirent(sd, &dirent);
    1056           0 :                 if (error)
    1057           0 :                         return error;
    1058             :         }
    1059             : 
    1060             :         return 0;
    1061             : }
    1062             : 
    1063             : /* Scrub a whole directory. */
    1064             : int
    1065    23135967 : xchk_directory(
    1066             :         struct xfs_scrub        *sc)
    1067             : {
    1068    23135967 :         struct xchk_dir         *sd;
    1069    23135967 :         int                     error;
    1070             : 
    1071    23135967 :         if (!S_ISDIR(VFS_I(sc->ip)->i_mode))
    1072             :                 return -ENOENT;
    1073             : 
    1074             :         /* Plausible size? */
    1075    23135967 :         if (sc->ip->i_disk_size < xfs_dir2_sf_hdr_size(0)) {
    1076           0 :                 xchk_ino_set_corrupt(sc, sc->ip->i_ino);
    1077           0 :                 return 0;
    1078             :         }
    1079             : 
    1080             :         /* Check directory tree structure */
    1081    23135967 :         error = xchk_da_btree(sc, XFS_DATA_FORK, xchk_dir_rec, NULL);
    1082    23073369 :         if (error)
    1083             :                 return error;
    1084             : 
    1085    23073368 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
    1086             :                 return 0;
    1087             : 
    1088             :         /* Check the freespace. */
    1089    23071998 :         error = xchk_directory_blocks(sc);
    1090    23041424 :         if (error)
    1091             :                 return error;
    1092             : 
    1093    23041424 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
    1094             :                 return 0;
    1095             : 
    1096    23042547 :         sd = kvzalloc(sizeof(struct xchk_dir), XCHK_GFP_FLAGS);
    1097    23143694 :         if (!sd)
    1098             :                 return -ENOMEM;
    1099    23143694 :         sd->sc = sc;
    1100             : 
    1101    23143694 :         if (xfs_has_parent(sc->mp)) {
    1102    22460052 :                 char            *descr;
    1103             : 
    1104             :                 /*
    1105             :                  * Set up some staging memory for dirents that we can't check
    1106             :                  * due to locking contention.
    1107             :                  */
    1108    22460052 :                 descr = xchk_xfile_ino_descr(sc, "slow directory entries");
    1109    22399420 :                 error = xfarray_create(descr, 0, sizeof(struct xchk_dirent),
    1110             :                                 &sd->dir_entries);
    1111    22421296 :                 kfree(descr);
    1112    22443550 :                 if (error)
    1113           0 :                         goto out_sd;
    1114             : 
    1115    22443550 :                 descr = xchk_xfile_ino_descr(sc, "slow directory entry names");
    1116    22424119 :                 error = xfblob_create(descr, &sd->dir_names);
    1117    22484943 :                 kfree(descr);
    1118    22468629 :                 if (error)
    1119           0 :                         goto out_entries;
    1120             :         }
    1121             : 
    1122             :         /* Look up every name in this directory by hash. */
    1123    23152271 :         error = xchk_dir_walk(sc, sc->ip, xchk_dir_actor, sd);
    1124    23170399 :         if (error == -ECANCELED)
    1125             :                 error = 0;
    1126    23173790 :         if (error)
    1127           4 :                 goto out_names;
    1128             : 
    1129    23170395 :         if (xfs_has_parent(sc->mp)) {
    1130    22483284 :                 error = xchk_dir_finish_slow_dirents(sd);
    1131    22469496 :                 if (error)
    1132           0 :                         goto out_names;
    1133             :         }
    1134             : 
    1135    23156607 : out_names:
    1136    23156611 :         if (sd->dir_names)
    1137    22469730 :                 xfblob_destroy(sd->dir_names);
    1138      686881 : out_entries:
    1139    23166590 :         if (sd->dir_entries)
    1140    22479848 :                 xfarray_destroy(sd->dir_entries);
    1141      686742 : out_sd:
    1142    23168097 :         kvfree(sd);
    1143    23168097 :         return error;
    1144             : }
    1145             : 
    1146             : /*
    1147             :  * Decide if this directory has been zapped to satisfy the inode and ifork
    1148             :  * verifiers.  Checking and repairing should be postponed until the directory
    1149             :  * is fixed.
    1150             :  */
    1151             : bool
    1152   180429096 : xchk_dir_looks_zapped(
    1153             :         struct xfs_inode        *dp)
    1154             : {
    1155             :         /*
    1156             :          * If the dinode repair found a bad data fork, it will reset the fork
    1157             :          * to extents format with zero records and wait for the bmapbtd
    1158             :          * scrubber to reconstruct the block mappings.  Directories always
    1159             :          * contain some content, so this is a clear sign of a zapped directory.
    1160             :          */
    1161   180429096 :         if (dp->i_df.if_format == XFS_DINODE_FMT_EXTENTS)
    1162      808084 :                 return dp->i_df.if_nextents == 0;
    1163             : 
    1164             :         return false;
    1165             : }

Generated by: LCOV version 1.14