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