Warning: This file is not a C or C++ file. It does not have highlighting.
| 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 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 | struct xfs_parent_rec pptr_rec; |
| 20 | }; |
| 21 | |
| 22 | enum 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 being |
| 38 | * scanned. These exist in-core, and hopefully there aren't more than a |
| 39 | * handful of them. |
| 40 | */ |
| 41 | struct 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 | |
| 63 | struct 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 | |
| 77 | struct 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 can |
| 85 | * continue to be called after xchk_teardown drops sc->ip but before |
| 86 | * 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 is |
| 92 | * the inode number of the surviving parent and the dotdot entry will |
| 93 | * be set to this value. If the value is NULLFSINO, then use @root_ino |
| 94 | * 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 updates |
| 111 | * 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 path |
| 127 | * steps for a particular pathwalk are recorded in sequential |
| 128 | * order in the xfarray. A pathwalk ends either with a step |
| 129 | * pointing to the root directory (success) or pointing to NULLFSINO |
| 130 | * (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 | |
| 159 | bool xchk_dirtree_parentless(const struct xchk_dirtree *dl); |
| 160 | |
| 161 | int xchk_dirtree_find_paths_to_root(struct xchk_dirtree *dl); |
| 162 | int xchk_dirpath_append(struct xchk_dirtree *dl, struct xfs_inode *ip, |
| 163 | struct xchk_dirpath *path, const struct xfs_name *name, |
| 164 | const struct xfs_parent_rec *pptr); |
| 165 | void xchk_dirtree_evaluate(struct xchk_dirtree *dl, |
| 166 | struct xchk_dirtree_outcomes *oc); |
| 167 | |
| 168 | #endif /* __XFS_SCRUB_DIRTREE_H__ */ |
| 169 |
Warning: This file is not a C or C++ file. It does not have highlighting.
