xref: /linux/fs/xfs/scrub/quota.c (revision e814f3fd16acfb7f9966773953de8f740a1e3202)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (C) 2017-2023 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_bit.h"
10 #include "xfs_format.h"
11 #include "xfs_trans_resv.h"
12 #include "xfs_mount.h"
13 #include "xfs_log_format.h"
14 #include "xfs_trans.h"
15 #include "xfs_inode.h"
16 #include "xfs_quota.h"
17 #include "xfs_qm.h"
18 #include "xfs_bmap.h"
19 #include "scrub/scrub.h"
20 #include "scrub/common.h"
21 #include "scrub/quota.h"
22 
23 /* Convert a scrub type code to a DQ flag, or return 0 if error. */
24 xfs_dqtype_t
25 xchk_quota_to_dqtype(
26 	struct xfs_scrub	*sc)
27 {
28 	switch (sc->sm->sm_type) {
29 	case XFS_SCRUB_TYPE_UQUOTA:
30 		return XFS_DQTYPE_USER;
31 	case XFS_SCRUB_TYPE_GQUOTA:
32 		return XFS_DQTYPE_GROUP;
33 	case XFS_SCRUB_TYPE_PQUOTA:
34 		return XFS_DQTYPE_PROJ;
35 	default:
36 		return 0;
37 	}
38 }
39 
40 /* Set us up to scrub a quota. */
41 int
42 xchk_setup_quota(
43 	struct xfs_scrub	*sc)
44 {
45 	xfs_dqtype_t		dqtype;
46 	int			error;
47 
48 	if (!XFS_IS_QUOTA_ON(sc->mp))
49 		return -ENOENT;
50 
51 	dqtype = xchk_quota_to_dqtype(sc);
52 	if (dqtype == 0)
53 		return -EINVAL;
54 
55 	if (!xfs_this_quota_on(sc->mp, dqtype))
56 		return -ENOENT;
57 
58 	if (xchk_need_intent_drain(sc))
59 		xchk_fsgates_enable(sc, XCHK_FSGATES_DRAIN);
60 
61 	error = xchk_setup_fs(sc);
62 	if (error)
63 		return error;
64 
65 	error = xchk_install_live_inode(sc, xfs_quota_inode(sc->mp, dqtype));
66 	if (error)
67 		return error;
68 
69 	xchk_ilock(sc, XFS_ILOCK_EXCL);
70 	return 0;
71 }
72 
73 /* Quotas. */
74 
75 struct xchk_quota_info {
76 	struct xfs_scrub	*sc;
77 	xfs_dqid_t		last_id;
78 };
79 
80 /* There's a written block backing this dquot, right? */
81 STATIC int
82 xchk_quota_item_bmap(
83 	struct xfs_scrub	*sc,
84 	struct xfs_dquot	*dq,
85 	xfs_fileoff_t		offset)
86 {
87 	struct xfs_bmbt_irec	irec;
88 	struct xfs_mount	*mp = sc->mp;
89 	int			nmaps = 1;
90 	int			error;
91 
92 	if (!xfs_verify_fileoff(mp, offset)) {
93 		xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);
94 		return 0;
95 	}
96 
97 	if (dq->q_fileoffset != offset) {
98 		xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);
99 		return 0;
100 	}
101 
102 	error = xfs_bmapi_read(sc->ip, offset, 1, &irec, &nmaps, 0);
103 	if (error)
104 		return error;
105 
106 	if (nmaps != 1) {
107 		xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);
108 		return 0;
109 	}
110 
111 	if (!xfs_verify_fsbno(mp, irec.br_startblock))
112 		xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);
113 	if (XFS_FSB_TO_DADDR(mp, irec.br_startblock) != dq->q_blkno)
114 		xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);
115 	if (!xfs_bmap_is_written_extent(&irec))
116 		xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);
117 
118 	return 0;
119 }
120 
121 /* Complain if a quota timer is incorrectly set. */
122 static inline void
123 xchk_quota_item_timer(
124 	struct xfs_scrub		*sc,
125 	xfs_fileoff_t			offset,
126 	const struct xfs_dquot_res	*res)
127 {
128 	if ((res->softlimit && res->count > res->softlimit) ||
129 	    (res->hardlimit && res->count > res->hardlimit)) {
130 		if (!res->timer)
131 			xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);
132 	} else {
133 		if (res->timer)
134 			xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);
135 	}
136 }
137 
138 /* Scrub the fields in an individual quota item. */
139 STATIC int
140 xchk_quota_item(
141 	struct xchk_quota_info	*sqi,
142 	struct xfs_dquot	*dq)
143 {
144 	struct xfs_scrub	*sc = sqi->sc;
145 	struct xfs_mount	*mp = sc->mp;
146 	struct xfs_quotainfo	*qi = mp->m_quotainfo;
147 	xfs_fileoff_t		offset;
148 	xfs_ino_t		fs_icount;
149 	int			error = 0;
150 
151 	if (xchk_should_terminate(sc, &error))
152 		return error;
153 
154 	/*
155 	 * We want to validate the bmap record for the storage backing this
156 	 * dquot, so we need to lock the dquot and the quota file.  For quota
157 	 * operations, the locking order is first the ILOCK and then the dquot.
158 	 * However, dqiterate gave us a locked dquot, so drop the dquot lock to
159 	 * get the ILOCK.
160 	 */
161 	xfs_dqunlock(dq);
162 	xchk_ilock(sc, XFS_ILOCK_SHARED);
163 	xfs_dqlock(dq);
164 
165 	/*
166 	 * Except for the root dquot, the actual dquot we got must either have
167 	 * the same or higher id as we saw before.
168 	 */
169 	offset = dq->q_id / qi->qi_dqperchunk;
170 	if (dq->q_id && dq->q_id <= sqi->last_id)
171 		xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);
172 
173 	sqi->last_id = dq->q_id;
174 
175 	error = xchk_quota_item_bmap(sc, dq, offset);
176 	xchk_iunlock(sc, XFS_ILOCK_SHARED);
177 	if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, offset, &error))
178 		return error;
179 
180 	/*
181 	 * Warn if the hard limits are larger than the fs.
182 	 * Administrators can do this, though in production this seems
183 	 * suspect, which is why we flag it for review.
184 	 *
185 	 * Complain about corruption if the soft limit is greater than
186 	 * the hard limit.
187 	 */
188 	if (dq->q_blk.hardlimit > mp->m_sb.sb_dblocks)
189 		xchk_fblock_set_warning(sc, XFS_DATA_FORK, offset);
190 	if (dq->q_blk.softlimit > dq->q_blk.hardlimit)
191 		xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);
192 
193 	if (dq->q_ino.hardlimit > M_IGEO(mp)->maxicount)
194 		xchk_fblock_set_warning(sc, XFS_DATA_FORK, offset);
195 	if (dq->q_ino.softlimit > dq->q_ino.hardlimit)
196 		xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);
197 
198 	if (dq->q_rtb.hardlimit > mp->m_sb.sb_rblocks)
199 		xchk_fblock_set_warning(sc, XFS_DATA_FORK, offset);
200 	if (dq->q_rtb.softlimit > dq->q_rtb.hardlimit)
201 		xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);
202 
203 	/* Check the resource counts. */
204 	fs_icount = percpu_counter_sum(&mp->m_icount);
205 
206 	/*
207 	 * Check that usage doesn't exceed physical limits.  However, on
208 	 * a reflink filesystem we're allowed to exceed physical space
209 	 * if there are no quota limits.
210 	 */
211 	if (xfs_has_reflink(mp)) {
212 		if (mp->m_sb.sb_dblocks < dq->q_blk.count)
213 			xchk_fblock_set_warning(sc, XFS_DATA_FORK,
214 					offset);
215 		if (mp->m_sb.sb_rblocks < dq->q_rtb.count)
216 			xchk_fblock_set_warning(sc, XFS_DATA_FORK,
217 					offset);
218 	} else {
219 		if (mp->m_sb.sb_dblocks < dq->q_blk.count)
220 			xchk_fblock_set_corrupt(sc, XFS_DATA_FORK,
221 					offset);
222 		if (mp->m_sb.sb_rblocks < dq->q_rtb.count)
223 			xchk_fblock_set_corrupt(sc, XFS_DATA_FORK,
224 					offset);
225 	}
226 	if (dq->q_ino.count > fs_icount)
227 		xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);
228 
229 	/*
230 	 * We can violate the hard limits if the admin suddenly sets a
231 	 * lower limit than the actual usage.  However, we flag it for
232 	 * admin review.
233 	 */
234 	if (dq->q_id == 0)
235 		goto out;
236 
237 	if (dq->q_blk.hardlimit != 0 &&
238 	    dq->q_blk.count > dq->q_blk.hardlimit)
239 		xchk_fblock_set_warning(sc, XFS_DATA_FORK, offset);
240 
241 	if (dq->q_ino.hardlimit != 0 &&
242 	    dq->q_ino.count > dq->q_ino.hardlimit)
243 		xchk_fblock_set_warning(sc, XFS_DATA_FORK, offset);
244 
245 	if (dq->q_rtb.hardlimit != 0 &&
246 	    dq->q_rtb.count > dq->q_rtb.hardlimit)
247 		xchk_fblock_set_warning(sc, XFS_DATA_FORK, offset);
248 
249 	xchk_quota_item_timer(sc, offset, &dq->q_blk);
250 	xchk_quota_item_timer(sc, offset, &dq->q_ino);
251 	xchk_quota_item_timer(sc, offset, &dq->q_rtb);
252 
253 out:
254 	if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
255 		return -ECANCELED;
256 
257 	return 0;
258 }
259 
260 /* Check the quota's data fork. */
261 STATIC int
262 xchk_quota_data_fork(
263 	struct xfs_scrub	*sc)
264 {
265 	struct xfs_bmbt_irec	irec = { 0 };
266 	struct xfs_iext_cursor	icur;
267 	struct xfs_quotainfo	*qi = sc->mp->m_quotainfo;
268 	struct xfs_ifork	*ifp;
269 	xfs_fileoff_t		max_dqid_off;
270 	int			error = 0;
271 
272 	/* Invoke the fork scrubber. */
273 	error = xchk_metadata_inode_forks(sc);
274 	if (error || (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT))
275 		return error;
276 
277 	/* Check for data fork problems that apply only to quota files. */
278 	max_dqid_off = XFS_DQ_ID_MAX / qi->qi_dqperchunk;
279 	ifp = xfs_ifork_ptr(sc->ip, XFS_DATA_FORK);
280 	for_each_xfs_iext(ifp, &icur, &irec) {
281 		if (xchk_should_terminate(sc, &error))
282 			break;
283 
284 		/*
285 		 * delalloc/unwritten extents or blocks mapped above the highest
286 		 * quota id shouldn't happen.
287 		 */
288 		if (!xfs_bmap_is_written_extent(&irec) ||
289 		    irec.br_startoff > max_dqid_off ||
290 		    irec.br_startoff + irec.br_blockcount - 1 > max_dqid_off) {
291 			xchk_fblock_set_corrupt(sc, XFS_DATA_FORK,
292 					irec.br_startoff);
293 			break;
294 		}
295 	}
296 
297 	return error;
298 }
299 
300 /* Scrub all of a quota type's items. */
301 int
302 xchk_quota(
303 	struct xfs_scrub	*sc)
304 {
305 	struct xchk_dqiter	cursor = { };
306 	struct xchk_quota_info	sqi = { .sc = sc };
307 	struct xfs_mount	*mp = sc->mp;
308 	struct xfs_quotainfo	*qi = mp->m_quotainfo;
309 	struct xfs_dquot	*dq;
310 	xfs_dqtype_t		dqtype;
311 	int			error = 0;
312 
313 	dqtype = xchk_quota_to_dqtype(sc);
314 
315 	/* Look for problem extents. */
316 	error = xchk_quota_data_fork(sc);
317 	if (error)
318 		goto out;
319 	if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
320 		goto out;
321 
322 	/*
323 	 * Check all the quota items.  Now that we've checked the quota inode
324 	 * data fork we have to drop ILOCK_EXCL to use the regular dquot
325 	 * functions.
326 	 */
327 	xchk_iunlock(sc, sc->ilock_flags);
328 
329 	/* Now look for things that the quota verifiers won't complain about. */
330 	xchk_dqiter_init(&cursor, sc, dqtype);
331 	while ((error = xchk_dquot_iter(&cursor, &dq)) == 1) {
332 		error = xchk_quota_item(&sqi, dq);
333 		xfs_qm_dqput(dq);
334 		if (error)
335 			break;
336 	}
337 	if (error == -ECANCELED)
338 		error = 0;
339 	if (!xchk_fblock_process_error(sc, XFS_DATA_FORK,
340 			sqi.last_id * qi->qi_dqperchunk, &error))
341 		goto out;
342 
343 out:
344 	return error;
345 }
346