xref: /linux/fs/xfs/scrub/dirtree.h (revision c771600c6af14749609b49565ffb4cac2959710d)
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