LCOV - code coverage report
Current view: top level - fs/xfs/scrub - dirtree.h (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc4-xfsa @ Mon Jul 31 20:08:27 PDT 2023 Lines: 6 6 100.0 %
Date: 2023-07-31 20:08:27 Functions: 1 1 100.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             : #ifndef __XFS_SCRUB_DIRTREE_H__
       7             : #define __XFS_SCRUB_DIRTREE_H__
       8             : 
       9             : /*
      10             :  * Each of these represents one parent pointer path step in a chain going
      11             :  * up towards the directory tree root.  These are stored inside an xfarray.
      12             :  */
      13             : struct xchk_dirpath_step {
      14             :         /* Directory entry name associated with this parent link. */
      15             :         xfblob_cookie           name_cookie;
      16             :         unsigned int            name_len;
      17             : 
      18             :         /* Handle of the parent directory. */
      19             :         unsigned int            parent_gen;
      20             :         xfs_ino_t               parent_ino;
      21             : };
      22             : 
      23             : enum xchk_dirpath_outcome {
      24             :         XCHK_DIRPATH_SCANNING = 0,      /* still being put together */
      25             :         XCHK_DIRPATH_DELETE,            /* delete this path */
      26             :         XCHK_DIRPATH_CORRUPT,           /* corruption detected in path */
      27             :         XCHK_DIRPATH_LOOP,              /* cycle detected further up in the dir tree */
      28             :         XCHK_DIRPATH_STALE,             /* path is stale */
      29             :         XCHK_DIRPATH_OK,                /* path reaches the root */
      30             : 
      31             :         XREP_DIRPATH_DELETING,          /* path is being deleted */
      32             :         XREP_DIRPATH_DELETED,           /* path has been deleted */
      33             :         XREP_DIRPATH_ADOPTING,          /* path is being adopted */
      34             :         XREP_DIRPATH_ADOPTED,           /* path has been adopted */
      35             : };
      36             : 
      37             : /*
      38             :  * Each of these represents one parent pointer path out of the directory being
      39             :  * scanned.  These exist in-core, and hopefully there aren't more than a
      40             :  * handful of them.
      41             :  */
      42             : struct xchk_dirpath {
      43             :         struct list_head        list;
      44             : 
      45             :         /* Index of the first step in this path. */
      46             :         xfarray_idx_t           first_step;
      47             : 
      48             :         /* Index of the second step in this path. */
      49             :         xfarray_idx_t           second_step;
      50             : 
      51             :         /* Inodes seen while walking this path. */
      52             :         struct xino_bitmap      seen_inodes;
      53             : 
      54             :         /* Number of steps in this path. */
      55             :         unsigned int            nr_steps;
      56             : 
      57             :         /* Which path is this? */
      58             :         unsigned int            path_nr;
      59             : 
      60             :         /* What did we conclude from following this path? */
      61             :         enum xchk_dirpath_outcome outcome;
      62             : };
      63             : 
      64             : struct xchk_dirtree_outcomes {
      65             :         /* Number of XCHK_DIRPATH_DELETE */
      66             :         unsigned int                    bad;
      67             : 
      68             :         /* Number of XCHK_DIRPATH_CORRUPT or XCHK_DIRPATH_LOOP */
      69             :         unsigned int                    suspect;
      70             : 
      71             :         /* Number of XCHK_DIRPATH_OK */
      72             :         unsigned int                    good;
      73             : 
      74             :         /* Directory needs to be added to lost+found */
      75             :         bool                            needs_adoption;
      76             : };
      77             : 
      78             : struct xchk_dirtree {
      79             :         struct xfs_scrub        *sc;
      80             : 
      81             :         /* Root inode that we're looking for. */
      82             :         xfs_ino_t               root_ino;
      83             : 
      84             :         /*
      85             :          * This is the inode that we're scanning.  The live update hook can
      86             :          * continue to be called after xchk_teardown drops sc->ip but before
      87             :          * it calls buf_cleanup, so we keep a copy.
      88             :          */
      89             :         xfs_ino_t               scan_ino;
      90             : 
      91             :         /*
      92             :          * If we start deleting redundant paths to this subdirectory, this is
      93             :          * the inode number of the surviving parent and the dotdot entry will
      94             :          * be set to this value.  If the value is NULLFSINO, then use @root_ino
      95             :          * as a stand-in until the orphanage can adopt the subdirectory.
      96             :          */
      97             :         xfs_ino_t               parent_ino;
      98             : 
      99             :         /* Scratch buffer for scanning pptr xattrs */
     100             :         struct xfs_parent_scratch scratch;
     101             :         struct xfs_parent_name_irec pptr;
     102             : 
     103             :         /* Information for reparenting this directory. */
     104             :         struct xrep_adoption    adoption;
     105             : 
     106             :         /*
     107             :          * Hook into directory updates so that we can receive live updates
     108             :          * from other writer threads.
     109             :          */
     110             :         struct xfs_dir_hook     hooks;
     111             : 
     112             :         /* lock for everything below here */
     113             :         struct mutex            lock;
     114             : 
     115             :         /* buffer for the live update functions to use for dirent names */
     116             :         unsigned char           hook_namebuf[MAXNAMELEN];
     117             : 
     118             :         /*
     119             :          * All path steps observed during this scan.  Each of the path
     120             :          * steps for a particular pathwalk are recorded in sequential
     121             :          * order in the xfarray.  A pathwalk ends either with a step
     122             :          * pointing to the root directory (success) or pointing to NULLFSINO
     123             :          * (loop detected, empty dir detected, etc).
     124             :          */
     125             :         struct xfarray          *path_steps;
     126             : 
     127             :         /* All names observed during this scan. */
     128             :         struct xfblob           *path_names;
     129             : 
     130             :         /* All paths being tracked by this scanner. */
     131             :         struct list_head        path_list;
     132             : 
     133             :         /* Number of paths in path_list. */
     134             :         unsigned int            nr_paths;
     135             : 
     136             :         /* Have the path data been invalidated by a concurrent update? */
     137             :         bool                    stale:1;
     138             : 
     139             :         /* Has the scan been aborted? */
     140             :         bool                    aborted:1;
     141             : };
     142             : 
     143             : #define xchk_dirtree_for_each_path_safe(dl, path, n) \
     144             :         list_for_each_entry_safe((path), (n), &(dl)->path_list, list)
     145             : 
     146             : #define xchk_dirtree_for_each_path(dl, path) \
     147             :         list_for_each_entry((path), &(dl)->path_list, list)
     148             : 
     149             : static inline bool
     150    11514108 : xchk_dirtree_parentless(const struct xchk_dirtree *dl)
     151             : {
     152    11514108 :         struct xfs_scrub        *sc = dl->sc;
     153             : 
     154    11514108 :         if (sc->ip == sc->mp->m_rootip)
     155             :                 return true;
     156    11502812 :         if (sc->ip == sc->mp->m_metadirip)
     157             :                 return true;
     158    11502812 :         if (VFS_I(sc->ip)->i_nlink == 0)
     159        2072 :                 return true;
     160             :         return false;
     161             : }
     162             : 
     163             : int xchk_dirtree_find_paths_to_root(struct xchk_dirtree *dl);
     164             : int xchk_dirpath_append(struct xchk_dirtree *dl, struct xfs_inode *ip,
     165             :                 struct xchk_dirpath *path,
     166             :                 const struct xfs_parent_name_irec *pptr);
     167             : void xchk_dirtree_evaluate(struct xchk_dirtree *dl,
     168             :                 struct xchk_dirtree_outcomes *oc);
     169             : 
     170             : #endif /* __XFS_SCRUB_DIRTREE_H__ */

Generated by: LCOV version 1.14