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

Generated by: LCOV version 1.14