xref: /linux/fs/xfs/scrub/nlinks.h (revision c771600c6af14749609b49565ffb4cac2959710d)
1f1184081SDarrick J. Wong /* SPDX-License-Identifier: GPL-2.0-or-later */
2f1184081SDarrick J. Wong /*
3f1184081SDarrick J. Wong  * Copyright (c) 2021-2024 Oracle.  All Rights Reserved.
4f1184081SDarrick J. Wong  * Author: Darrick J. Wong <djwong@kernel.org>
5f1184081SDarrick J. Wong  */
6f1184081SDarrick J. Wong #ifndef __XFS_SCRUB_NLINKS_H__
7f1184081SDarrick J. Wong #define __XFS_SCRUB_NLINKS_H__
8f1184081SDarrick J. Wong 
9f1184081SDarrick J. Wong /* Live link count control structure. */
10f1184081SDarrick J. Wong struct xchk_nlink_ctrs {
11f1184081SDarrick J. Wong 	struct xfs_scrub	*sc;
12f1184081SDarrick J. Wong 
13f1184081SDarrick J. Wong 	/* Shadow link count data and its mutex. */
14f1184081SDarrick J. Wong 	struct xfarray		*nlinks;
15f1184081SDarrick J. Wong 	struct mutex		lock;
16f1184081SDarrick J. Wong 
17f1184081SDarrick J. Wong 	/*
18f1184081SDarrick J. Wong 	 * The collection step uses a separate iscan context from the compare
19f1184081SDarrick J. Wong 	 * step because the collection iscan coordinates live updates to the
20f1184081SDarrick J. Wong 	 * observation data while this scanner is running.  The compare iscan
21f1184081SDarrick J. Wong 	 * is secondary and can be reinitialized as needed.
22f1184081SDarrick J. Wong 	 */
23f1184081SDarrick J. Wong 	struct xchk_iscan	collect_iscan;
24f1184081SDarrick J. Wong 	struct xchk_iscan	compare_iscan;
2586a1746eSDarrick J. Wong 
2686a1746eSDarrick J. Wong 	/*
2786a1746eSDarrick J. Wong 	 * Hook into directory updates so that we can receive live updates
2886a1746eSDarrick J. Wong 	 * from other writer threads.
2986a1746eSDarrick J. Wong 	 */
3086a1746eSDarrick J. Wong 	struct xfs_dir_hook	dhook;
31*e6c9e75fSDarrick J. Wong 
32*e6c9e75fSDarrick J. Wong 	/* Orphanage reparenting request. */
33*e6c9e75fSDarrick J. Wong 	struct xrep_adoption	adoption;
34*e6c9e75fSDarrick J. Wong 
35*e6c9e75fSDarrick J. Wong 	/* Directory entry name, plus the trailing null. */
36*e6c9e75fSDarrick J. Wong 	struct xfs_name		xname;
37*e6c9e75fSDarrick J. Wong 	char			namebuf[MAXNAMELEN];
38f1184081SDarrick J. Wong };
39f1184081SDarrick J. Wong 
40f1184081SDarrick J. Wong /*
41f1184081SDarrick J. Wong  * In-core link counts for a given inode in the filesystem.
42f1184081SDarrick J. Wong  *
43f1184081SDarrick J. Wong  * For an empty rootdir, the directory entries and the field to which they are
44f1184081SDarrick J. Wong  * accounted are as follows:
45f1184081SDarrick J. Wong  *
46f1184081SDarrick J. Wong  * Root directory:
47f1184081SDarrick J. Wong  *
48f1184081SDarrick J. Wong  * . points to self		(root.child)
49f1184081SDarrick J. Wong  * .. points to self		(root.parent)
50f1184081SDarrick J. Wong  * f1 points to a child file	(f1.parent)
51f1184081SDarrick J. Wong  * d1 points to a child dir	(d1.parent, root.child)
52f1184081SDarrick J. Wong  *
53f1184081SDarrick J. Wong  * Subdirectory d1:
54f1184081SDarrick J. Wong  *
55f1184081SDarrick J. Wong  * . points to self		(d1.child)
56f1184081SDarrick J. Wong  * .. points to root dir	(root.backref)
57f1184081SDarrick J. Wong  * f2 points to child file	(f2.parent)
58f1184081SDarrick J. Wong  * f3 points to root.f1		(f1.parent)
59f1184081SDarrick J. Wong  *
60f1184081SDarrick J. Wong  * root.nlink == 3 (root.dot, root.dotdot, root.d1)
61f1184081SDarrick J. Wong  * d1.nlink == 2 (root.d1, d1.dot)
62f1184081SDarrick J. Wong  * f1.nlink == 2 (root.f1, d1.f3)
63f1184081SDarrick J. Wong  * f2.nlink == 1 (d1.f2)
64f1184081SDarrick J. Wong  */
65f1184081SDarrick J. Wong struct xchk_nlink {
66f1184081SDarrick J. Wong 	/* Count of forward links from parent directories to this file. */
67f1184081SDarrick J. Wong 	xfs_nlink_t		parents;
68f1184081SDarrick J. Wong 
69f1184081SDarrick J. Wong 	/*
70f1184081SDarrick J. Wong 	 * Count of back links to this parent directory from child
71f1184081SDarrick J. Wong 	 * subdirectories.
72f1184081SDarrick J. Wong 	 */
73f1184081SDarrick J. Wong 	xfs_nlink_t		backrefs;
74f1184081SDarrick J. Wong 
75f1184081SDarrick J. Wong 	/*
76f1184081SDarrick J. Wong 	 * Count of forward links from this directory to all child files and
77f1184081SDarrick J. Wong 	 * the number of dot entries.  Should be zero for non-directories.
78f1184081SDarrick J. Wong 	 */
79f1184081SDarrick J. Wong 	xfs_nlink_t		children;
80f1184081SDarrick J. Wong 
81f1184081SDarrick J. Wong 	/* Record state flags */
82f1184081SDarrick J. Wong 	unsigned int		flags;
83f1184081SDarrick J. Wong };
84f1184081SDarrick J. Wong 
85f1184081SDarrick J. Wong /*
86f1184081SDarrick J. Wong  * This incore link count has been written at least once.  We never want to
87f1184081SDarrick J. Wong  * store an xchk_nlink that looks uninitialized.
88f1184081SDarrick J. Wong  */
89f1184081SDarrick J. Wong #define XCHK_NLINK_WRITTEN		(1U << 0)
90f1184081SDarrick J. Wong 
916b631c60SDarrick J. Wong /* Already checked this link count record. */
92f1184081SDarrick J. Wong #define XCHK_NLINK_COMPARE_SCANNED	(1U << 1)
93f1184081SDarrick J. Wong 
946b631c60SDarrick J. Wong /* Already made a repair with this link count record. */
956b631c60SDarrick J. Wong #define XREP_NLINK_DIRTY		(1U << 2)
966b631c60SDarrick J. Wong 
97f1184081SDarrick J. Wong /* Compute total link count, using large enough variables to detect overflow. */
98f1184081SDarrick J. Wong static inline uint64_t
99f1184081SDarrick J. Wong xchk_nlink_total(struct xfs_inode *ip, const struct xchk_nlink *live)
100f1184081SDarrick J. Wong {
101f1184081SDarrick J. Wong 	uint64_t	ret = live->parents;
102f1184081SDarrick J. Wong 
103f1184081SDarrick J. Wong 	/* Add one link count for the dot entry of any linked directory. */
104f1184081SDarrick J. Wong 	if (ip && S_ISDIR(VFS_I(ip)->i_mode) && VFS_I(ip)->i_nlink)
105f1184081SDarrick J. Wong 		ret++;
106f1184081SDarrick J. Wong 	return ret + live->children;
107f1184081SDarrick J. Wong }
108f1184081SDarrick J. Wong 
109f1184081SDarrick J. Wong #endif /* __XFS_SCRUB_NLINKS_H__ */
110