Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0-or-later
2 : /*
3 : * Copyright (C) 2018-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_format.h"
10 : #include "xfs_trans_resv.h"
11 : #include "xfs_mount.h"
12 : #include "xfs_defer.h"
13 : #include "xfs_btree.h"
14 : #include "xfs_bit.h"
15 : #include "xfs_log_format.h"
16 : #include "xfs_trans.h"
17 : #include "xfs_sb.h"
18 : #include "xfs_inode.h"
19 : #include "xfs_inode_fork.h"
20 : #include "xfs_alloc.h"
21 : #include "xfs_bmap.h"
22 : #include "xfs_quota.h"
23 : #include "xfs_qm.h"
24 : #include "xfs_dquot.h"
25 : #include "xfs_dquot_item.h"
26 : #include "xfs_reflink.h"
27 : #include "scrub/xfs_scrub.h"
28 : #include "scrub/scrub.h"
29 : #include "scrub/common.h"
30 : #include "scrub/quota.h"
31 : #include "scrub/trace.h"
32 : #include "scrub/repair.h"
33 :
34 : /*
35 : * Quota Repair
36 : * ============
37 : *
38 : * Quota repairs are fairly simplistic; we fix everything that the dquot
39 : * verifiers complain about, cap any counters or limits that make no sense,
40 : * and schedule a quotacheck if we had to fix anything. We also repair any
41 : * data fork extent records that don't apply to metadata files.
42 : */
43 :
44 : struct xrep_quota_info {
45 : struct xfs_scrub *sc;
46 : bool need_quotacheck;
47 : };
48 :
49 : /* Scrub the fields in an individual quota item. */
50 : STATIC int
51 0 : xrep_quota_item(
52 : struct xfs_dquot *dqp,
53 : xfs_dqtype_t dqtype,
54 : void *priv)
55 : {
56 0 : struct xrep_quota_info *rqi = priv;
57 0 : struct xfs_scrub *sc = rqi->sc;
58 0 : struct xfs_mount *mp = sc->mp;
59 0 : xfs_ino_t fs_icount;
60 0 : bool dirty = false;
61 0 : int error = 0;
62 :
63 : /* Last chance to abort before we start committing fixes. */
64 0 : if (xchk_should_terminate(sc, &error))
65 0 : return error;
66 :
67 : /* Check the limits. */
68 0 : if (dqp->q_blk.softlimit > dqp->q_blk.hardlimit) {
69 0 : dqp->q_blk.softlimit = dqp->q_blk.hardlimit;
70 0 : dirty = true;
71 : }
72 :
73 0 : if (dqp->q_ino.softlimit > dqp->q_ino.hardlimit) {
74 0 : dqp->q_ino.softlimit = dqp->q_ino.hardlimit;
75 0 : dirty = true;
76 : }
77 :
78 0 : if (dqp->q_rtb.softlimit > dqp->q_rtb.hardlimit) {
79 0 : dqp->q_rtb.softlimit = dqp->q_rtb.hardlimit;
80 0 : dirty = true;
81 : }
82 :
83 : /*
84 : * Check that usage doesn't exceed physical limits. However, on
85 : * a reflink filesystem we're allowed to exceed physical space
86 : * if there are no quota limits. We don't know what the real number
87 : * is, but we can make quotacheck find out for us.
88 : */
89 0 : if (!xfs_has_reflink(mp) && dqp->q_blk.count > mp->m_sb.sb_dblocks) {
90 0 : dqp->q_blk.reserved -= dqp->q_blk.count;
91 0 : dqp->q_blk.reserved += mp->m_sb.sb_dblocks;
92 0 : dqp->q_blk.count = mp->m_sb.sb_dblocks;
93 0 : rqi->need_quotacheck = true;
94 0 : dirty = true;
95 : }
96 0 : fs_icount = percpu_counter_sum(&mp->m_icount);
97 0 : if (dqp->q_ino.count > fs_icount) {
98 0 : dqp->q_ino.reserved -= dqp->q_ino.count;
99 0 : dqp->q_ino.reserved += fs_icount;
100 0 : dqp->q_ino.count = fs_icount;
101 0 : rqi->need_quotacheck = true;
102 0 : dirty = true;
103 : }
104 0 : if (dqp->q_rtb.count > mp->m_sb.sb_rblocks) {
105 0 : dqp->q_rtb.reserved -= dqp->q_rtb.count;
106 0 : dqp->q_rtb.reserved += mp->m_sb.sb_rblocks;
107 0 : dqp->q_rtb.count = mp->m_sb.sb_rblocks;
108 0 : rqi->need_quotacheck = true;
109 0 : dirty = true;
110 : }
111 :
112 0 : if (!dirty)
113 : return 0;
114 :
115 0 : trace_xrep_dquot_item(sc->mp, dqp->q_type, dqp->q_id);
116 :
117 0 : dqp->q_flags |= XFS_DQFLAG_DIRTY;
118 0 : xfs_trans_dqjoin(sc->tp, dqp);
119 0 : if (dqp->q_id) {
120 0 : xfs_qm_adjust_dqlimits(dqp);
121 0 : xfs_qm_adjust_dqtimers(dqp);
122 : }
123 0 : xfs_trans_log_dquot(sc->tp, dqp);
124 0 : error = xfs_trans_roll(&sc->tp);
125 0 : xfs_dqlock(dqp);
126 0 : return error;
127 : }
128 :
129 : /* Fix a quota timer so that we can pass the verifier. */
130 : STATIC void
131 0 : xrep_quota_fix_timer(
132 : struct xfs_mount *mp,
133 : __be64 softlimit,
134 : __be64 countnow,
135 : __be32 *timer,
136 : time64_t timelimit)
137 : {
138 0 : uint64_t soft = be64_to_cpu(softlimit);
139 0 : uint64_t count = be64_to_cpu(countnow);
140 0 : time64_t new_timer;
141 :
142 0 : if (!soft || count <= soft || *timer != 0)
143 : return;
144 :
145 0 : new_timer = xfs_dquot_set_timeout(mp,
146 0 : ktime_get_real_seconds() + timelimit);
147 0 : *timer = cpu_to_be32(new_timer);
148 : }
149 :
150 : /* Fix anything the verifiers complain about. */
151 : STATIC int
152 0 : xrep_quota_block(
153 : struct xfs_scrub *sc,
154 : xfs_daddr_t daddr,
155 : xfs_dqtype_t dqtype,
156 : xfs_dqid_t id)
157 : {
158 0 : struct xfs_dqblk *dqblk;
159 0 : struct xfs_disk_dquot *ddq;
160 0 : struct xfs_quotainfo *qi = sc->mp->m_quotainfo;
161 0 : struct xfs_def_quota *defq = xfs_get_defquota(qi, dqtype);
162 0 : struct xfs_buf *bp = NULL;
163 0 : enum xfs_blft buftype = 0;
164 0 : int i;
165 0 : int error;
166 :
167 0 : error = xfs_trans_read_buf(sc->mp, sc->tp, sc->mp->m_ddev_targp, daddr,
168 0 : qi->qi_dqchunklen, 0, &bp, &xfs_dquot_buf_ops);
169 0 : switch (error) {
170 0 : case -EFSBADCRC:
171 : case -EFSCORRUPTED:
172 : /* Failed verifier, retry read with no ops. */
173 0 : error = xfs_trans_read_buf(sc->mp, sc->tp,
174 0 : sc->mp->m_ddev_targp, daddr, qi->qi_dqchunklen,
175 : 0, &bp, NULL);
176 0 : if (error)
177 : return error;
178 : break;
179 0 : case 0:
180 0 : dqblk = bp->b_addr;
181 0 : ddq = &dqblk[0].dd_diskdq;
182 :
183 : /*
184 : * If there's nothing that would impede a dqiterate, we're
185 : * done.
186 : */
187 0 : if ((ddq->d_type & XFS_DQTYPE_REC_MASK) != dqtype ||
188 0 : id == be32_to_cpu(ddq->d_id)) {
189 0 : xfs_trans_brelse(sc->tp, bp);
190 0 : return 0;
191 : }
192 : break;
193 : default:
194 : return error;
195 : }
196 :
197 : /* Something's wrong with the block, fix the whole thing. */
198 0 : dqblk = bp->b_addr;
199 0 : bp->b_ops = &xfs_dquot_buf_ops;
200 0 : for (i = 0; i < qi->qi_dqperchunk; i++, dqblk++) {
201 0 : ddq = &dqblk->dd_diskdq;
202 :
203 0 : trace_xrep_disk_dquot(sc->mp, dqtype, id + i);
204 :
205 0 : ddq->d_magic = cpu_to_be16(XFS_DQUOT_MAGIC);
206 0 : ddq->d_version = XFS_DQUOT_VERSION;
207 0 : ddq->d_type = dqtype;
208 0 : ddq->d_id = cpu_to_be32(id + i);
209 :
210 0 : xrep_quota_fix_timer(sc->mp, ddq->d_blk_softlimit,
211 : ddq->d_bcount, &ddq->d_btimer,
212 : defq->blk.time);
213 :
214 0 : xrep_quota_fix_timer(sc->mp, ddq->d_ino_softlimit,
215 : ddq->d_icount, &ddq->d_itimer,
216 : defq->ino.time);
217 :
218 0 : xrep_quota_fix_timer(sc->mp, ddq->d_rtb_softlimit,
219 : ddq->d_rtbcount, &ddq->d_rtbtimer,
220 : defq->rtb.time);
221 :
222 : /* We only support v5 filesystems so always set these. */
223 0 : uuid_copy(&dqblk->dd_uuid, &sc->mp->m_sb.sb_meta_uuid);
224 0 : xfs_update_cksum((char *)dqblk, sizeof(struct xfs_dqblk),
225 : XFS_DQUOT_CRC_OFF);
226 0 : dqblk->dd_lsn = 0;
227 : }
228 0 : switch (dqtype) {
229 : case XFS_DQTYPE_USER:
230 : buftype = XFS_BLFT_UDQUOT_BUF;
231 : break;
232 : case XFS_DQTYPE_GROUP:
233 : buftype = XFS_BLFT_GDQUOT_BUF;
234 : break;
235 : case XFS_DQTYPE_PROJ:
236 : buftype = XFS_BLFT_PDQUOT_BUF;
237 : break;
238 : }
239 0 : xfs_trans_buf_set_type(sc->tp, bp, buftype);
240 0 : xfs_trans_log_buf(sc->tp, bp, 0, BBTOB(bp->b_length) - 1);
241 0 : return xrep_roll_trans(sc);
242 : }
243 :
244 : /*
245 : * Repair a quota file's data fork. The function returns with the inode
246 : * joined.
247 : */
248 : STATIC int
249 2331 : xrep_quota_data_fork(
250 : struct xfs_scrub *sc,
251 : xfs_dqtype_t dqtype)
252 : {
253 2331 : struct xfs_bmbt_irec irec = { 0 };
254 2331 : struct xfs_iext_cursor icur;
255 2331 : struct xfs_quotainfo *qi = sc->mp->m_quotainfo;
256 2331 : struct xfs_ifork *ifp;
257 2331 : xfs_fileoff_t max_dqid_off;
258 2331 : xfs_fileoff_t off;
259 2331 : xfs_fsblock_t fsbno;
260 2331 : bool truncate = false;
261 2331 : int error = 0;
262 :
263 2331 : error = xrep_metadata_inode_forks(sc);
264 2331 : if (error)
265 2331 : goto out;
266 :
267 : /* Check for data fork problems that apply only to quota files. */
268 0 : max_dqid_off = ((xfs_dqid_t)-1) / qi->qi_dqperchunk;
269 0 : ifp = xfs_ifork_ptr(sc->ip, XFS_DATA_FORK);
270 0 : for_each_xfs_iext(ifp, &icur, &irec) {
271 0 : if (isnullstartblock(irec.br_startblock)) {
272 0 : error = -EFSCORRUPTED;
273 0 : goto out;
274 : }
275 :
276 0 : if (irec.br_startoff > max_dqid_off ||
277 0 : irec.br_startoff + irec.br_blockcount - 1 > max_dqid_off) {
278 : truncate = true;
279 : break;
280 : }
281 :
282 : /* Convert unwritten extents to real ones. */
283 0 : if (irec.br_state == XFS_EXT_UNWRITTEN) {
284 0 : struct xfs_bmbt_irec nrec;
285 0 : int nmap = 1;
286 :
287 0 : xfs_trans_ijoin(sc->tp, sc->ip, 0);
288 :
289 0 : error = xfs_bmapi_write(sc->tp, sc->ip,
290 : irec.br_startoff, irec.br_blockcount,
291 : XFS_BMAPI_CONVERT, 0, &nrec, &nmap);
292 0 : if (error)
293 0 : goto out;
294 0 : ASSERT(nmap == 1);
295 0 : ASSERT(nrec.br_startoff == irec.br_startoff);
296 0 : ASSERT(nrec.br_blockcount == irec.br_blockcount);
297 :
298 0 : error = xfs_defer_finish(&sc->tp);
299 0 : if (error)
300 0 : goto out;
301 : }
302 : }
303 :
304 0 : xfs_trans_ijoin(sc->tp, sc->ip, 0);
305 :
306 0 : if (truncate) {
307 : /* Erase everything after the block containing the max dquot */
308 0 : error = xfs_bunmapi_range(&sc->tp, sc->ip, 0,
309 0 : max_dqid_off * sc->mp->m_sb.sb_blocksize,
310 : XFS_MAX_FILEOFF);
311 0 : if (error)
312 0 : goto out;
313 :
314 : /* Remove all CoW reservations. */
315 0 : error = xfs_reflink_cancel_cow_blocks(sc->ip, &sc->tp, 0,
316 : XFS_MAX_FILEOFF, true);
317 0 : if (error)
318 0 : goto out;
319 0 : sc->ip->i_diflags2 &= ~XFS_DIFLAG2_REFLINK;
320 :
321 : /*
322 : * Always re-log the inode so that our permanent transaction
323 : * can keep on rolling it forward in the log.
324 : */
325 0 : xfs_trans_log_inode(sc->tp, sc->ip, XFS_ILOG_CORE);
326 : }
327 :
328 : /* Now go fix anything that fails the verifiers. */
329 0 : for_each_xfs_iext(ifp, &icur, &irec) {
330 0 : for (fsbno = irec.br_startblock, off = irec.br_startoff;
331 0 : fsbno < irec.br_startblock + irec.br_blockcount;
332 0 : fsbno += XFS_DQUOT_CLUSTER_SIZE_FSB,
333 0 : off += XFS_DQUOT_CLUSTER_SIZE_FSB) {
334 0 : error = xrep_quota_block(sc,
335 0 : XFS_FSB_TO_DADDR(sc->mp, fsbno),
336 0 : dqtype, off * qi->qi_dqperchunk);
337 0 : if (error)
338 0 : goto out;
339 : }
340 : }
341 :
342 0 : out:
343 2331 : return error;
344 : }
345 :
346 : /*
347 : * Go fix anything in the quota items that we could have been mad about. Now
348 : * that we've checked the quota inode data fork we have to drop ILOCK_EXCL to
349 : * use the regular dquot functions.
350 : */
351 : STATIC int
352 0 : xrep_quota_problems(
353 : struct xfs_scrub *sc,
354 : xfs_dqtype_t dqtype)
355 : {
356 0 : struct xrep_quota_info rqi;
357 0 : int error;
358 :
359 0 : rqi.sc = sc;
360 0 : rqi.need_quotacheck = false;
361 0 : error = xfs_qm_dqiterate(sc->mp, dqtype, xrep_quota_item, &rqi);
362 0 : if (error)
363 : return error;
364 :
365 : /* Make a quotacheck happen. */
366 0 : if (rqi.need_quotacheck)
367 0 : xrep_force_quotacheck(sc, dqtype);
368 : return 0;
369 : }
370 :
371 : /* Repair all of a quota type's items. */
372 : int
373 2331 : xrep_quota(
374 : struct xfs_scrub *sc)
375 : {
376 2331 : xfs_dqtype_t dqtype;
377 2331 : int error;
378 :
379 2331 : dqtype = xchk_quota_to_dqtype(sc);
380 :
381 : /*
382 : * Re-take the ILOCK so that we can fix any problems that we found
383 : * with the data fork mappings, or with the dquot bufs themselves.
384 : */
385 2331 : if (!(sc->ilock_flags & XFS_ILOCK_EXCL))
386 2331 : xchk_ilock(sc, XFS_ILOCK_EXCL);
387 2331 : error = xrep_quota_data_fork(sc, dqtype);
388 2331 : if (error)
389 2331 : goto out;
390 :
391 : /*
392 : * Roll the transaction to unjoin the quota inode from transaction so
393 : * that we can unlock the quota inode; we play only with dquots from
394 : * now on.
395 : */
396 0 : error = xfs_trans_roll(&sc->tp);
397 0 : if (error)
398 0 : goto out;
399 0 : xchk_iunlock(sc, sc->ilock_flags);
400 :
401 : /* Fix anything the dquot verifiers don't complain about. */
402 0 : error = xrep_quota_problems(sc, dqtype);
403 2331 : out:
404 2331 : return error;
405 : }
|