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-acha @ Mon Jul 31 20:08:06 PDT 2023 Lines: 408 570 71.6 %
Date: 2023-07-31 20:08:07 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    14306065 : xchk_setup_directory(
      33             :         struct xfs_scrub        *sc)
      34             : {
      35    14306065 :         int                     error;
      36             : 
      37    28612130 :         if (xchk_could_repair(sc)) {
      38      184730 :                 error = xrep_setup_directory(sc);
      39      184635 :                 if (error)
      40             :                         return error;
      41             :         }
      42             : 
      43    14305970 :         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   137805824 : xchk_dir_check_ftype(
      88             :         struct xfs_scrub        *sc,
      89             :         xfs_fileoff_t           offset,
      90             :         struct xfs_inode        *ip,
      91             :         int                     ftype)
      92             : {
      93   137805824 :         struct xfs_mount        *mp = sc->mp;
      94             : 
      95   137805824 :         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   137805824 :         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   109192726 : xchk_dir_lock_child(
     111             :         struct xfs_scrub        *sc,
     112             :         struct xfs_inode        *ip)
     113             : {
     114   109192726 :         if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED))
     115             :                 return 0;
     116             : 
     117   109151562 :         if (!xfs_ilock_nowait(ip, XFS_ILOCK_SHARED)) {
     118         323 :                 xfs_iunlock(ip, XFS_IOLOCK_SHARED);
     119         323 :                 return 0;
     120             :         }
     121             : 
     122   218302588 :         if (!xfs_inode_has_attr_fork(ip) || !xfs_need_iread_extents(&ip->i_af))
     123   109151325 :                 return XFS_IOLOCK_SHARED | XFS_ILOCK_SHARED;
     124             : 
     125          35 :         xfs_iunlock(ip, XFS_ILOCK_SHARED);
     126             : 
     127          35 :         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   109150770 : xchk_dir_parent_pointer(
     138             :         struct xchk_dir         *sd,
     139             :         const struct xfs_name   *name,
     140             :         struct xfs_inode        *ip)
     141             : {
     142   109150770 :         struct xfs_scrub        *sc = sd->sc;
     143   109150770 :         int                     error;
     144             : 
     145   109150770 :         sd->pptr.p_ino = sc->ip->i_ino;
     146   109150770 :         sd->pptr.p_gen = VFS_I(sc->ip)->i_generation;
     147   109150770 :         sd->pptr.p_namelen = name->len;
     148   218301540 :         memcpy(sd->pptr.p_name, name->name, name->len);
     149   109150770 :         xfs_parent_irec_hashname(sc->mp, &sd->pptr);
     150             : 
     151   109152596 :         error = xfs_parent_lookup(sc->tp, ip, &sd->pptr, &sd->pptr_scratch);
     152   109147529 :         if (error == -ENOATTR)
     153           0 :                 xchk_fblock_xref_set_corrupt(sc, XFS_DATA_FORK, 0);
     154             : 
     155   109147529 :         return 0;
     156             : }
     157             : 
     158             : /* Look for a parent pointer matching this dirent, if the child isn't busy. */
     159             : STATIC int
     160   137790041 : 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   137790041 :         struct xfs_scrub        *sc = sd->sc;
     167   137790041 :         unsigned int            lockmode;
     168   137790041 :         int                     error;
     169             : 
     170             :         /* dot and dotdot entries do not have parent pointers */
     171   261286033 :         if (xfs_dir2_samename(name, &xfs_name_dot) ||
     172   123496147 :             xfs_dir2_samename(name, &xfs_name_dotdot))
     173    28604264 :                 return 0;
     174             : 
     175             :         /* Try to lock the inode. */
     176   109195057 :         lockmode = xchk_dir_lock_child(sc, ip);
     177   109195203 :         if (!lockmode) {
     178       43834 :                 struct xchk_dirent      save_de = {
     179       43834 :                         .namelen        = name->len,
     180       43834 :                         .ino            = ip->i_ino,
     181             :                 };
     182             : 
     183             :                 /* Couldn't lock the inode, so save the dirent for later. */
     184       43834 :                 trace_xchk_dir_defer(sc->ip, name->name, name->len, ip->i_ino);
     185             : 
     186       87668 :                 error = xfblob_store(sd->dir_names, &save_de.name_cookie,
     187       43834 :                                 name->name, name->len);
     188       43834 :                 if (xchk_fblock_xref_process_error(sc, XFS_DATA_FORK, 0,
     189             :                                         &error))
     190       43834 :                         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   109151369 :         error = xchk_dir_parent_pointer(sd, name, ip);
     201   109147027 :         xfs_iunlock(ip, lockmode);
     202   109152733 :         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   137800827 : 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   137800827 :         struct xfs_mount        *mp = dp->i_mount;
     221   137800827 :         struct xfs_inode        *ip;
     222   137800827 :         struct xchk_dir         *sd = priv;
     223   137800827 :         xfs_ino_t               lookup_ino;
     224   137800827 :         xfs_dablk_t             offset;
     225   137800827 :         int                     error = 0;
     226             : 
     227   137800827 :         offset = xfs_dir2_db_to_da(mp->m_dir_geo,
     228             :                         xfs_dir2_dataptr_to_db(mp->m_dir_geo, dapos));
     229             : 
     230   137800827 :         if (xchk_should_terminate(sc, &error))
     231           0 :                 return error;
     232             : 
     233             :         /* Does this inode number make sense? */
     234   137802397 :         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   137807111 :         if (!xfs_dir2_namecheck(name->name, name->len)) {
     241           2 :                 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);
     242           2 :                 return -ECANCELED;
     243             :         }
     244             : 
     245   137807716 :         if (xfs_dir2_samename(name, &xfs_name_dot)) {
     246             :                 /* If this is "." then check that the inum matches the dir. */
     247    14303371 :                 if (ino != dp->i_ino)
     248           0 :                         xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);
     249   123508527 :         } 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    14303880 :                 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   137812716 :         error = xchk_dir_lookup(sc, dp, name, &lookup_ino);
     260             :         /* ENOENT means the hash lookup failed and the dir is corrupt */
     261   137801723 :         if (error == -ENOENT)
     262           0 :                 error = -EFSCORRUPTED;
     263   137801723 :         if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, offset, &error))
     264           0 :                 goto out;
     265   137806088 :         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   137806088 :         error = xchk_iget(sc, ino, &ip);
     280   137805687 :         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   137805687 :         if (!xchk_fblock_xref_process_error(sc, XFS_DATA_FORK, offset, &error))
     286           0 :                 goto out;
     287             : 
     288   137804862 :         xchk_dir_check_ftype(sc, offset, ip, name->type);
     289             : 
     290   137804061 :         if (xfs_has_parent(mp)) {
     291   137791449 :                 error = xchk_dir_check_pptr_fast(sd, dapos, name, ip);
     292   137788613 :                 if (error)
     293             :                         goto out_rele;
     294             :         }
     295             : 
     296   137801225 : out_rele:
     297   137801225 :         xchk_irele(sc, ip);
     298   137801627 : out:
     299   137801627 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     300             :                 return -ECANCELED;
     301   137801627 :         return error;
     302             : }
     303             : 
     304             : /* Scrub a directory btree record. */
     305             : STATIC int
     306    60148292 : xchk_dir_rec(
     307             :         struct xchk_da_btree            *ds,
     308             :         int                             level)
     309             : {
     310    60148292 :         struct xfs_name                 dname = { };
     311    60148292 :         struct xfs_da_state_blk         *blk = &ds->state->path.blk[level];
     312    60148292 :         struct xfs_mount                *mp = ds->state->mp;
     313    60148292 :         struct xfs_inode                *dp = ds->dargs.dp;
     314    60148292 :         struct xfs_da_geometry          *geo = mp->m_dir_geo;
     315    60148292 :         struct xfs_dir2_data_entry      *dent;
     316    60148292 :         struct xfs_buf                  *bp;
     317    60148292 :         struct xfs_dir2_leaf_entry      *ent;
     318    60148292 :         unsigned int                    end;
     319    60148292 :         unsigned int                    iter_off;
     320    60148292 :         xfs_ino_t                       ino;
     321    60148292 :         xfs_dablk_t                     rec_bno;
     322    60148292 :         xfs_dir2_db_t                   db;
     323    60148292 :         xfs_dir2_data_aoff_t            off;
     324    60148292 :         xfs_dir2_dataptr_t              ptr;
     325    60148292 :         xfs_dahash_t                    calc_hash;
     326    60148292 :         xfs_dahash_t                    hash;
     327    60148292 :         struct xfs_dir3_icleaf_hdr      hdr;
     328    60148292 :         unsigned int                    tag;
     329    60148292 :         int                             error;
     330             : 
     331    60148292 :         ASSERT(blk->magic == XFS_DIR2_LEAF1_MAGIC ||
     332             :                blk->magic == XFS_DIR2_LEAFN_MAGIC);
     333             : 
     334    60148292 :         xfs_dir2_leaf_hdr_from_disk(mp, &hdr, blk->bp->b_addr);
     335    60148433 :         ent = hdr.ents + blk->index;
     336             : 
     337             :         /* Check the hash of the entry. */
     338    60148433 :         error = xchk_da_btree_hash(ds, level, &ent->hashval);
     339    60147894 :         if (error)
     340           0 :                 goto out;
     341             : 
     342             :         /* Valid hash pointer? */
     343    60147894 :         ptr = be32_to_cpu(ent->address);
     344    60147894 :         if (ptr == 0)
     345             :                 return 0;
     346             : 
     347             :         /* Find the directory entry's location. */
     348    50266035 :         db = xfs_dir2_dataptr_to_db(geo, ptr);
     349    50266035 :         off = xfs_dir2_dataptr_to_off(geo, ptr);
     350    50266035 :         rec_bno = xfs_dir2_db_to_da(geo, db);
     351             : 
     352    50266035 :         if (rec_bno >= geo->leafblk) {
     353           0 :                 xchk_da_set_corrupt(ds, level);
     354           0 :                 goto out;
     355             :         }
     356    50266035 :         error = xfs_dir3_data_read(ds->dargs.trans, dp, ds->dargs.owner,
     357             :                         rec_bno, XFS_DABUF_MAP_HOLE_OK, &bp);
     358    50265676 :         if (!xchk_fblock_process_error(ds->sc, XFS_DATA_FORK, rec_bno,
     359             :                         &error))
     360           0 :                 goto out;
     361    50266029 :         if (!bp) {
     362           0 :                 xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno);
     363           0 :                 goto out;
     364             :         }
     365    50266029 :         xchk_buffer_recheck(ds->sc, bp);
     366             : 
     367    50262907 :         if (ds->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     368           0 :                 goto out_relse;
     369             : 
     370    50262907 :         dent = bp->b_addr + off;
     371             : 
     372             :         /* Make sure we got a real directory entry. */
     373    50262907 :         iter_off = geo->data_entry_offset;
     374    50262907 :         end = xfs_dir3_data_end_offset(geo, bp->b_addr);
     375    50261444 :         if (!end) {
     376           0 :                 xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno);
     377           0 :                 goto out_relse;
     378             :         }
     379  5007458583 :         for (;;) {
     380  5007458583 :                 struct xfs_dir2_data_entry      *dep = bp->b_addr + iter_off;
     381  5007458583 :                 struct xfs_dir2_data_unused     *dup = bp->b_addr + iter_off;
     382             : 
     383  5007458583 :                 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  5007458583 :                 if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
     389   275525547 :                         iter_off += be16_to_cpu(dup->length);
     390   275525547 :                         continue;
     391             :                 }
     392  4731933036 :                 if (dep == dent)
     393             :                         break;
     394  9371387064 :                 iter_off += xfs_dir2_data_entsize(mp, dep->namelen);
     395             :         }
     396             : 
     397             :         /* Retrieve the entry, sanity check it, and compare hashes. */
     398    50261444 :         ino = be64_to_cpu(dent->inumber);
     399    50261444 :         hash = be32_to_cpu(ent->hashval);
     400    50261444 :         tag = be16_to_cpup(xfs_dir2_data_entry_tag_p(mp, dent));
     401    50262241 :         if (!xfs_verify_dir_ino(mp, ino) || tag != off)
     402         322 :                 xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno);
     403    50262899 :         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    50262899 :         dname.name = dent->name;
     410    50262899 :         dname.len = dent->namelen;
     411    50262899 :         calc_hash = xfs_dir2_hashname(mp, &dname);
     412    50264698 :         if (calc_hash != hash)
     413           0 :                 xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno);
     414             : 
     415    50264698 : out_relse:
     416    50264698 :         xfs_trans_brelse(ds->dargs.trans, bp);
     417    50266134 : out:
     418    50266134 :         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     5181813 : 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     5181813 :         struct xfs_dir2_data_free       *dfp;
     434     5181813 :         unsigned int                    dup_length;
     435             : 
     436     5181813 :         dup_length = be16_to_cpu(dup->length);
     437             : 
     438             :         /* Unused entry is shorter than any of the bestfrees */
     439     5181813 :         if (dup_length < be16_to_cpu(bf[XFS_DIR2_DATA_FD_COUNT - 1].length))
     440             :                 return;
     441             : 
     442     4208941 :         for (dfp = &bf[XFS_DIR2_DATA_FD_COUNT - 1]; dfp >= bf; dfp--)
     443     4208941 :                 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      576550 : xchk_directory_data_bestfree(
     453             :         struct xfs_scrub                *sc,
     454             :         xfs_dablk_t                     lblk,
     455             :         bool                            is_block)
     456             : {
     457      576550 :         struct xfs_dir2_data_unused     *dup;
     458      576550 :         struct xfs_dir2_data_free       *dfp;
     459      576550 :         struct xfs_buf                  *bp;
     460      576550 :         struct xfs_dir2_data_free       *bf;
     461      576550 :         struct xfs_mount                *mp = sc->mp;
     462      576550 :         u16                             tag;
     463      576550 :         unsigned int                    nr_bestfrees = 0;
     464      576550 :         unsigned int                    nr_frees = 0;
     465      576550 :         unsigned int                    smallest_bestfree;
     466      576550 :         int                             newlen;
     467      576550 :         unsigned int                    offset;
     468      576550 :         unsigned int                    end;
     469      576550 :         int                             error;
     470             : 
     471      576550 :         if (is_block) {
     472             :                 /* dir block format */
     473      270752 :                 if (lblk != XFS_B_TO_FSBT(mp, XFS_DIR2_DATA_OFFSET))
     474           0 :                         xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
     475      270752 :                 error = xfs_dir3_block_read(sc->tp, sc->ip, sc->ip->i_ino, &bp);
     476             :         } else {
     477             :                 /* dir data format */
     478      305798 :                 error = xfs_dir3_data_read(sc->tp, sc->ip, sc->ip->i_ino, lblk,
     479             :                                 0, &bp);
     480             :         }
     481      576551 :         if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk, &error))
     482           0 :                 goto out;
     483      576551 :         xchk_buffer_recheck(sc, bp);
     484             : 
     485             :         /* XXX: Check xfs_dir3_data_hdr.pad is zero once we start setting it. */
     486             : 
     487      576550 :         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      576550 :         bf = xfs_dir2_data_bestfree_p(mp, bp->b_addr);
     492      576550 :         smallest_bestfree = UINT_MAX;
     493     2882751 :         for (dfp = &bf[0]; dfp < &bf[XFS_DIR2_DATA_FD_COUNT]; dfp++) {
     494     1729651 :                 offset = be16_to_cpu(dfp->offset);
     495     1729651 :                 if (offset == 0)
     496      490757 :                         continue;
     497     1238894 :                 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     1238894 :                 dup = bp->b_addr + offset;
     502     1238894 :                 tag = be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup));
     503             : 
     504             :                 /* bestfree doesn't match the entry it points at? */
     505     2477788 :                 if (dup->freetag != cpu_to_be16(XFS_DIR2_DATA_FREE_TAG) ||
     506     1238894 :                     be16_to_cpu(dup->length) != be16_to_cpu(dfp->length) ||
     507     1238894 :                     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     1238894 :                 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     1238894 :                 smallest_bestfree = be16_to_cpu(dfp->length);
     519     1238894 :                 nr_bestfrees++;
     520             :         }
     521             : 
     522             :         /* Make sure the bestfrees are actually the best free spaces. */
     523      576550 :         offset = mp->m_dir_geo->data_entry_offset;
     524      576550 :         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    61428600 :         while (offset < end) {
     528    60852049 :                 dup = bp->b_addr + offset;
     529             : 
     530             :                 /* Skip real entries */
     531    60852049 :                 if (dup->freetag != cpu_to_be16(XFS_DIR2_DATA_FREE_TAG)) {
     532    55670236 :                         struct xfs_dir2_data_entry *dep = bp->b_addr + offset;
     533             : 
     534    55670236 :                         newlen = xfs_dir2_data_entsize(mp, dep->namelen);
     535    55670236 :                         if (newlen <= 0) {
     536             :                                 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK,
     537             :                                                 lblk);
     538             :                                 goto out_buf;
     539             :                         }
     540    55670236 :                         offset += newlen;
     541    55670236 :                         continue;
     542             :                 }
     543             : 
     544             :                 /* Spot check this free entry */
     545     5181813 :                 tag = be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup));
     546     5181813 :                 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     5181813 :                 xchk_directory_check_free_entry(sc, lblk, bf, dup);
     556     5181814 :                 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     557           0 :                         goto out_buf;
     558             : 
     559             :                 /* Move on. */
     560     5181814 :                 newlen = be16_to_cpu(dup->length);
     561     5181814 :                 if (newlen <= 0) {
     562           0 :                         xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
     563           0 :                         goto out_buf;
     564             :                 }
     565     5181814 :                 offset += newlen;
     566     5181814 :                 if (offset <= end)
     567     5181814 :                         nr_frees++;
     568             :         }
     569             : 
     570             :         /* We're required to fill all the space. */
     571      576551 :         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      576551 :         if (nr_frees < nr_bestfrees)
     576           0 :                 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
     577      576551 : out_buf:
     578      576551 :         xfs_trans_brelse(sc->tp, bp);
     579      576551 : out:
     580      576551 :         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      305798 : 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      305798 :         struct xfs_dir2_data_free       *dfp;
     597             : 
     598      305798 :         dfp = xfs_dir2_data_bestfree_p(sc->mp, dbp->b_addr);
     599             : 
     600      305798 :         if (len != be16_to_cpu(dfp->length))
     601           0 :                 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
     602             : 
     603      305798 :         if (len > 0 && be16_to_cpu(dfp->offset) == 0)
     604           0 :                 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
     605      305798 : }
     606             : 
     607             : /* Check free space info in a directory leaf1 block. */
     608             : STATIC int
     609        6244 : 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        6244 :         struct xfs_dir3_icleaf_hdr      leafhdr;
     616        6244 :         struct xfs_dir2_leaf_tail       *ltp;
     617        6244 :         struct xfs_dir2_leaf            *leaf;
     618        6244 :         struct xfs_buf                  *dbp;
     619        6244 :         struct xfs_buf                  *bp;
     620        6244 :         struct xfs_da_geometry          *geo = sc->mp->m_dir_geo;
     621        6244 :         __be16                          *bestp;
     622        6244 :         __u16                           best;
     623        6244 :         __u32                           hash;
     624        6244 :         __u32                           lasthash = 0;
     625        6244 :         __u32                           bestcount;
     626        6244 :         unsigned int                    stale = 0;
     627        6244 :         int                             i;
     628        6244 :         int                             error;
     629             : 
     630             :         /* Read the free space block. */
     631        6244 :         error = xfs_dir3_leaf_read(sc->tp, sc->ip, sc->ip->i_ino, lblk, &bp);
     632        6244 :         if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk, &error))
     633           0 :                 return error;
     634        6244 :         xchk_buffer_recheck(sc, bp);
     635             : 
     636        6244 :         leaf = bp->b_addr;
     637        6244 :         xfs_dir2_leaf_hdr_from_disk(sc->ip->i_mount, &leafhdr, leaf);
     638        6244 :         ltp = xfs_dir2_leaf_tail_p(geo, leaf);
     639        6244 :         bestcount = be32_to_cpu(ltp->bestcount);
     640        6244 :         bestp = xfs_dir2_leaf_bests_p(ltp);
     641             : 
     642        6244 :         if (xfs_has_crc(sc->mp)) {
     643        6244 :                 struct xfs_dir3_leaf_hdr        *hdr3 = bp->b_addr;
     644             : 
     645        6244 :                 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        6244 :         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        6244 :         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        6244 :         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     1731726 :         for (i = 0; i < leafhdr.count; i++) {
     676     1725482 :                 hash = be32_to_cpu(leafhdr.ents[i].hashval);
     677     1725482 :                 if (i > 0 && lasthash > hash)
     678           0 :                         xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
     679     1725482 :                 lasthash = hash;
     680     1725482 :                 if (leafhdr.ents[i].address ==
     681             :                     cpu_to_be32(XFS_DIR2_NULL_DATAPTR))
     682      350134 :                         stale++;
     683             :         }
     684        6244 :         if (leafhdr.stale != stale)
     685           0 :                 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
     686        6244 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     687           0 :                 goto out;
     688             : 
     689             :         /* Check all the bestfree entries. */
     690       18191 :         for (i = 0; i < bestcount; i++, bestp++) {
     691       11947 :                 best = be16_to_cpu(*bestp);
     692       11947 :                 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       11947 :                 if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk,
     696             :                                 &error))
     697             :                         break;
     698             : 
     699       11947 :                 if (!dbp) {
     700          62 :                         if (best != NULLDATAOFF) {
     701           0 :                                 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK,
     702             :                                                 lblk);
     703           0 :                                 break;
     704             :                         }
     705          62 :                         continue;
     706             :                 }
     707             : 
     708       11885 :                 if (best == NULLDATAOFF)
     709           0 :                         xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
     710             :                 else
     711       11885 :                         xchk_directory_check_freesp(sc, lblk, dbp, best);
     712       11885 :                 xfs_trans_brelse(sc->tp, dbp);
     713       11885 :                 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     714             :                         break;
     715             :         }
     716        6244 : out:
     717        6244 :         xfs_trans_brelse(sc->tp, bp);
     718        6244 :         return error;
     719             : }
     720             : 
     721             : /* Check free space info in a directory freespace block. */
     722             : STATIC int
     723       16627 : xchk_directory_free_bestfree(
     724             :         struct xfs_scrub                *sc,
     725             :         struct xfs_da_args              *args,
     726             :         xfs_dablk_t                     lblk)
     727             : {
     728       16627 :         struct xfs_dir3_icfree_hdr      freehdr;
     729       16627 :         struct xfs_buf                  *dbp;
     730       16627 :         struct xfs_buf                  *bp;
     731       16627 :         __u16                           best;
     732       16627 :         unsigned int                    stale = 0;
     733       16627 :         int                             i;
     734       16627 :         int                             error;
     735             : 
     736             :         /* Read the free space block */
     737       16627 :         error = xfs_dir2_free_read(sc->tp, sc->ip, sc->ip->i_ino, lblk, &bp);
     738       16627 :         if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk, &error))
     739           0 :                 return error;
     740       16627 :         xchk_buffer_recheck(sc, bp);
     741             : 
     742       16627 :         if (xfs_has_crc(sc->mp)) {
     743       16627 :                 struct xfs_dir3_free_hdr        *hdr3 = bp->b_addr;
     744             : 
     745       16627 :                 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       16627 :         xfs_dir2_free_hdr_from_disk(sc->ip->i_mount, &freehdr, bp->b_addr);
     751      331765 :         for (i = 0; i < freehdr.nvalid; i++) {
     752      298511 :                 best = be16_to_cpu(freehdr.bests[i]);
     753      298511 :                 if (best == NULLDATAOFF) {
     754        4598 :                         stale++;
     755        4598 :                         continue;
     756             :                 }
     757      587826 :                 error = xfs_dir3_data_read(sc->tp, sc->ip, args->owner,
     758      293913 :                                 (freehdr.firstdb + i) * args->geo->fsbcount,
     759             :                                 0, &dbp);
     760      293913 :                 if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk,
     761             :                                 &error))
     762           0 :                         goto out;
     763      293913 :                 xchk_directory_check_freesp(sc, lblk, dbp, best);
     764      293913 :                 xfs_trans_brelse(sc->tp, dbp);
     765             :         }
     766             : 
     767       16627 :         if (freehdr.nused + stale != freehdr.nvalid)
     768           0 :                 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
     769       16627 : out:
     770       16627 :         xfs_trans_brelse(sc->tp, bp);
     771       16627 :         return error;
     772             : }
     773             : 
     774             : /* Check free space information in directories. */
     775             : STATIC int
     776    14303770 : xchk_directory_blocks(
     777             :         struct xfs_scrub        *sc)
     778             : {
     779    14303770 :         struct xfs_bmbt_irec    got;
     780    14303770 :         struct xfs_da_args      args = {
     781    14303770 :                 .dp             = sc->ip,
     782             :                 .whichfork      = XFS_DATA_FORK,
     783    14303770 :                 .geo            = sc->mp->m_dir_geo,
     784    14303770 :                 .trans          = sc->tp,
     785    14303770 :                 .owner          = sc->ip->i_ino,
     786             :         };
     787    14303770 :         struct xfs_ifork        *ifp = xfs_ifork_ptr(sc->ip, XFS_DATA_FORK);
     788    14303770 :         struct xfs_mount        *mp = sc->mp;
     789    14303770 :         xfs_fileoff_t           leaf_lblk;
     790    14303770 :         xfs_fileoff_t           free_lblk;
     791    14303770 :         xfs_fileoff_t           lblk;
     792    14303770 :         struct xfs_iext_cursor  icur;
     793    14303770 :         xfs_dablk_t             dabno;
     794    14303770 :         xfs_dir2_db_t           last_data_db = 0;
     795    14303770 :         bool                    found;
     796    14303770 :         bool                    is_block = false;
     797    14303770 :         int                     error;
     798             : 
     799             :         /* Ignore local format directories. */
     800    14303770 :         if (ifp->if_format != XFS_DINODE_FMT_EXTENTS &&
     801             :             ifp->if_format != XFS_DINODE_FMT_BTREE)
     802             :                 return 0;
     803             : 
     804      293621 :         lblk = XFS_B_TO_FSB(mp, XFS_DIR2_DATA_OFFSET);
     805      293621 :         leaf_lblk = XFS_B_TO_FSB(mp, XFS_DIR2_LEAF_OFFSET);
     806      293621 :         free_lblk = XFS_B_TO_FSB(mp, XFS_DIR2_FREE_OFFSET);
     807             : 
     808             :         /* Is this a block dir? */
     809      293621 :         error = xfs_dir2_isblock(&args, &is_block);
     810      293620 :         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      293621 :         found = xfs_iext_lookup_extent(sc->ip, ifp, lblk, &icur, &got);
     815      815205 :         while (found && !(sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)) {
     816             :                 /* No more data blocks... */
     817      544452 :                 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      521584 :                 for (lblk = roundup((xfs_dablk_t)got.br_startoff,
     832             :                                 args.geo->fsbcount);
     833     1098135 :                      lblk < got.br_startoff + got.br_blockcount;
     834      576551 :                      lblk += args.geo->fsbcount) {
     835      576550 :                         last_data_db = xfs_dir2_da_to_db(args.geo, lblk);
     836      576550 :                         error = xchk_directory_data_bestfree(sc, lblk,
     837             :                                         is_block);
     838      576551 :                         if (error)
     839           0 :                                 goto out;
     840             :                 }
     841      521585 :                 dabno = got.br_startoff + got.br_blockcount;
     842      521585 :                 lblk = roundup(dabno, args.geo->fsbcount);
     843      521585 :                 found = xfs_iext_lookup_extent(sc->ip, ifp, lblk, &icur, &got);
     844             :         }
     845             : 
     846      293621 :         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      293621 :         if (xfs_iext_lookup_extent(sc->ip, ifp, leaf_lblk, &icur, &got) &&
     851       22868 :             got.br_startoff == leaf_lblk &&
     852       45736 :             got.br_blockcount == args.geo->fsbcount &&
     853       22868 :             !xfs_iext_next_extent(ifp, &icur, &got)) {
     854        6244 :                 if (is_block) {
     855           0 :                         xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
     856           0 :                         goto out;
     857             :                 }
     858        6244 :                 error = xchk_directory_leaf1_bestfree(sc, &args, last_data_db,
     859             :                                 leaf_lblk);
     860        6244 :                 if (error)
     861           0 :                         goto out;
     862             :         }
     863             : 
     864      293621 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     865           0 :                 goto out;
     866             : 
     867             :         /* Scan for free blocks */
     868      293621 :         lblk = free_lblk;
     869      293621 :         found = xfs_iext_lookup_extent(sc->ip, ifp, lblk, &icur, &got);
     870      310246 :         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       16627 :                 lblk = got.br_startoff;
     876       16627 :                 if (lblk & ~0xFFFFFFFFULL) {
     877           0 :                         xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
     878           0 :                         goto out;
     879             :                 }
     880       16627 :                 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       16627 :                 for (lblk = roundup((xfs_dablk_t)got.br_startoff,
     897             :                                 args.geo->fsbcount);
     898       33254 :                      lblk < got.br_startoff + got.br_blockcount;
     899       16627 :                      lblk += args.geo->fsbcount) {
     900       16627 :                         error = xchk_directory_free_bestfree(sc, &args,
     901             :                                         lblk);
     902       16627 :                         if (error)
     903           0 :                                 goto out;
     904             :                 }
     905       16627 :                 dabno = got.br_startoff + got.br_blockcount;
     906       16627 :                 lblk = roundup(dabno, args.geo->fsbcount);
     907       16627 :                 found = xfs_iext_lookup_extent(sc->ip, ifp, lblk, &icur, &got);
     908             :         }
     909      293619 : out:
     910      293619 :         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    14302318 : xchk_dir_finish_slow_dirents(
    1034             :         struct xchk_dir         *sd)
    1035             : {
    1036    14302318 :         xfarray_idx_t           array_cur;
    1037    14302318 :         int                     error;
    1038             : 
    1039    14302318 :         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    14303799 : xchk_directory(
    1066             :         struct xfs_scrub        *sc)
    1067             : {
    1068    14303799 :         struct xchk_dir         *sd;
    1069    14303799 :         int                     error;
    1070             : 
    1071    14303799 :         if (!S_ISDIR(VFS_I(sc->ip)->i_mode))
    1072             :                 return -ENOENT;
    1073             : 
    1074             :         /* Plausible size? */
    1075    14303799 :         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    14303799 :         error = xchk_da_btree(sc, XFS_DATA_FORK, xchk_dir_rec, NULL);
    1082    14303898 :         if (error)
    1083             :                 return error;
    1084             : 
    1085    14303897 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
    1086             :                 return 0;
    1087             : 
    1088             :         /* Check the freespace. */
    1089    14303871 :         error = xchk_directory_blocks(sc);
    1090    14303983 :         if (error)
    1091             :                 return error;
    1092             : 
    1093    14303983 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
    1094             :                 return 0;
    1095             : 
    1096    14304015 :         sd = kvzalloc(sizeof(struct xchk_dir), XCHK_GFP_FLAGS);
    1097    14303795 :         if (!sd)
    1098             :                 return -ENOMEM;
    1099    14303795 :         sd->sc = sc;
    1100             : 
    1101    14303795 :         if (xfs_has_parent(sc->mp)) {
    1102    14302477 :                 char            *descr;
    1103             : 
    1104             :                 /*
    1105             :                  * Set up some staging memory for dirents that we can't check
    1106             :                  * due to locking contention.
    1107             :                  */
    1108    14302477 :                 descr = xchk_xfile_ino_descr(sc, "slow directory entries");
    1109    14302385 :                 error = xfarray_create(descr, 0, sizeof(struct xchk_dirent),
    1110             :                                 &sd->dir_entries);
    1111    14302243 :                 kfree(descr);
    1112    14302533 :                 if (error)
    1113           0 :                         goto out_sd;
    1114             : 
    1115    14302533 :                 descr = xchk_xfile_ino_descr(sc, "slow directory entry names");
    1116    14302086 :                 error = xfblob_create(descr, &sd->dir_names);
    1117    14302630 :                 kfree(descr);
    1118    14302658 :                 if (error)
    1119           0 :                         goto out_entries;
    1120             :         }
    1121             : 
    1122             :         /* Look up every name in this directory by hash. */
    1123    14303976 :         error = xchk_dir_walk(sc, sc->ip, xchk_dir_actor, sd);
    1124    14303901 :         if (error == -ECANCELED)
    1125             :                 error = 0;
    1126    14303892 :         if (error)
    1127           0 :                 goto out_names;
    1128             : 
    1129    14303901 :         if (xfs_has_parent(sc->mp)) {
    1130    14302583 :                 error = xchk_dir_finish_slow_dirents(sd);
    1131    14302432 :                 if (error)
    1132           0 :                         goto out_names;
    1133             :         }
    1134             : 
    1135    14303750 : out_names:
    1136    14303750 :         if (sd->dir_names)
    1137    14302432 :                 xfblob_destroy(sd->dir_names);
    1138        1318 : out_entries:
    1139    14303996 :         if (sd->dir_entries)
    1140    14302678 :                 xfarray_destroy(sd->dir_entries);
    1141        1318 : out_sd:
    1142    14304003 :         kvfree(sd);
    1143    14304003 :         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   168975201 : 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   168975201 :         if (dp->i_df.if_format == XFS_DINODE_FMT_EXTENTS)
    1162      696361 :                 return dp->i_df.if_nextents == 0;
    1163             : 
    1164             :         return false;
    1165             : }

Generated by: LCOV version 1.14