xref: /linux/fs/xfs/scrub/nlinks_repair.c (revision 1e58a8ccf2597c9259a8e71a2bffac5e11e12ea0)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2021-2024 Oracle.  All Rights Reserved.
4  * Author: Darrick J. Wong <djwong@kernel.org>
5  */
6 #include "xfs.h"
7 #include "xfs_fs.h"
8 #include "xfs_shared.h"
9 #include "xfs_format.h"
10 #include "xfs_trans_resv.h"
11 #include "xfs_mount.h"
12 #include "xfs_log_format.h"
13 #include "xfs_trans.h"
14 #include "xfs_inode.h"
15 #include "xfs_icache.h"
16 #include "xfs_bmap_util.h"
17 #include "xfs_iwalk.h"
18 #include "xfs_ialloc.h"
19 #include "xfs_sb.h"
20 #include "xfs_ag.h"
21 #include "scrub/scrub.h"
22 #include "scrub/common.h"
23 #include "scrub/repair.h"
24 #include "scrub/xfile.h"
25 #include "scrub/xfarray.h"
26 #include "scrub/iscan.h"
27 #include "scrub/nlinks.h"
28 #include "scrub/trace.h"
29 #include "scrub/tempfile.h"
30 
31 /*
32  * Live Inode Link Count Repair
33  * ============================
34  *
35  * Use the live inode link count information that we collected to replace the
36  * nlink values of the incore inodes.  A scrub->repair cycle should have left
37  * the live data and hooks active, so this is safe so long as we make sure the
38  * inode is locked.
39  */
40 
41 /* Remove an inode from the unlinked list. */
42 STATIC int
43 xrep_nlinks_iunlink_remove(
44 	struct xfs_scrub	*sc)
45 {
46 	struct xfs_perag	*pag;
47 	int			error;
48 
49 	pag = xfs_perag_get(sc->mp, XFS_INO_TO_AGNO(sc->mp, sc->ip->i_ino));
50 	error = xfs_iunlink_remove(sc->tp, pag, sc->ip);
51 	xfs_perag_put(pag);
52 	return error;
53 }
54 
55 /*
56  * Correct the link count of the given inode.  Because we have to grab locks
57  * and resources in a certain order, it's possible that this will be a no-op.
58  */
59 STATIC int
60 xrep_nlinks_repair_inode(
61 	struct xchk_nlink_ctrs	*xnc)
62 {
63 	struct xchk_nlink	obs;
64 	struct xfs_scrub	*sc = xnc->sc;
65 	struct xfs_mount	*mp = sc->mp;
66 	struct xfs_inode	*ip = sc->ip;
67 	uint64_t		total_links;
68 	uint64_t		actual_nlink;
69 	bool			dirty = false;
70 	int			error;
71 
72 	/*
73 	 * Ignore temporary files being used to stage repairs, since we assume
74 	 * they're correct for non-directories, and the directory repair code
75 	 * doesn't bump the link counts for the children.
76 	 */
77 	if (xrep_is_tempfile(ip))
78 		return 0;
79 
80 	xchk_ilock(sc, XFS_IOLOCK_EXCL);
81 
82 	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_link, 0, 0, 0, &sc->tp);
83 	if (error)
84 		return error;
85 
86 	xchk_ilock(sc, XFS_ILOCK_EXCL);
87 	xfs_trans_ijoin(sc->tp, ip, 0);
88 
89 	mutex_lock(&xnc->lock);
90 
91 	if (xchk_iscan_aborted(&xnc->collect_iscan)) {
92 		error = -ECANCELED;
93 		goto out_scanlock;
94 	}
95 
96 	error = xfarray_load_sparse(xnc->nlinks, ip->i_ino, &obs);
97 	if (error)
98 		goto out_scanlock;
99 
100 	/*
101 	 * We're done accessing the shared scan data, so we can drop the lock.
102 	 * We still hold @ip's ILOCK, so its link count cannot change.
103 	 */
104 	mutex_unlock(&xnc->lock);
105 
106 	total_links = xchk_nlink_total(ip, &obs);
107 	actual_nlink = VFS_I(ip)->i_nlink;
108 
109 	/*
110 	 * Non-directories cannot have directories pointing up to them.
111 	 *
112 	 * We previously set error to zero, but set it again because one static
113 	 * checker author fears that programmers will fail to maintain this
114 	 * invariant and built their tool to flag this as a security risk.  A
115 	 * different tool author made their bot complain about the redundant
116 	 * store.  This is a never-ending and stupid battle; both tools missed
117 	 * *actual bugs* elsewhere; and I no longer care.
118 	 */
119 	if (!S_ISDIR(VFS_I(ip)->i_mode) && obs.children != 0) {
120 		trace_xrep_nlinks_unfixable_inode(mp, ip, &obs);
121 		error = 0;
122 		goto out_trans;
123 	}
124 
125 	/*
126 	 * If this inode is linked from the directory tree and on the unlinked
127 	 * list, remove it from the unlinked list.
128 	 */
129 	if (total_links > 0 && xfs_inode_on_unlinked_list(ip)) {
130 		error = xrep_nlinks_iunlink_remove(sc);
131 		if (error)
132 			goto out_trans;
133 		dirty = true;
134 	}
135 
136 	/*
137 	 * If this inode is not linked from the directory tree yet not on the
138 	 * unlinked list, put it on the unlinked list.
139 	 */
140 	if (total_links == 0 && !xfs_inode_on_unlinked_list(ip)) {
141 		error = xfs_iunlink(sc->tp, ip);
142 		if (error)
143 			goto out_trans;
144 		dirty = true;
145 	}
146 
147 	/* Commit the new link count if it changed. */
148 	if (total_links != actual_nlink) {
149 		if (total_links > XFS_MAXLINK) {
150 			trace_xrep_nlinks_unfixable_inode(mp, ip, &obs);
151 			goto out_trans;
152 		}
153 
154 		trace_xrep_nlinks_update_inode(mp, ip, &obs);
155 
156 		set_nlink(VFS_I(ip), total_links);
157 		dirty = true;
158 	}
159 
160 	if (!dirty) {
161 		error = 0;
162 		goto out_trans;
163 	}
164 
165 	xfs_trans_log_inode(sc->tp, ip, XFS_ILOG_CORE);
166 
167 	error = xrep_trans_commit(sc);
168 	xchk_iunlock(sc, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
169 	return error;
170 
171 out_scanlock:
172 	mutex_unlock(&xnc->lock);
173 out_trans:
174 	xchk_trans_cancel(sc);
175 	xchk_iunlock(sc, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
176 	return error;
177 }
178 
179 /*
180  * Try to visit every inode in the filesystem for repairs.  Move on if we can't
181  * grab an inode, since we're still making forward progress.
182  */
183 static int
184 xrep_nlinks_iter(
185 	struct xchk_nlink_ctrs	*xnc,
186 	struct xfs_inode	**ipp)
187 {
188 	int			error;
189 
190 	do {
191 		error = xchk_iscan_iter(&xnc->compare_iscan, ipp);
192 	} while (error == -EBUSY);
193 
194 	return error;
195 }
196 
197 /* Commit the new inode link counters. */
198 int
199 xrep_nlinks(
200 	struct xfs_scrub	*sc)
201 {
202 	struct xchk_nlink_ctrs	*xnc = sc->buf;
203 	int			error;
204 
205 	/*
206 	 * We need ftype for an accurate count of the number of child
207 	 * subdirectory links.  Child subdirectories with a back link (dotdot
208 	 * entry) but no forward link are unfixable, so we cannot repair the
209 	 * link count of the parent directory based on the back link count
210 	 * alone.  Filesystems without ftype support are rare (old V4) so we
211 	 * just skip out here.
212 	 */
213 	if (!xfs_has_ftype(sc->mp))
214 		return -EOPNOTSUPP;
215 
216 	/*
217 	 * Use the inobt to walk all allocated inodes to compare and fix the
218 	 * link counts.  Retry iget every tenth of a second for up to 30
219 	 * seconds -- even if repair misses a few inodes, we still try to fix
220 	 * as many of them as we can.
221 	 */
222 	xchk_iscan_start(sc, 30000, 100, &xnc->compare_iscan);
223 	ASSERT(sc->ip == NULL);
224 
225 	while ((error = xrep_nlinks_iter(xnc, &sc->ip)) == 1) {
226 		/*
227 		 * Commit the scrub transaction so that we can create repair
228 		 * transactions with the correct reservations.
229 		 */
230 		xchk_trans_cancel(sc);
231 
232 		error = xrep_nlinks_repair_inode(xnc);
233 		xchk_iscan_mark_visited(&xnc->compare_iscan, sc->ip);
234 		xchk_irele(sc, sc->ip);
235 		sc->ip = NULL;
236 		if (error)
237 			break;
238 
239 		if (xchk_should_terminate(sc, &error))
240 			break;
241 
242 		/*
243 		 * Create a new empty transaction so that we can advance the
244 		 * iscan cursor without deadlocking if the inobt has a cycle.
245 		 * We can only push the inactivation workqueues with an empty
246 		 * transaction.
247 		 */
248 		error = xchk_trans_alloc_empty(sc);
249 		if (error)
250 			break;
251 	}
252 	xchk_iscan_iter_finish(&xnc->compare_iscan);
253 	xchk_iscan_teardown(&xnc->compare_iscan);
254 
255 	return error;
256 }
257