LCOV - code coverage report
Current view: top level - fs/xfs/scrub - dirtree.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc3-acha @ Mon Jul 31 20:08:06 PDT 2023 Lines: 293 408 71.8 %
Date: 2023-07-31 20:08:07 Functions: 15 20 75.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-or-later
       2             : /*
       3             :  * Copyright (C) 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/bitmap.h"
      23             : #include "scrub/xfile.h"
      24             : #include "scrub/xfarray.h"
      25             : #include "scrub/xfblob.h"
      26             : #include "scrub/listxattr.h"
      27             : #include "scrub/trace.h"
      28             : #include "scrub/repair.h"
      29             : #include "scrub/orphanage.h"
      30             : #include "scrub/dirtree.h"
      31             : 
      32             : #include "scrub/readdir.h"
      33             : 
      34             : /*
      35             :  * Directory Tree Structure Validation
      36             :  * ===================================
      37             :  *
      38             :  * Validating the tree qualities of the directory tree structure can be
      39             :  * difficult.  If the tree is frozen, running a depth (or breadth) first search
      40             :  * and marking a bitmap suffices to determine if there is a cycle.  XORing the
      41             :  * mark bitmap with the inode bitmap afterwards tells us if there are
      42             :  * disconnected cycles.  If the tree is not frozen, directory updates can move
      43             :  * subtrees across the scanner wavefront, which complicates the design greatly.
      44             :  *
      45             :  * Directory parent pointers change that by enabling an incremental approach to
      46             :  * validation of the tree structure.  Instead of using one thread to scan the
      47             :  * entire filesystem, we instead can have multiple threads walking individual
      48             :  * subdirectories upwards to the root.  Each scanner thread must be able to
      49             :  * take the IOLOCK of the directory that it is examining to prevent that
      50             :  * directory from being moved within the tree.  This was not possible prior to
      51             :  * Linux 6.5 because the VFS did not take i_rwsem when moving subdirectories.
      52             :  *
      53             :  * If the walk terminates without reaching the root, we know the path is
      54             :  * disconnected and ought to be attached to the lost and found.  If on the walk
      55             :  * we find the same subdir that we're scanning, we know this is a cycle and
      56             :  * should delete an incoming edge.  If we find multiple paths to the root, we
      57             :  * know to delete an incoming edge.
      58             :  *
      59             :  * There are two big hitches with this approach: first, all file link counts
      60             :  * must be correct to prevent other writers from doing the wrong thing with the
      61             :  * directory tree structure.  Second, because we're walking upwards in a tree
      62             :  * of arbitrary depth, we cannot hold all the ILOCKs.  Instead, we will use a
      63             :  * directory update hook to invalidate the scan results if one of the paths
      64             :  * we've scanned has changed.
      65             :  */
      66             : 
      67             : /* Clean up the dirtree checking resources. */
      68             : STATIC void
      69    13596435 : xchk_dirtree_buf_cleanup(
      70             :         void                    *buf)
      71             : {
      72    13596435 :         struct xchk_dirtree     *dl = buf;
      73    13596435 :         struct xchk_dirpath     *path, *n;
      74             : 
      75    13596435 :         if (dl->scan_ino != NULLFSINO)
      76    13596450 :                 xfs_dir_hook_del(dl->sc->mp, &dl->hooks);
      77             : 
      78    27181390 :         xchk_dirtree_for_each_path_safe(dl, path, n) {
      79    13584272 :                 list_del_init(&path->list);
      80    13584136 :                 xino_bitmap_destroy(&path->seen_inodes);
      81    13583215 :                 kfree(path);
      82             :         }
      83             : 
      84    13597118 :         xfblob_destroy(dl->path_names);
      85    13597173 :         xfarray_destroy(dl->path_steps);
      86    13597258 :         mutex_destroy(&dl->lock);
      87    13596895 : }
      88             : 
      89             : /* Set us up to look for directory loops. */
      90             : int
      91    13597685 : xchk_setup_dirtree(
      92             :         struct xfs_scrub        *sc)
      93             : {
      94    13597685 :         struct xchk_dirtree     *dl;
      95    13597685 :         char                    *descr;
      96    13597685 :         int                     error;
      97             : 
      98    13597685 :         xchk_fsgates_enable(sc, XCHK_FSGATES_DIRENTS);
      99             : 
     100    27188844 :         if (xchk_could_repair(sc)) {
     101      169534 :                 error = xrep_setup_dirtree(sc);
     102      169597 :                 if (error)
     103             :                         return error;
     104             :         }
     105             : 
     106    13594485 :         dl = kvzalloc(sizeof(struct xchk_dirtree), XCHK_GFP_FLAGS);
     107    13583283 :         if (!dl)
     108             :                 return -ENOMEM;
     109    13583283 :         dl->sc = sc;
     110    13583283 :         INIT_LIST_HEAD(&dl->path_list);
     111    13583283 :         dl->root_ino = NULLFSINO;
     112    13583283 :         dl->scan_ino = NULLFSINO;
     113    13583283 :         dl->parent_ino = NULLFSINO;
     114             : 
     115    13583283 :         mutex_init(&dl->lock);
     116             : 
     117    13583527 :         descr = xchk_xfile_ino_descr(sc, "dirtree path steps");
     118    13364119 :         error = xfarray_create(descr, 0, sizeof(struct xchk_dirpath_step),
     119             :                         &dl->path_steps);
     120    13557127 :         kfree(descr);
     121    13571923 :         if (error)
     122           0 :                 goto out_dl;
     123             : 
     124    13571923 :         descr = xchk_xfile_ino_descr(sc, "dirtree path names");
     125    13549188 :         error = xfblob_create(descr, &dl->path_names);
     126    13590341 :         kfree(descr);
     127    13593027 :         if (error)
     128           0 :                 goto out_steps;
     129             : 
     130    13593027 :         error = xchk_setup_inode_contents(sc, 0);
     131    13579297 :         if (error)
     132           7 :                 goto out_names;
     133             : 
     134    13579290 :         sc->buf = dl;
     135    13579290 :         sc->buf_cleanup = xchk_dirtree_buf_cleanup;
     136    13579290 :         return 0;
     137             : 
     138             : out_names:
     139           7 :         xfblob_destroy(dl->path_names);
     140           7 : out_steps:
     141           7 :         xfarray_destroy(dl->path_steps);
     142           7 : out_dl:
     143           7 :         mutex_destroy(&dl->lock);
     144           7 :         kvfree(dl);
     145           7 :         return error;
     146             : }
     147             : 
     148             : /*
     149             :  * Add the parent pointer described by @dl->pptr to the given path as a new
     150             :  * step.  Returns -ELNRNG if the path is too deep.
     151             :  */
     152             : int
     153  1188484112 : xchk_dirpath_append(
     154             :         struct xchk_dirtree             *dl,
     155             :         struct xfs_inode                *ip,
     156             :         struct xchk_dirpath             *path,
     157             :         const struct xfs_parent_name_irec *pptr)
     158             : {
     159  1188484112 :         struct xchk_dirpath_step        step = {
     160  1188484112 :                 .parent_ino             = pptr->p_ino,
     161  1188484112 :                 .parent_gen             = pptr->p_gen,
     162  1188484112 :                 .name_len               = pptr->p_namelen,
     163             :         };
     164  1188484112 :         int                             error;
     165             : 
     166             :         /*
     167             :          * If this path is more than 2 billion steps long, this directory tree
     168             :          * is too far gone to fix.
     169             :          */
     170  1188484112 :         if (path->nr_steps >= XFS_MAXLINK)
     171             :                 return -ELNRNG;
     172             : 
     173  1188484112 :         error = xfblob_store(dl->path_names, &step.name_cookie,
     174  1188484112 :                         dl->pptr.p_name, dl->pptr.p_namelen);
     175  1190217516 :         if (error)
     176             :                 return error;
     177             : 
     178  1190223602 :         error = xino_bitmap_set(&path->seen_inodes, ip->i_ino);
     179  1187746206 :         if (error)
     180             :                 return error;
     181             : 
     182  1187797680 :         error = xfarray_append(dl->path_steps, &step);
     183  1190061183 :         if (error)
     184             :                 return error;
     185             : 
     186  1190061183 :         path->nr_steps++;
     187  1190061183 :         return 0;
     188             : }
     189             : 
     190             : /*
     191             :  * Create an xchk_path for each parent pointer of the directory that we're
     192             :  * scanning.  For each path created, we will eventually try to walk towards the
     193             :  * root with the goal of deleting all parents except for one that leads to the
     194             :  * root.
     195             :  *
     196             :  * Returns -EFSCORRUPTED to signal that the inode being scanned has a corrupt
     197             :  * parent pointer and hence there's no point in continuing; or -ENOSR if there
     198             :  * are too many parent pointers for this directory.
     199             :  */
     200             : STATIC int
     201    13577663 : xchk_dirtree_create_path(
     202             :         struct xfs_scrub                *sc,
     203             :         struct xfs_inode                *ip,
     204             :         const struct xfs_parent_name_irec *pptr,
     205             :         void                            *priv)
     206             : {
     207    13577663 :         struct xchk_dirtree             *dl = priv;
     208    13577663 :         struct xchk_dirpath             *path;
     209    13577663 :         int                             error;
     210             : 
     211             :         /*
     212             :          * If there are more than 2 billion actual parent pointers for this
     213             :          * subdirectory, this fs is too far gone to fix.
     214             :          */
     215    13577663 :         if (dl->nr_paths >= XFS_MAXLINK)
     216             :                 return -ENOSR;
     217             : 
     218    13577663 :         trace_xchk_dirtree_create_path(sc, ip, dl->nr_paths, pptr);
     219             : 
     220             :         /*
     221             :          * Create a new xchk_path structure to remember this parent pointer
     222             :          * and record the first name step.
     223             :          */
     224    13577217 :         path = kmalloc(sizeof(struct xchk_dirpath), XCHK_GFP_FLAGS);
     225    13575779 :         if (!path)
     226             :                 return -ENOMEM;
     227             : 
     228    13575779 :         INIT_LIST_HEAD(&path->list);
     229    13575779 :         xino_bitmap_init(&path->seen_inodes);
     230    13573402 :         path->nr_steps = 0;
     231    13573402 :         path->outcome = XCHK_DIRPATH_SCANNING;
     232             : 
     233    13573402 :         error = xchk_dirpath_append(dl, sc->ip, path, pptr);
     234    13565436 :         if (error)
     235           0 :                 goto out_path;
     236             : 
     237    13565436 :         path->first_step = xfarray_length(dl->path_steps) - 1;
     238    13561117 :         path->second_step = XFARRAY_NULLIDX;
     239    13561117 :         path->path_nr = dl->nr_paths;
     240             : 
     241    13561117 :         list_add_tail(&path->list, &dl->path_list);
     242    13558345 :         dl->nr_paths++;
     243    13558345 :         return 0;
     244             : out_path:
     245           0 :         kfree(path);
     246           0 :         return error;
     247             : }
     248             : 
     249             : /*
     250             :  * Validate that the first step of this path still has a corresponding
     251             :  * parent pointer in @sc->ip.  We probably dropped @sc->ip's ILOCK while
     252             :  * walking towards the roots, which is why this is necessary.
     253             :  *
     254             :  * This function has a side effect of loading the first parent pointer of this
     255             :  * path into the parent pointer scratch pad.  This prepares us to walk up the
     256             :  * directory tree towards the root.  Returns -ESTALE if the scan data is now
     257             :  * out of date.
     258             :  */
     259             : STATIC int
     260    13561639 : xchk_dirpath_revalidate(
     261             :         struct xchk_dirtree             *dl,
     262             :         struct xchk_dirpath             *path)
     263             : {
     264    13561639 :         struct xchk_dirpath_step        step;
     265    13561639 :         struct xfs_scrub                *sc = dl->sc;
     266    13561639 :         int                             error;
     267             : 
     268    13561639 :         error = xfarray_load(dl->path_steps, path->first_step, &step);
     269    13580872 :         if (error)
     270             :                 return error;
     271             : 
     272             :         /*
     273             :          * Check that this parent pointer is still attached to the inode that
     274             :          * we're scanning/
     275             :          */
     276    13580428 :         dl->pptr.p_ino = step.parent_ino;
     277    13580428 :         dl->pptr.p_gen = step.parent_gen;
     278    13580428 :         dl->pptr.p_namelen = step.name_len;
     279             : 
     280    13580428 :         error = xfblob_load(dl->path_names, step.name_cookie, dl->pptr.p_name,
     281             :                         step.name_len);
     282    13586775 :         if (error)
     283             :                 return error;
     284    13586776 :         xfs_parent_irec_hashname(sc->mp, &dl->pptr);
     285             : 
     286             :         /*
     287             :          * Look up the parent pointer that corresponds to the start of this
     288             :          * path.  If the parent pointer has disappeared on us, dump all the
     289             :          * scan results and try again.
     290             :          */
     291    13581685 :         error = xfs_parent_lookup(sc->tp, sc->ip, &dl->pptr, &dl->scratch);
     292    13477477 :         if (error == -ENOATTR) {
     293           0 :                 trace_xchk_dirpath_disappeared(dl->sc, sc->ip, path->path_nr,
     294           0 :                                 path->first_step, &dl->pptr);
     295           0 :                 dl->stale = true;
     296           0 :                 return -ESTALE;
     297             :         }
     298             : 
     299             :         return error;
     300             : }
     301             : 
     302             : /*
     303             :  * Walk the parent pointers of a directory at the end of a path and record
     304             :  * the parent that we find.
     305             :  */
     306             : STATIC int
     307  1174185466 : xchk_dirpath_find_next_step(
     308             :         struct xfs_scrub                *sc,
     309             :         struct xfs_inode                *ip,
     310             :         const struct xfs_parent_name_irec *pptr,
     311             :         void                            *priv)
     312             : {
     313  1174185466 :         unsigned int                    *parents_found = priv;
     314             : 
     315             :         /*
     316             :          * If we've already set @dl->pptr.p_ino, then this directory has
     317             :          * multiple parents.  Signal this back to the caller via -EMLINK.
     318             :          */
     319  1174185466 :         if (*parents_found > 0)
     320             :                 return -EMLINK;
     321             : 
     322  1174185466 :         (*parents_found)++;
     323  1174185466 :         return 0;
     324             : }
     325             : 
     326             : /* Set and log the outcome of a path walk. */
     327             : static inline void
     328             : xchk_dirpath_set_outcome(
     329             :         struct xchk_dirtree             *dl,
     330             :         struct xchk_dirpath             *path,
     331             :         enum xchk_dirpath_outcome       outcome)
     332             : {
     333    13584357 :         trace_xchk_dirpath_set_outcome(dl->sc, path->path_nr, path->nr_steps,
     334             :                         outcome);
     335             : 
     336    13584352 :         path->outcome = outcome;
     337             : }
     338             : 
     339             : /*
     340             :  * Scan the directory at the end of this path for its parent directory link.
     341             :  * If we find one, extend the path.  Returns -ESTALE if the scan data out of
     342             :  * date.  Returns -EFSCORRUPTED if the parent pointer is bad; or -ELNRNG if
     343             :  * the path got too deep.
     344             :  */
     345             : STATIC int
     346  1189976497 : xchk_dirpath_step_up(
     347             :         struct xchk_dirtree     *dl,
     348             :         struct xchk_dirpath     *path)
     349             : {
     350  1189976497 :         struct xfs_scrub        *sc = dl->sc;
     351  1189976497 :         struct xfs_inode        *dp;
     352  1189976497 :         unsigned int            lock_mode;
     353  1189976497 :         unsigned int            parents_found = 0;
     354  1189976497 :         int                     error;
     355             : 
     356             :         /* Grab and lock the parent directory. */
     357  1189976497 :         error = xchk_iget(sc, dl->pptr.p_ino, &dp);
     358  1188437009 :         if (error)
     359             :                 return error;
     360             : 
     361  1188471950 :         lock_mode = xfs_ilock_attr_map_shared(dp);
     362  1189481002 :         mutex_lock(&dl->lock);
     363             : 
     364  1190095946 :         if (dl->stale) {
     365        2469 :                 error = -ESTALE;
     366        2469 :                 goto out_scanlock;
     367             :         }
     368             : 
     369             :         /* We've reached the root directory; the path is ok. */
     370  1190093477 :         if (dl->pptr.p_ino == dl->root_ino) {
     371    13584357 :                 xchk_dirpath_set_outcome(dl, path, XCHK_DIRPATH_OK);
     372    13584352 :                 error = 0;
     373    13584352 :                 goto out_scanlock;
     374             :         }
     375             : 
     376             :         /*
     377             :          * The inode being scanned is its own distant ancestor!  Get rid of
     378             :          * this path.
     379             :          */
     380  1176509120 :         if (dl->pptr.p_ino == sc->ip->i_ino) {
     381           0 :                 xchk_dirpath_set_outcome(dl, path, XCHK_DIRPATH_DELETE);
     382           0 :                 error = 0;
     383           0 :                 goto out_scanlock;
     384             :         }
     385             : 
     386             :         /*
     387             :          * We've seen this inode before during the path walk.  There's a loop
     388             :          * above us in the directory tree.  This probably means that we cannot
     389             :          * continue, but let's keep walking paths to get a full picture.
     390             :          */
     391  1176509120 :         if (xino_bitmap_test(&path->seen_inodes, dl->pptr.p_ino)) {
     392           0 :                 xchk_dirpath_set_outcome(dl, path, XCHK_DIRPATH_LOOP);
     393           0 :                 error = 0;
     394           0 :                 goto out_scanlock;
     395             :         }
     396             : 
     397             :         /* The handle encoded in the parent pointer must match. */
     398  1174352681 :         if (VFS_I(dp)->i_generation != dl->pptr.p_gen) {
     399           0 :                 trace_xchk_dirpath_badgen(dl->sc, dp, path->path_nr,
     400           0 :                                 path->nr_steps, &dl->pptr);
     401           0 :                 error = -EFSCORRUPTED;
     402           0 :                 goto out_scanlock;
     403             :         }
     404             : 
     405             :         /* Parent pointer must point up to a directory. */
     406  1174352681 :         if (!S_ISDIR(VFS_I(dp)->i_mode)) {
     407           0 :                 trace_xchk_dirpath_nondir_parent(dl->sc, dp, path->path_nr,
     408           0 :                                 path->nr_steps, &dl->pptr);
     409           0 :                 error = -EFSCORRUPTED;
     410           0 :                 goto out_scanlock;
     411             :         }
     412             : 
     413             :         /* Parent cannot be an unlinked directory. */
     414  1174352681 :         if (VFS_I(dp)->i_nlink == 0) {
     415           0 :                 trace_xchk_dirpath_unlinked_parent(dl->sc, dp, path->path_nr,
     416           0 :                                 path->nr_steps, &dl->pptr);
     417           0 :                 error = -EFSCORRUPTED;
     418           0 :                 goto out_scanlock;
     419             :         }
     420             : 
     421             :         /*
     422             :          * Walk the parent pointers of @dp to find the parent of this directory
     423             :          * to find the next step in our walk.  If we find that @dp has exactly
     424             :          * one parent, the parent pointer information will be in @dl->pptr.
     425             :          */
     426  1174352681 :         mutex_unlock(&dl->lock);
     427  1172610282 :         error = xchk_pptr_walk(sc, dp, xchk_dirpath_find_next_step, &dl->pptr,
     428             :                         &parents_found);
     429  1174165074 :         mutex_lock(&dl->lock);
     430  1175000357 :         if (error == -EFSCORRUPTED || error == -EMLINK ||
     431  1175414150 :             (!error && parents_found == 0)) {
     432             :                 /*
     433             :                  * Further up the directory tree from @sc->ip, we found a
     434             :                  * corrupt parent pointer, multiple parent pointers while
     435             :                  * finding this directory's parent, or zero parents despite
     436             :                  * having a nonzero link count.  Keep looking for other paths.
     437             :                  */
     438           0 :                 xchk_dirpath_set_outcome(dl, path, XCHK_DIRPATH_CORRUPT);
     439           0 :                 error = 0;
     440           0 :                 goto out_scanlock;
     441             :         }
     442  1175000357 :         if (error)
     443           0 :                 goto out_scanlock;
     444             : 
     445  1175000357 :         if (dl->stale) {
     446         413 :                 error = -ESTALE;
     447         413 :                 goto out_scanlock;
     448             :         }
     449             : 
     450  1174999944 :         trace_xchk_dirpath_found_next_step(sc, dp, path->path_nr,
     451             :                         path->nr_steps, &dl->pptr);
     452             : 
     453             :         /* Append to the path steps */
     454  1174990484 :         error = xchk_dirpath_append(dl, dp, path, &dl->pptr);
     455  1176486654 :         if (error)
     456           0 :                 goto out_scanlock;
     457             : 
     458  1176486654 :         if (path->second_step == XFARRAY_NULLIDX)
     459    13554841 :                 path->second_step = xfarray_length(dl->path_steps) - 1;
     460             : 
     461  1162931813 : out_scanlock:
     462  1190073021 :         mutex_unlock(&dl->lock);
     463  1187333418 :         xfs_iunlock(dp, lock_mode);
     464  1189904896 :         xchk_irele(sc, dp);
     465  1189904896 :         return error;
     466             : }
     467             : 
     468             : /*
     469             :  * Walk the directory tree upwards towards what is hopefully the root
     470             :  * directory, recording path steps as we go.  Returns -ESTALE if the scan data
     471             :  * are out of date.  Returns -EFSCORRUPTED only if the direct parent pointer of
     472             :  * @sc->ip associated with this path is corrupt.
     473             :  */
     474             : STATIC int
     475    13566422 : xchk_dirpath_walk_upwards(
     476             :         struct xchk_dirtree     *dl,
     477             :         struct xchk_dirpath     *path)
     478             : {
     479    13566422 :         struct xfs_scrub        *sc = dl->sc;
     480    13566422 :         int                     error;
     481             : 
     482    13566422 :         ASSERT(sc->ilock_flags & XFS_ILOCK_EXCL);
     483             : 
     484             :         /* Reload the start of this path and make sure it's still there. */
     485    13566422 :         error = xchk_dirpath_revalidate(dl, path);
     486    13490731 :         if (error)
     487             :                 return error;
     488             : 
     489    13502336 :         trace_xchk_dirpath_walk_upwards(sc, sc->ip, path->path_nr, &dl->pptr);
     490             : 
     491             :         /*
     492             :          * The inode being scanned is its own direct ancestor!
     493             :          * Get rid of this path.
     494             :          */
     495    13506750 :         if (dl->pptr.p_ino == sc->ip->i_ino) {
     496           0 :                 xchk_dirpath_set_outcome(dl, path, XCHK_DIRPATH_DELETE);
     497           0 :                 return 0;
     498             :         }
     499             : 
     500             :         /*
     501             :          * Drop ILOCK_EXCL on the inode being scanned.  We still hold
     502             :          * IOLOCK_EXCL on it, so it cannot move around or be renamed.
     503             :          *
     504             :          * Beyond this point we're walking up the directory tree, which means
     505             :          * that we can acquire and drop the ILOCK on an alias of sc->ip.  The
     506             :          * ILOCK state is no longer tracked in the scrub context.  Hence we
     507             :          * must drop @sc->ip's ILOCK during the walk.
     508             :          */
     509    13506750 :         mutex_unlock(&dl->lock);
     510    13457265 :         xchk_iunlock(sc, XFS_ILOCK_EXCL);
     511             : 
     512             :         /*
     513             :          * Take the first step in the walk towards the root by checking the
     514             :          * start of this path, which is a direct parent pointer of @sc->ip.
     515             :          * If we see any kind of error here (including corruptions), the parent
     516             :          * pointer of @sc->ip is corrupt.  Stop the whole scan.
     517             :          */
     518    13499047 :         error = xchk_dirpath_step_up(dl, path);
     519    13583759 :         if (error) {
     520           0 :                 xchk_ilock(sc, XFS_ILOCK_EXCL);
     521           0 :                 mutex_lock(&dl->lock);
     522           0 :                 return error;
     523             :         }
     524             : 
     525             :         /*
     526             :          * Take steps upward from the second step in this path towards the
     527             :          * root.  If we hit corruption errors here, there's a problem
     528             :          * *somewhere* in the path, but we don't need to stop scanning.
     529             :          */
     530  1190134906 :         while (!error && path->outcome == XCHK_DIRPATH_SCANNING)
     531  1176547773 :                 error = xchk_dirpath_step_up(dl, path);
     532             : 
     533             :         /* Retake the locks we had, mark paths, etc. */
     534    13587133 :         xchk_ilock(sc, XFS_ILOCK_EXCL);
     535    13587240 :         mutex_lock(&dl->lock);
     536    13587255 :         if (error == -EFSCORRUPTED) {
     537           0 :                 xchk_dirpath_set_outcome(dl, path, XCHK_DIRPATH_CORRUPT);
     538           0 :                 error = 0;
     539             :         }
     540    13587255 :         if (!error && dl->stale)
     541          26 :                 return -ESTALE;
     542             :         return error;
     543             : }
     544             : 
     545             : /*
     546             :  * Decide if this path step has been touched by this live update.  Returns
     547             :  * 1 for yes, 0 for no, or a negative errno.
     548             :  */
     549             : STATIC int
     550      127711 : xchk_dirpath_step_is_stale(
     551             :         struct xchk_dirtree             *dl,
     552             :         struct xchk_dirpath             *path,
     553             :         unsigned int                    step_nr,
     554             :         xfarray_idx_t                   step_idx,
     555             :         struct xfs_dir_update_params    *p,
     556             :         struct xchk_dirpath_step        *step)
     557             : {
     558      127711 :         xfs_ino_t                       child_ino = step->parent_ino;
     559      127711 :         int                             error;
     560             : 
     561      127711 :         error = xfarray_load(dl->path_steps, step_idx, step);
     562      127711 :         if (error)
     563             :                 return error;
     564             : 
     565             :         /*
     566             :          * If the parent and child being updated are not the ones mentioned in
     567             :          * this path step, the scan data is still ok.
     568             :          */
     569      127711 :         if (p->ip->i_ino != child_ino || p->dp->i_ino != step->parent_ino)
     570             :                 return 0;
     571             : 
     572             :         /*
     573             :          * If the dirent name lengths or byte sequences are different, the scan
     574             :          * data is still ok.
     575             :          */
     576        3668 :         if (p->name->len != step->name_len)
     577             :                 return 0;
     578             : 
     579        3668 :         error = xfblob_load(dl->path_names, step->name_cookie,
     580        3668 :                         dl->hook_namebuf, step->name_len);
     581        3668 :         if (error)
     582             :                 return error;
     583             : 
     584        7336 :         if (memcmp(dl->hook_namebuf, p->name->name, p->name->len) != 0)
     585             :                 return 0;
     586             : 
     587             :         /*
     588             :          * If the update comes from the repair code itself, walk the state
     589             :          * machine forward.
     590             :          */
     591        3668 :         if (p->ip->i_ino == dl->scan_ino &&
     592          28 :             path->outcome == XREP_DIRPATH_ADOPTING) {
     593           0 :                 xchk_dirpath_set_outcome(dl, path, XREP_DIRPATH_ADOPTED);
     594           0 :                 return 0;
     595             :         }
     596             : 
     597        3668 :         if (p->ip->i_ino == dl->scan_ino &&
     598          28 :             path->outcome == XREP_DIRPATH_DELETING) {
     599           0 :                 xchk_dirpath_set_outcome(dl, path, XREP_DIRPATH_DELETED);
     600           0 :                 return 0;
     601             :         }
     602             : 
     603             :         /* Exact match, scan data is out of date. */
     604        3668 :         trace_xchk_dirpath_changed(dl->sc, path->path_nr, step_nr, p->dp,
     605             :                         p->ip, p->name);
     606        3668 :         return 1;
     607             : }
     608             : 
     609             : /*
     610             :  * Decide if this path has been touched by this live update.  Returns 1 for
     611             :  * yes, 0 for no, or a negative errno.
     612             :  */
     613             : STATIC int
     614    10624039 : xchk_dirpath_is_stale(
     615             :         struct xchk_dirtree             *dl,
     616             :         struct xchk_dirpath             *path,
     617             :         struct xfs_dir_update_params    *p)
     618             : {
     619    10624039 :         struct xchk_dirpath_step        step = {
     620    10624039 :                 .parent_ino             = dl->scan_ino,
     621             :         };
     622    10624039 :         xfarray_idx_t                   idx = path->first_step;
     623    10624039 :         unsigned int                    i;
     624    10624039 :         int                             ret;
     625             : 
     626             :         /*
     627             :          * The child being updated has not been seen by this path at all; this
     628             :          * path cannot be stale.
     629             :          */
     630    10624039 :         if (!xino_bitmap_test(&path->seen_inodes, p->ip->i_ino))
     631             :                 return 0;
     632             : 
     633        3668 :         ret = xchk_dirpath_step_is_stale(dl, path, 0, idx, p, &step);
     634        3668 :         if (ret != 0)
     635             :                 return ret;
     636             : 
     637      124043 :         for (i = 1, idx = path->second_step; i < path->nr_steps; i++, idx++) {
     638      124043 :                 ret = xchk_dirpath_step_is_stale(dl, path, i, idx, p, &step);
     639      124043 :                 if (ret != 0)
     640        3640 :                         return ret;
     641             :         }
     642             : 
     643             :         return 0;
     644             : }
     645             : 
     646             : /*
     647             :  * Decide if a directory update from the regular filesystem touches any of the
     648             :  * paths we've scanned, and invalidate the scan data if true.
     649             :  */
     650             : STATIC int
     651    10877525 : xchk_dirtree_live_update(
     652             :         struct notifier_block           *nb,
     653             :         unsigned long                   action,
     654             :         void                            *data)
     655             : {
     656    10877525 :         struct xfs_dir_update_params    *p = data;
     657    10877525 :         struct xchk_dirtree             *dl;
     658    10877525 :         struct xchk_dirpath             *path;
     659    10877525 :         int                             ret;
     660             : 
     661    10877525 :         dl = container_of(nb, struct xchk_dirtree, hooks.dirent_hook.nb);
     662             : 
     663    10877525 :         trace_xchk_dirtree_live_update(dl->sc, p->dp, action, p->ip, p->delta,
     664             :                         p->name);
     665             : 
     666    10877522 :         mutex_lock(&dl->lock);
     667             : 
     668    10877562 :         if (dl->stale || dl->aborted)
     669      253170 :                 goto out_unlock;
     670             : 
     671    21244766 :         xchk_dirtree_for_each_path(dl, path) {
     672    10624047 :                 ret = xchk_dirpath_is_stale(dl, path, p);
     673    10624042 :                 if (ret < 0) {
     674           0 :                         dl->aborted = true;
     675           0 :                         break;
     676             :                 }
     677    10624042 :                 if (ret == 1) {
     678        3668 :                         dl->stale = true;
     679        3668 :                         break;
     680             :                 }
     681             :         }
     682             : 
     683    10620719 : out_unlock:
     684    10877557 :         mutex_unlock(&dl->lock);
     685    10877532 :         return NOTIFY_DONE;
     686             : }
     687             : 
     688             : /* Delete all the collected path information. */
     689             : STATIC void
     690    13598508 : xchk_dirtree_reset(
     691             :         void                    *buf)
     692             : {
     693    13598508 :         struct xchk_dirtree     *dl = buf;
     694    13598508 :         struct xchk_dirpath     *path, *n;
     695             : 
     696    13598508 :         ASSERT(dl->sc->ilock_flags & XFS_ILOCK_EXCL);
     697             : 
     698    13597754 :         xchk_dirtree_for_each_path_safe(dl, path, n) {
     699        2908 :                 list_del_init(&path->list);
     700        2908 :                 xino_bitmap_destroy(&path->seen_inodes);
     701        2908 :                 kfree(path);
     702             :         }
     703    13594846 :         dl->nr_paths = 0;
     704             : 
     705    13594846 :         xfarray_truncate(dl->path_steps);
     706    13589966 :         xfblob_truncate(dl->path_names);
     707             : 
     708    13598644 :         dl->stale = false;
     709    13598644 : }
     710             : 
     711             : /*
     712             :  * For each parent pointer of this subdir, trace a path upwards towards the
     713             :  * root directory and record what we find.  Returns 0 for success;
     714             :  * -EFSCORRUPTED if walking the parent pointers of @sc->ip failed, -ELNRNG if a
     715             :  * path was too deep; -ENOSR if there were too many parent pointers; or
     716             :  * a negative errno.
     717             :  */
     718             : int
     719    13595361 : xchk_dirtree_find_paths_to_root(
     720             :         struct xchk_dirtree     *dl)
     721             : {
     722    13595361 :         struct xfs_scrub        *sc = dl->sc;
     723    13595361 :         struct xchk_dirpath     *path;
     724    13595361 :         int                     error = 0;
     725             : 
     726    13598240 :         do {
     727    13598240 :                 if (xchk_should_terminate(sc, &error))
     728           1 :                         return error;
     729             : 
     730    13598323 :                 xchk_dirtree_reset(dl);
     731             : 
     732             :                 /*
     733             :                  * Create path walk contexts for each parent of the directory
     734             :                  * that is being scanned.  Directories are supposed to have
     735             :                  * only one parent, but this is how we detect multiple parents.
     736             :                  */
     737    13598620 :                 error = xchk_pptr_walk(sc, sc->ip, xchk_dirtree_create_path,
     738             :                                 &dl->pptr, dl);
     739    13572330 :                 if (error)
     740           0 :                         return error;
     741             : 
     742    27156657 :                 xchk_dirtree_for_each_path(dl, path) {
     743             :                         /*
     744             :                          * Try to walk up each path to the root.  This enables
     745             :                          * us to find directory loops in ancestors, and the
     746             :                          * like.
     747             :                          */
     748    13558678 :                         error = xchk_dirpath_walk_upwards(dl, path);
     749    13587235 :                         if (error == -EFSCORRUPTED) {
     750             :                                 /*
     751             :                                  * A parent pointer of @sc->ip is bad, don't
     752             :                                  * bother continuing.
     753             :                                  */
     754             :                                 break;
     755             :                         }
     756    13587235 :                         if (error == -ESTALE) {
     757             :                                 /* This had better be an invalidation. */
     758        2908 :                                 ASSERT(dl->stale);
     759             :                                 break;
     760             :                         }
     761    13584327 :                         if (error)
     762           0 :                                 return error;
     763    13584327 :                         if (dl->aborted)
     764             :                                 return 0;
     765             :                 }
     766    13600887 :         } while (dl->stale);
     767             : 
     768    13598008 :         return error;
     769             : }
     770             : 
     771             : /*
     772             :  * Figure out what to do with the paths we tried to find.  Do not call this
     773             :  * if the scan results are stale.
     774             :  */
     775             : void
     776    13767472 : xchk_dirtree_evaluate(
     777             :         struct xchk_dirtree             *dl,
     778             :         struct xchk_dirtree_outcomes    *oc)
     779             : {
     780    13767472 :         struct xchk_dirpath             *path;
     781             : 
     782    13767472 :         ASSERT(!dl->stale);
     783             : 
     784             :         /* Scan the paths we have to decide what to do. */
     785    13767472 :         memset(oc, 0, sizeof(struct xchk_dirtree_outcomes));
     786    27519413 :         xchk_dirtree_for_each_path(dl, path) {
     787    13752033 :                 trace_xchk_dirpath_evaluate_path(dl->sc, path->path_nr,
     788    13752033 :                                 path->nr_steps, path->outcome);
     789             : 
     790    13751941 :                 switch (path->outcome) {
     791           0 :                 case XCHK_DIRPATH_SCANNING:
     792             :                         /* shouldn't get here */
     793           0 :                         ASSERT(0);
     794           0 :                         break;
     795           0 :                 case XCHK_DIRPATH_DELETE:
     796             :                         /* This one is already going away. */
     797           0 :                         oc->bad++;
     798           0 :                         break;
     799           0 :                 case XCHK_DIRPATH_CORRUPT:
     800             :                 case XCHK_DIRPATH_LOOP:
     801             :                         /* Couldn't find the end of this path. */
     802           0 :                         oc->suspect++;
     803           0 :                         break;
     804           0 :                 case XCHK_DIRPATH_STALE:
     805             :                         /* shouldn't get here either */
     806           0 :                         ASSERT(0);
     807           0 :                         break;
     808    13751941 :                 case XCHK_DIRPATH_OK:
     809             :                         /* This path got all the way to the root. */
     810    13751941 :                         oc->good++;
     811    13751941 :                         break;
     812           0 :                 case XREP_DIRPATH_DELETING:
     813             :                 case XREP_DIRPATH_DELETED:
     814             :                 case XREP_DIRPATH_ADOPTING:
     815             :                 case XREP_DIRPATH_ADOPTED:
     816             :                         /* These should not be in progress! */
     817           0 :                         ASSERT(0);
     818           0 :                         break;
     819             :                 }
     820             :         }
     821             : 
     822    13767380 :         trace_xchk_dirtree_evaluate(dl, oc);
     823    13767287 : }
     824             : 
     825             : /* Dump a path step. */
     826             : STATIC void
     827           0 : xchk_dirpath_step_dump(
     828             :         struct xchk_dirtree             *dl,
     829             :         struct xchk_dirpath             *path,
     830             :         xfarray_idx_t                   idx,
     831             :         unsigned int                    step_nr)
     832             : {
     833           0 :         struct xchk_dirpath_step        step;
     834           0 :         struct xfs_scrub                *sc = dl->sc;
     835           0 :         int                             error;
     836             : 
     837           0 :         error = xfarray_load(dl->path_steps, idx, &step);
     838           0 :         if (error)
     839           0 :                 return;
     840             : 
     841           0 :         error = xfblob_load(dl->path_names, step.name_cookie, dl->pptr.p_name,
     842             :                         step.name_len);
     843           0 :         if (error)
     844             :                 return;
     845             : 
     846           0 :         xfs_err(sc->mp, "    scan_ino 0x%llx path %u step %u parent_ino 0x%llx parent_gen 0x%x name '%.*s'",
     847             :                         sc->ip->i_ino, path->path_nr, step_nr, step.parent_ino,
     848             :                         step.parent_gen, step.name_len, dl->pptr.p_name);
     849             : }
     850             : 
     851             : /* Dump a path. */
     852             : STATIC void
     853           0 : xchk_dirpath_dump(
     854             :         struct xchk_dirtree     *dl,
     855             :         struct xchk_dirpath     *path)
     856             : {
     857           0 :         struct xfs_scrub        *sc = dl->sc;
     858           0 :         xfarray_idx_t           idx;
     859           0 :         unsigned int            i;
     860             : 
     861           0 :         xfs_err(sc->mp, "  scan_ino 0x%llx path %u outcome %u",
     862             :                         dl->scan_ino, path->path_nr, path->outcome);
     863             : 
     864           0 :         if (path->nr_steps > 0)
     865           0 :                 xchk_dirpath_step_dump(dl, path, path->first_step, 0);
     866             : 
     867           0 :         for (i = 1, idx = path->second_step; i < path->nr_steps; i++, idx++)
     868           0 :                 xchk_dirpath_step_dump(dl, path, idx, i);
     869           0 : }
     870             : 
     871             : STATIC int
     872           0 : xchk_dirtree_dump_dirent(
     873             :         struct xfs_scrub        *sc,
     874             :         struct xfs_inode        *dp,
     875             :         xfs_dir2_dataptr_t      dapos,
     876             :         const struct xfs_name   *name,
     877             :         xfs_ino_t               ino,
     878             :         void                    *priv)
     879             : {
     880           0 :         unsigned int            *nrp = priv;
     881             : 
     882           0 :         if (name->type == XFS_DIR3_FT_UNKNOWN ||
     883             :             name->type == XFS_DIR3_FT_DIR)
     884           0 :                 xfs_err(sc->mp, "    scan_ino 0x%llx dirent %u ino 0x%llx name '%.*s' type %u",
     885             :                                 dp->i_ino, (*nrp)++, ino, name->len,
     886             :                                 name->name, name->type);
     887           0 :         return 0;
     888             : }
     889             : 
     890             : STATIC int
     891           0 : xchk_dirtree_dump_pptr(
     892             :         struct xfs_scrub                *sc,
     893             :         struct xfs_inode                *ip,
     894             :         const struct xfs_parent_name_irec *pptr,
     895             :         void                            *priv)
     896             : {
     897           0 :         unsigned int                    *nrp = priv;
     898             : 
     899           0 :         xfs_err(sc->mp, "    scan_ino 0x%llx pptr %u ino 0x%llx name '%.*s'",
     900             :                         ip->i_ino, (*nrp)++, pptr->p_ino, pptr->p_namelen,
     901             :                         pptr->p_name);
     902           0 :         return 0;
     903             : }
     904             : 
     905             : /* Dump all paths. */
     906             : STATIC void
     907           0 : xchk_dirtree_dump(
     908             :         struct xchk_dirtree     *dl,
     909             :         struct xchk_dirtree_outcomes *oc)
     910             : {
     911           0 :         struct xfs_scrub        *sc = dl->sc;
     912           0 :         struct xchk_dirpath     *path;
     913           0 :         unsigned int            nr;
     914             : 
     915           0 :         xfs_err(sc->mp, "scan_ino 0x%llx parentless? %d nlink %u root_ino 0x%llx paths %u stale? %d aborted? %d",
     916             :                         dl->scan_ino, xchk_dirtree_parentless(dl),
     917             :                         VFS_I(sc->ip)->i_nlink,
     918             :                         dl->root_ino, dl->nr_paths, dl->stale, dl->aborted);
     919           0 :         xfs_err(sc->mp, "  scan_ino 0x%llx good %u bad %u suspect %u",
     920             :                         dl->scan_ino, oc->good, oc->bad, oc->suspect);
     921             : 
     922           0 :         xchk_dirtree_for_each_path(dl, path) {
     923           0 :                 xchk_dirpath_dump(dl, path);
     924             :         }
     925             : 
     926           0 :         xfs_err(sc->mp, "  scan_ino 0x%llx dirents", sc->ip->i_ino);
     927           0 :         nr = 0;
     928           0 :         xchk_dir_walk(sc, sc->ip, xchk_dirtree_dump_dirent, &nr);
     929             : 
     930           0 :         xfs_err(sc->mp, "  scan_ino 0x%llx pptrs", sc->ip->i_ino);
     931           0 :         nr = 0;
     932           0 :         xchk_pptr_walk(sc, sc->ip, xchk_dirtree_dump_pptr, &dl->pptr, &nr);
     933           0 : }
     934             : 
     935             : /* Look for directory loops. */
     936             : int
     937    13587951 : xchk_dirtree(
     938             :         struct xfs_scrub                *sc)
     939             : {
     940    13587951 :         struct xchk_dirtree_outcomes    oc;
     941    13587951 :         struct xchk_dirtree             *dl = sc->buf;
     942    13587951 :         int                             error;
     943             : 
     944             :         /*
     945             :          * Nondirectories do not point downwards to other files, so they cannot
     946             :          * cause a cycle in the directory tree.
     947             :          */
     948    13587951 :         if (!S_ISDIR(VFS_I(sc->ip)->i_mode))
     949             :                 return -ENOENT;
     950             : 
     951    13587951 :         ASSERT(xfs_has_parent(sc->mp));
     952             : 
     953             :         /*
     954             :          * Find the root of the directory tree.  Remember which directory to
     955             :          * scan, because the hook doesn't detach until after sc->ip gets
     956             :          * released during teardown.
     957             :          */
     958    13587951 :         dl->root_ino = sc->mp->m_rootip->i_ino;
     959    13587951 :         dl->scan_ino = sc->ip->i_ino;
     960             : 
     961    13587951 :         trace_xchk_dirtree_start(sc->ip, sc->sm, 0);
     962             : 
     963    13582854 :         mutex_lock(&dl->lock);
     964             :         /*
     965             :          * Hook into the directory entry code so that we can capture updates to
     966             :          * paths that we have already scanned.  The scanner thread takes each
     967             :          * directory's ILOCK, which means that any in-progress directory update
     968             :          * will finish before we can scan the directory.
     969             :          */
     970    13584488 :         ASSERT(sc->flags & XCHK_FSGATES_DIRENTS);
     971    13584488 :         xfs_hook_setup(&dl->hooks.dirent_hook, xchk_dirtree_live_update);
     972    13584488 :         error = xfs_dir_hook_add(sc->mp, &dl->hooks);
     973    13593547 :         if (error)
     974           0 :                 goto out_scanlock;
     975             : 
     976             :         /* Trace each parent pointer's path to the root. */
     977    13593547 :         error = xchk_dirtree_find_paths_to_root(dl);
     978    13597920 :         if (error == -EFSCORRUPTED || error == -ELNRNG || error == -ENOSR) {
     979             :                 /*
     980             :                  * Don't bother walking the paths if the xattr structure or the
     981             :                  * parent pointers are corrupt; this scan cannot be completed
     982             :                  * without full information.
     983             :                  */
     984           0 :                 xchk_ino_xref_set_corrupt(sc, sc->ip->i_ino);
     985           0 :                 error = 0;
     986           0 :                 goto out_scanlock;
     987             :         }
     988    13597920 :         if (error)
     989           1 :                 goto out_scanlock;
     990    13597919 :         if (dl->aborted) {
     991           0 :                 xchk_set_incomplete(sc);
     992           0 :                 goto out_scanlock;
     993             :         }
     994             : 
     995             :         /* Assess what we found in our path evaluation. */
     996    13597919 :         xchk_dirtree_evaluate(dl, &oc);
     997    13597485 :         if (xchk_dirtree_parentless(dl)) {
     998       13655 :                 if (oc.good || oc.bad || oc.suspect)
     999           0 :                         xchk_ino_set_corrupt(sc, sc->ip->i_ino);
    1000             : 
    1001       13655 :                 if (oc.good || oc.bad || oc.suspect)
    1002           0 :                         xchk_dirtree_dump(dl, &oc);
    1003             :         } else {
    1004    13583830 :                 if (oc.bad || oc.good + oc.suspect != 1)
    1005          14 :                         xchk_ino_set_corrupt(sc, sc->ip->i_ino);
    1006    13583986 :                 if (oc.suspect)
    1007           0 :                         xchk_ino_xref_set_corrupt(sc, sc->ip->i_ino);
    1008             : 
    1009    13583986 :                 if (oc.bad || oc.good + oc.suspect != 1 || oc.suspect)
    1010          73 :                         xchk_dirtree_dump(dl, &oc);
    1011             :         }
    1012             : 
    1013    13583918 : out_scanlock:
    1014    13597574 :         mutex_unlock(&dl->lock);
    1015    13597366 :         trace_xchk_dirtree_done(sc->ip, sc->sm, error);
    1016    13597366 :         return error;
    1017             : }

Generated by: LCOV version 1.14