179 lines · c
1/* SPDX-License-Identifier: GPL-2.0-or-later */2/*3 * Copyright (c) 2023-2024 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 going11 * up towards the directory tree root. These are stored inside an xfarray.12 */13struct 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 struct xfs_parent_rec pptr_rec;20};21 22enum xchk_dirpath_outcome {23 XCHK_DIRPATH_SCANNING = 0, /* still being put together */24 XCHK_DIRPATH_DELETE, /* delete this path */25 XCHK_DIRPATH_CORRUPT, /* corruption detected in path */26 XCHK_DIRPATH_LOOP, /* cycle detected further up */27 XCHK_DIRPATH_STALE, /* path is stale */28 XCHK_DIRPATH_OK, /* path reaches the root */29 30 XREP_DIRPATH_DELETING, /* path is being deleted */31 XREP_DIRPATH_DELETED, /* path has been deleted */32 XREP_DIRPATH_ADOPTING, /* path is being adopted */33 XREP_DIRPATH_ADOPTED, /* path has been adopted */34};35 36/*37 * Each of these represents one parent pointer path out of the directory being38 * scanned. These exist in-core, and hopefully there aren't more than a39 * handful of them.40 */41struct xchk_dirpath {42 struct list_head list;43 44 /* Index of the first step in this path. */45 xfarray_idx_t first_step;46 47 /* Index of the second step in this path. */48 xfarray_idx_t second_step;49 50 /* Inodes seen while walking this path. */51 struct xino_bitmap seen_inodes;52 53 /* Number of steps in this path. */54 unsigned int nr_steps;55 56 /* Which path is this? */57 unsigned int path_nr;58 59 /* What did we conclude from following this path? */60 enum xchk_dirpath_outcome outcome;61};62 63struct xchk_dirtree_outcomes {64 /* Number of XCHK_DIRPATH_DELETE */65 unsigned int bad;66 67 /* Number of XCHK_DIRPATH_CORRUPT or XCHK_DIRPATH_LOOP */68 unsigned int suspect;69 70 /* Number of XCHK_DIRPATH_OK */71 unsigned int good;72 73 /* Directory needs to be added to lost+found */74 bool needs_adoption;75};76 77struct xchk_dirtree {78 struct xfs_scrub *sc;79 80 /* Root inode that we're looking for. */81 xfs_ino_t root_ino;82 83 /*84 * This is the inode that we're scanning. The live update hook can85 * continue to be called after xchk_teardown drops sc->ip but before86 * it calls buf_cleanup, so we keep a copy.87 */88 xfs_ino_t scan_ino;89 90 /*91 * If we start deleting redundant paths to this subdirectory, this is92 * the inode number of the surviving parent and the dotdot entry will93 * be set to this value. If the value is NULLFSINO, then use @root_ino94 * as a stand-in until the orphanage can adopt the subdirectory.95 */96 xfs_ino_t parent_ino;97 98 /* Scratch buffer for scanning pptr xattrs */99 struct xfs_parent_rec pptr_rec;100 struct xfs_da_args pptr_args;101 102 /* Name buffer */103 struct xfs_name xname;104 char namebuf[MAXNAMELEN];105 106 /* Information for reparenting this directory. */107 struct xrep_adoption adoption;108 109 /*110 * Hook into directory updates so that we can receive live updates111 * from other writer threads.112 */113 struct xfs_dir_hook dhook;114 115 /* Parent pointer update arguments. */116 struct xfs_parent_args ppargs;117 118 /* lock for everything below here */119 struct mutex lock;120 121 /* buffer for the live update functions to use for dirent names */122 struct xfs_name hook_xname;123 unsigned char hook_namebuf[MAXNAMELEN];124 125 /*126 * All path steps observed during this scan. Each of the path127 * steps for a particular pathwalk are recorded in sequential128 * order in the xfarray. A pathwalk ends either with a step129 * pointing to the root directory (success) or pointing to NULLFSINO130 * (loop detected, empty dir detected, etc).131 */132 struct xfarray *path_steps;133 134 /* All names observed during this scan. */135 struct xfblob *path_names;136 137 /* All paths being tracked by this scanner. */138 struct list_head path_list;139 140 /* Number of paths in path_list. */141 unsigned int nr_paths;142 143 /* Number of parents found by a pptr scan. */144 unsigned int parents_found;145 146 /* Have the path data been invalidated by a concurrent update? */147 bool stale:1;148 149 /* Has the scan been aborted? */150 bool aborted:1;151};152 153#define xchk_dirtree_for_each_path_safe(dl, path, n) \154 list_for_each_entry_safe((path), (n), &(dl)->path_list, list)155 156#define xchk_dirtree_for_each_path(dl, path) \157 list_for_each_entry((path), &(dl)->path_list, list)158 159static inline bool160xchk_dirtree_parentless(const struct xchk_dirtree *dl)161{162 struct xfs_scrub *sc = dl->sc;163 164 if (sc->ip == sc->mp->m_rootip)165 return true;166 if (VFS_I(sc->ip)->i_nlink == 0)167 return true;168 return false;169}170 171int xchk_dirtree_find_paths_to_root(struct xchk_dirtree *dl);172int xchk_dirpath_append(struct xchk_dirtree *dl, struct xfs_inode *ip,173 struct xchk_dirpath *path, const struct xfs_name *name,174 const struct xfs_parent_rec *pptr);175void xchk_dirtree_evaluate(struct xchk_dirtree *dl,176 struct xchk_dirtree_outcomes *oc);177 178#endif /* __XFS_SCRUB_DIRTREE_H__ */179