1928b721aSDarrick J. Wong /* SPDX-License-Identifier: GPL-2.0-or-later */ 2928b721aSDarrick J. Wong /* 3928b721aSDarrick J. Wong * Copyright (c) 2023-2024 Oracle. All Rights Reserved. 4928b721aSDarrick J. Wong * Author: Darrick J. Wong <djwong@kernel.org> 5928b721aSDarrick J. Wong */ 6928b721aSDarrick J. Wong #ifndef __XFS_SCRUB_DIRTREE_H__ 7928b721aSDarrick J. Wong #define __XFS_SCRUB_DIRTREE_H__ 8928b721aSDarrick J. Wong 9928b721aSDarrick J. Wong /* 10928b721aSDarrick J. Wong * Each of these represents one parent pointer path step in a chain going 11928b721aSDarrick J. Wong * up towards the directory tree root. These are stored inside an xfarray. 12928b721aSDarrick J. Wong */ 13928b721aSDarrick J. Wong struct xchk_dirpath_step { 14928b721aSDarrick J. Wong /* Directory entry name associated with this parent link. */ 15928b721aSDarrick J. Wong xfblob_cookie name_cookie; 16928b721aSDarrick J. Wong unsigned int name_len; 17928b721aSDarrick J. Wong 18928b721aSDarrick J. Wong /* Handle of the parent directory. */ 19928b721aSDarrick J. Wong struct xfs_parent_rec pptr_rec; 20928b721aSDarrick J. Wong }; 21928b721aSDarrick J. Wong 22928b721aSDarrick J. Wong enum xchk_dirpath_outcome { 23928b721aSDarrick J. Wong XCHK_DIRPATH_SCANNING = 0, /* still being put together */ 24928b721aSDarrick J. Wong XCHK_DIRPATH_DELETE, /* delete this path */ 25928b721aSDarrick J. Wong XCHK_DIRPATH_CORRUPT, /* corruption detected in path */ 26928b721aSDarrick J. Wong XCHK_DIRPATH_LOOP, /* cycle detected further up */ 27928b721aSDarrick J. Wong XCHK_DIRPATH_STALE, /* path is stale */ 28928b721aSDarrick J. Wong XCHK_DIRPATH_OK, /* path reaches the root */ 293f31406aSDarrick J. Wong 303f31406aSDarrick J. Wong XREP_DIRPATH_DELETING, /* path is being deleted */ 313f31406aSDarrick J. Wong XREP_DIRPATH_DELETED, /* path has been deleted */ 323f31406aSDarrick J. Wong XREP_DIRPATH_ADOPTING, /* path is being adopted */ 333f31406aSDarrick J. Wong XREP_DIRPATH_ADOPTED, /* path has been adopted */ 34928b721aSDarrick J. Wong }; 35928b721aSDarrick J. Wong 36928b721aSDarrick J. Wong /* 37928b721aSDarrick J. Wong * Each of these represents one parent pointer path out of the directory being 38928b721aSDarrick J. Wong * scanned. These exist in-core, and hopefully there aren't more than a 39928b721aSDarrick J. Wong * handful of them. 40928b721aSDarrick J. Wong */ 41928b721aSDarrick J. Wong struct xchk_dirpath { 42928b721aSDarrick J. Wong struct list_head list; 43928b721aSDarrick J. Wong 44928b721aSDarrick J. Wong /* Index of the first step in this path. */ 45928b721aSDarrick J. Wong xfarray_idx_t first_step; 46928b721aSDarrick J. Wong 47928b721aSDarrick J. Wong /* Index of the second step in this path. */ 48928b721aSDarrick J. Wong xfarray_idx_t second_step; 49928b721aSDarrick J. Wong 50928b721aSDarrick J. Wong /* Inodes seen while walking this path. */ 51928b721aSDarrick J. Wong struct xino_bitmap seen_inodes; 52928b721aSDarrick J. Wong 53928b721aSDarrick J. Wong /* Number of steps in this path. */ 54928b721aSDarrick J. Wong unsigned int nr_steps; 55928b721aSDarrick J. Wong 56928b721aSDarrick J. Wong /* Which path is this? */ 57928b721aSDarrick J. Wong unsigned int path_nr; 58928b721aSDarrick J. Wong 59928b721aSDarrick J. Wong /* What did we conclude from following this path? */ 60928b721aSDarrick J. Wong enum xchk_dirpath_outcome outcome; 61928b721aSDarrick J. Wong }; 62928b721aSDarrick J. Wong 63928b721aSDarrick J. Wong struct xchk_dirtree_outcomes { 64928b721aSDarrick J. Wong /* Number of XCHK_DIRPATH_DELETE */ 65928b721aSDarrick J. Wong unsigned int bad; 66928b721aSDarrick J. Wong 67928b721aSDarrick J. Wong /* Number of XCHK_DIRPATH_CORRUPT or XCHK_DIRPATH_LOOP */ 68928b721aSDarrick J. Wong unsigned int suspect; 69928b721aSDarrick J. Wong 70928b721aSDarrick J. Wong /* Number of XCHK_DIRPATH_OK */ 71928b721aSDarrick J. Wong unsigned int good; 723f31406aSDarrick J. Wong 733f31406aSDarrick J. Wong /* Directory needs to be added to lost+found */ 743f31406aSDarrick J. Wong bool needs_adoption; 75928b721aSDarrick J. Wong }; 76928b721aSDarrick J. Wong 77928b721aSDarrick J. Wong struct xchk_dirtree { 78928b721aSDarrick J. Wong struct xfs_scrub *sc; 79928b721aSDarrick J. Wong 80928b721aSDarrick J. Wong /* Root inode that we're looking for. */ 81928b721aSDarrick J. Wong xfs_ino_t root_ino; 82928b721aSDarrick J. Wong 83d54c5ac8SDarrick J. Wong /* 84d54c5ac8SDarrick J. Wong * This is the inode that we're scanning. The live update hook can 85d54c5ac8SDarrick J. Wong * continue to be called after xchk_teardown drops sc->ip but before 86d54c5ac8SDarrick J. Wong * it calls buf_cleanup, so we keep a copy. 87d54c5ac8SDarrick J. Wong */ 88d54c5ac8SDarrick J. Wong xfs_ino_t scan_ino; 89d54c5ac8SDarrick J. Wong 903f31406aSDarrick J. Wong /* 913f31406aSDarrick J. Wong * If we start deleting redundant paths to this subdirectory, this is 923f31406aSDarrick J. Wong * the inode number of the surviving parent and the dotdot entry will 933f31406aSDarrick J. Wong * be set to this value. If the value is NULLFSINO, then use @root_ino 943f31406aSDarrick J. Wong * as a stand-in until the orphanage can adopt the subdirectory. 953f31406aSDarrick J. Wong */ 963f31406aSDarrick J. Wong xfs_ino_t parent_ino; 973f31406aSDarrick J. Wong 98928b721aSDarrick J. Wong /* Scratch buffer for scanning pptr xattrs */ 99928b721aSDarrick J. Wong struct xfs_parent_rec pptr_rec; 100928b721aSDarrick J. Wong struct xfs_da_args pptr_args; 101928b721aSDarrick J. Wong 102928b721aSDarrick J. Wong /* Name buffer */ 103928b721aSDarrick J. Wong struct xfs_name xname; 104928b721aSDarrick J. Wong char namebuf[MAXNAMELEN]; 105928b721aSDarrick J. Wong 1063f31406aSDarrick J. Wong /* Information for reparenting this directory. */ 1073f31406aSDarrick J. Wong struct xrep_adoption adoption; 1083f31406aSDarrick J. Wong 109d54c5ac8SDarrick J. Wong /* 110d54c5ac8SDarrick J. Wong * Hook into directory updates so that we can receive live updates 111d54c5ac8SDarrick J. Wong * from other writer threads. 112d54c5ac8SDarrick J. Wong */ 113d54c5ac8SDarrick J. Wong struct xfs_dir_hook dhook; 114d54c5ac8SDarrick J. Wong 1153f31406aSDarrick J. Wong /* Parent pointer update arguments. */ 1163f31406aSDarrick J. Wong struct xfs_parent_args ppargs; 1173f31406aSDarrick J. Wong 118928b721aSDarrick J. Wong /* lock for everything below here */ 119928b721aSDarrick J. Wong struct mutex lock; 120928b721aSDarrick J. Wong 121d54c5ac8SDarrick J. Wong /* buffer for the live update functions to use for dirent names */ 122d54c5ac8SDarrick J. Wong struct xfs_name hook_xname; 123d54c5ac8SDarrick J. Wong unsigned char hook_namebuf[MAXNAMELEN]; 124d54c5ac8SDarrick J. Wong 125928b721aSDarrick J. Wong /* 126928b721aSDarrick J. Wong * All path steps observed during this scan. Each of the path 127928b721aSDarrick J. Wong * steps for a particular pathwalk are recorded in sequential 128928b721aSDarrick J. Wong * order in the xfarray. A pathwalk ends either with a step 129928b721aSDarrick J. Wong * pointing to the root directory (success) or pointing to NULLFSINO 130928b721aSDarrick J. Wong * (loop detected, empty dir detected, etc). 131928b721aSDarrick J. Wong */ 132928b721aSDarrick J. Wong struct xfarray *path_steps; 133928b721aSDarrick J. Wong 134928b721aSDarrick J. Wong /* All names observed during this scan. */ 135928b721aSDarrick J. Wong struct xfblob *path_names; 136928b721aSDarrick J. Wong 137928b721aSDarrick J. Wong /* All paths being tracked by this scanner. */ 138928b721aSDarrick J. Wong struct list_head path_list; 139928b721aSDarrick J. Wong 140928b721aSDarrick J. Wong /* Number of paths in path_list. */ 141928b721aSDarrick J. Wong unsigned int nr_paths; 142928b721aSDarrick J. Wong 143928b721aSDarrick J. Wong /* Number of parents found by a pptr scan. */ 144928b721aSDarrick J. Wong unsigned int parents_found; 145928b721aSDarrick J. Wong 146928b721aSDarrick J. Wong /* Have the path data been invalidated by a concurrent update? */ 147928b721aSDarrick J. Wong bool stale:1; 148d54c5ac8SDarrick J. Wong 149d54c5ac8SDarrick J. Wong /* Has the scan been aborted? */ 150d54c5ac8SDarrick J. Wong bool aborted:1; 151928b721aSDarrick J. Wong }; 152928b721aSDarrick J. Wong 153928b721aSDarrick J. Wong #define xchk_dirtree_for_each_path_safe(dl, path, n) \ 154928b721aSDarrick J. Wong list_for_each_entry_safe((path), (n), &(dl)->path_list, list) 155928b721aSDarrick J. Wong 156928b721aSDarrick J. Wong #define xchk_dirtree_for_each_path(dl, path) \ 157928b721aSDarrick J. Wong list_for_each_entry((path), &(dl)->path_list, list) 158928b721aSDarrick J. Wong 159*679b098bSDarrick J. Wong bool xchk_dirtree_parentless(const struct xchk_dirtree *dl); 160928b721aSDarrick J. Wong 1613f31406aSDarrick J. Wong int xchk_dirtree_find_paths_to_root(struct xchk_dirtree *dl); 1623f31406aSDarrick J. Wong int xchk_dirpath_append(struct xchk_dirtree *dl, struct xfs_inode *ip, 1633f31406aSDarrick J. Wong struct xchk_dirpath *path, const struct xfs_name *name, 1643f31406aSDarrick J. Wong const struct xfs_parent_rec *pptr); 1653f31406aSDarrick J. Wong void xchk_dirtree_evaluate(struct xchk_dirtree *dl, 1663f31406aSDarrick J. Wong struct xchk_dirtree_outcomes *oc); 1673f31406aSDarrick J. Wong 168928b721aSDarrick J. Wong #endif /* __XFS_SCRUB_DIRTREE_H__ */ 169