File Index
Files and directories
Sign in
FILE

quota_repair.c

File preview with syntax highlighting.

linux-6.19.14/fs/xfs/scrub/quota_repair.c C
  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 "xfs_bmap_btree.h"
 28#include "xfs_trans_space.h"
 29#include "scrub/xfs_scrub.h"
 30#include "scrub/scrub.h"
 31#include "scrub/common.h"
 32#include "scrub/quota.h"
 33#include "scrub/trace.h"
 34#include "scrub/repair.h"
 35
 36/*
 37 * Quota Repair
 38 * ============
 39 *
 40 * Quota repairs are fairly simplistic; we fix everything that the dquot
 41 * verifiers complain about, cap any counters or limits that make no sense,
 42 * and schedule a quotacheck if we had to fix anything.  We also repair any
 43 * data fork extent records that don't apply to metadata files.
 44 */
 45
 46struct xrep_quota_info {
 47	struct xfs_scrub	*sc;
 48	bool			need_quotacheck;
 49};
 50
 51/*
 52 * Allocate a new block into a sparse hole in the quota file backing this
 53 * dquot, initialize the block, and commit the whole mess.
 54 */
 55STATIC int
 56xrep_quota_item_fill_bmap_hole(
 57	struct xfs_scrub	*sc,
 58	struct xfs_dquot	*dq,
 59	struct xfs_bmbt_irec	*irec)
 60{
 61	struct xfs_buf		*bp;
 62	struct xfs_mount	*mp = sc->mp;
 63	int			nmaps = 1;
 64	int			error;
 65
 66	xfs_trans_ijoin(sc->tp, sc->ip, 0);
 67
 68	/* Map a block into the file. */
 69	error = xfs_trans_reserve_more(sc->tp, XFS_QM_DQALLOC_SPACE_RES(mp),
 70			0);
 71	if (error)
 72		return error;
 73
 74	error = xfs_bmapi_write(sc->tp, sc->ip, dq->q_fileoffset,
 75			XFS_DQUOT_CLUSTER_SIZE_FSB, XFS_BMAPI_METADATA, 0,
 76			irec, &nmaps);
 77	if (error)
 78		return error;
 79
 80	dq->q_blkno = XFS_FSB_TO_DADDR(mp, irec->br_startblock);
 81
 82	trace_xrep_dquot_item_fill_bmap_hole(sc->mp, dq->q_type, dq->q_id);
 83
 84	/* Initialize the new block. */
 85	error = xfs_trans_get_buf(sc->tp, mp->m_ddev_targp, dq->q_blkno,
 86			mp->m_quotainfo->qi_dqchunklen, 0, &bp);
 87	if (error)
 88		return error;
 89	bp->b_ops = &xfs_dquot_buf_ops;
 90
 91	xfs_qm_init_dquot_blk(sc->tp, dq->q_id, dq->q_type, bp);
 92	xfs_buf_set_ref(bp, XFS_DQUOT_REF);
 93
 94	/*
 95	 * Finish the mapping transactions and roll one more time to
 96	 * disconnect sc->ip from sc->tp.
 97	 */
 98	error = xrep_defer_finish(sc);
 99	if (error)
100		return error;
101	return xfs_trans_roll(&sc->tp);
102}
103
104/* Make sure there's a written block backing this dquot */
105STATIC int
106xrep_quota_item_bmap(
107	struct xfs_scrub	*sc,
108	struct xfs_dquot	*dq,
109	bool			*dirty)
110{
111	struct xfs_bmbt_irec	irec;
112	struct xfs_mount	*mp = sc->mp;
113	struct xfs_quotainfo	*qi = mp->m_quotainfo;
114	xfs_fileoff_t		offset = dq->q_id / qi->qi_dqperchunk;
115	int			nmaps = 1;
116	int			error;
117
118	/* The computed file offset should always be valid. */
119	if (!xfs_verify_fileoff(mp, offset)) {
120		ASSERT(xfs_verify_fileoff(mp, offset));
121		return -EFSCORRUPTED;
122	}
123	dq->q_fileoffset = offset;
124
125	error = xfs_bmapi_read(sc->ip, offset, 1, &irec, &nmaps, 0);
126	if (error)
127		return error;
128
129	if (nmaps < 1 || !xfs_bmap_is_real_extent(&irec)) {
130		/* Hole/delalloc extent; allocate a real block. */
131		error = xrep_quota_item_fill_bmap_hole(sc, dq, &irec);
132		if (error)
133			return error;
134	} else if (irec.br_state != XFS_EXT_NORM) {
135		/* Unwritten extent, which we already took care of? */
136		ASSERT(irec.br_state == XFS_EXT_NORM);
137		return -EFSCORRUPTED;
138	} else if (dq->q_blkno != XFS_FSB_TO_DADDR(mp, irec.br_startblock)) {
139		/*
140		 * If the cached daddr is incorrect, repair probably punched a
141		 * hole out of the quota file and filled it back in with a new
142		 * block.  Update the block mapping in the dquot.
143		 */
144		dq->q_blkno = XFS_FSB_TO_DADDR(mp, irec.br_startblock);
145	}
146
147	*dirty = true;
148	return 0;
149}
150
151/* Reset quota timers if incorrectly set. */
152static inline void
153xrep_quota_item_timer(
154	struct xfs_scrub		*sc,
155	const struct xfs_dquot_res	*res,
156	bool				*dirty)
157{
158	if ((res->softlimit && res->count > res->softlimit) ||
159	    (res->hardlimit && res->count > res->hardlimit)) {
160		if (!res->timer)
161			*dirty = true;
162	} else {
163		if (res->timer)
164			*dirty = true;
165	}
166}
167
168/* Scrub the fields in an individual quota item. */
169STATIC int
170xrep_quota_item(
171	struct xrep_quota_info	*rqi,
172	struct xfs_dquot	*dq)
173{
174	struct xfs_scrub	*sc = rqi->sc;
175	struct xfs_mount	*mp = sc->mp;
176	xfs_ino_t		fs_icount;
177	bool			dirty = false;
178	int			error = 0;
179
180	/* Last chance to abort before we start committing fixes. */
181	if (xchk_should_terminate(sc, &error))
182		return error;
183
184	/*
185	 * We might need to fix holes in the bmap record for the storage
186	 * backing this dquot, so we need to lock the dquot and the quota file.
187	 */
188	xchk_ilock(sc, XFS_ILOCK_EXCL);
189	mutex_lock(&dq->q_qlock);
190	error = xrep_quota_item_bmap(sc, dq, &dirty);
191	xchk_iunlock(sc, XFS_ILOCK_EXCL);
192	if (error)
193		goto out_unlock_dquot;
194
195	/* Check the limits. */
196	if (dq->q_blk.softlimit > dq->q_blk.hardlimit) {
197		dq->q_blk.softlimit = dq->q_blk.hardlimit;
198		dirty = true;
199	}
200
201	if (dq->q_ino.softlimit > dq->q_ino.hardlimit) {
202		dq->q_ino.softlimit = dq->q_ino.hardlimit;
203		dirty = true;
204	}
205
206	if (dq->q_rtb.softlimit > dq->q_rtb.hardlimit) {
207		dq->q_rtb.softlimit = dq->q_rtb.hardlimit;
208		dirty = true;
209	}
210
211	/*
212	 * Check that usage doesn't exceed physical limits.  However, on
213	 * a reflink filesystem we're allowed to exceed physical space
214	 * if there are no quota limits.  We don't know what the real number
215	 * is, but we can make quotacheck find out for us.
216	 */
217	if (!xfs_has_reflink(mp) && dq->q_blk.count > mp->m_sb.sb_dblocks) {
218		dq->q_blk.reserved -= dq->q_blk.count;
219		dq->q_blk.reserved += mp->m_sb.sb_dblocks;
220		dq->q_blk.count = mp->m_sb.sb_dblocks;
221		rqi->need_quotacheck = true;
222		dirty = true;
223	}
224	fs_icount = percpu_counter_sum(&mp->m_icount);
225	if (dq->q_ino.count > fs_icount) {
226		dq->q_ino.reserved -= dq->q_ino.count;
227		dq->q_ino.reserved += fs_icount;
228		dq->q_ino.count = fs_icount;
229		rqi->need_quotacheck = true;
230		dirty = true;
231	}
232	if (!xfs_has_reflink(mp) && dq->q_rtb.count > mp->m_sb.sb_rblocks) {
233		dq->q_rtb.reserved -= dq->q_rtb.count;
234		dq->q_rtb.reserved += mp->m_sb.sb_rblocks;
235		dq->q_rtb.count = mp->m_sb.sb_rblocks;
236		rqi->need_quotacheck = true;
237		dirty = true;
238	}
239
240	xrep_quota_item_timer(sc, &dq->q_blk, &dirty);
241	xrep_quota_item_timer(sc, &dq->q_ino, &dirty);
242	xrep_quota_item_timer(sc, &dq->q_rtb, &dirty);
243
244	if (!dirty)
245		goto out_unlock_dquot;
246
247	trace_xrep_dquot_item(sc->mp, dq->q_type, dq->q_id);
248
249	dq->q_flags |= XFS_DQFLAG_DIRTY;
250	xfs_trans_dqjoin(sc->tp, dq);
251	if (dq->q_id) {
252		xfs_qm_adjust_dqlimits(dq);
253		xfs_qm_adjust_dqtimers(dq);
254	}
255	xfs_trans_log_dquot(sc->tp, dq);
256	return xfs_trans_roll(&sc->tp);
257
258out_unlock_dquot:
259	mutex_unlock(&dq->q_qlock);
260	return error;
261}
262
263/* Fix a quota timer so that we can pass the verifier. */
264STATIC void
265xrep_quota_fix_timer(
266	struct xfs_mount	*mp,
267	const struct xfs_disk_dquot *ddq,
268	__be64			softlimit,
269	__be64			countnow,
270	__be32			*timer,
271	time64_t		timelimit)
272{
273	uint64_t		soft = be64_to_cpu(softlimit);
274	uint64_t		count = be64_to_cpu(countnow);
275	time64_t		new_timer;
276	uint32_t		t;
277
278	if (!soft || count <= soft || *timer != 0)
279		return;
280
281	new_timer = xfs_dquot_set_timeout(mp,
282				ktime_get_real_seconds() + timelimit);
283	if (ddq->d_type & XFS_DQTYPE_BIGTIME)
284		t = xfs_dq_unix_to_bigtime(new_timer);
285	else
286		t = new_timer;
287
288	*timer = cpu_to_be32(t);
289}
290
291/* Fix anything the verifiers complain about. */
292STATIC int
293xrep_quota_block(
294	struct xfs_scrub	*sc,
295	xfs_daddr_t		daddr,
296	xfs_dqtype_t		dqtype,
297	xfs_dqid_t		id)
298{
299	struct xfs_dqblk	*dqblk;
300	struct xfs_disk_dquot	*ddq;
301	struct xfs_quotainfo	*qi = sc->mp->m_quotainfo;
302	struct xfs_def_quota	*defq = xfs_get_defquota(qi, dqtype);
303	struct xfs_buf		*bp = NULL;
304	enum xfs_blft		buftype = 0;
305	int			i;
306	int			error;
307
308	error = xfs_trans_read_buf(sc->mp, sc->tp, sc->mp->m_ddev_targp, daddr,
309			qi->qi_dqchunklen, 0, &bp, &xfs_dquot_buf_ops);
310	switch (error) {
311	case -EFSBADCRC:
312	case -EFSCORRUPTED:
313		/* Failed verifier, retry read with no ops. */
314		error = xfs_trans_read_buf(sc->mp, sc->tp,
315				sc->mp->m_ddev_targp, daddr, qi->qi_dqchunklen,
316				0, &bp, NULL);
317		if (error)
318			return error;
319		break;
320	case 0:
321		dqblk = bp->b_addr;
322		ddq = &dqblk[0].dd_diskdq;
323
324		/*
325		 * If there's nothing that would impede a dqiterate, we're
326		 * done.
327		 */
328		if ((ddq->d_type & XFS_DQTYPE_REC_MASK) != dqtype ||
329		    id == be32_to_cpu(ddq->d_id)) {
330			xfs_trans_brelse(sc->tp, bp);
331			return 0;
332		}
333		break;
334	default:
335		return error;
336	}
337
338	/* Something's wrong with the block, fix the whole thing. */
339	dqblk = bp->b_addr;
340	bp->b_ops = &xfs_dquot_buf_ops;
341	for (i = 0; i < qi->qi_dqperchunk; i++, dqblk++) {
342		ddq = &dqblk->dd_diskdq;
343
344		trace_xrep_disk_dquot(sc->mp, dqtype, id + i);
345
346		ddq->d_magic = cpu_to_be16(XFS_DQUOT_MAGIC);
347		ddq->d_version = XFS_DQUOT_VERSION;
348		ddq->d_type = dqtype;
349		ddq->d_id = cpu_to_be32(id + i);
350
351		if (xfs_has_bigtime(sc->mp) && ddq->d_id)
352			ddq->d_type |= XFS_DQTYPE_BIGTIME;
353
354		xrep_quota_fix_timer(sc->mp, ddq, ddq->d_blk_softlimit,
355				ddq->d_bcount, &ddq->d_btimer,
356				defq->blk.time);
357
358		xrep_quota_fix_timer(sc->mp, ddq, ddq->d_ino_softlimit,
359				ddq->d_icount, &ddq->d_itimer,
360				defq->ino.time);
361
362		xrep_quota_fix_timer(sc->mp, ddq, ddq->d_rtb_softlimit,
363				ddq->d_rtbcount, &ddq->d_rtbtimer,
364				defq->rtb.time);
365
366		/* We only support v5 filesystems so always set these. */
367		uuid_copy(&dqblk->dd_uuid, &sc->mp->m_sb.sb_meta_uuid);
368		xfs_update_cksum((char *)dqblk, sizeof(struct xfs_dqblk),
369				 XFS_DQUOT_CRC_OFF);
370		dqblk->dd_lsn = 0;
371	}
372	switch (dqtype) {
373	case XFS_DQTYPE_USER:
374		buftype = XFS_BLFT_UDQUOT_BUF;
375		break;
376	case XFS_DQTYPE_GROUP:
377		buftype = XFS_BLFT_GDQUOT_BUF;
378		break;
379	case XFS_DQTYPE_PROJ:
380		buftype = XFS_BLFT_PDQUOT_BUF;
381		break;
382	}
383	xfs_trans_buf_set_type(sc->tp, bp, buftype);
384	xfs_trans_log_buf(sc->tp, bp, 0, BBTOB(bp->b_length) - 1);
385	return xrep_roll_trans(sc);
386}
387
388/*
389 * Repair a quota file's data fork.  The function returns with the inode
390 * joined.
391 */
392STATIC int
393xrep_quota_data_fork(
394	struct xfs_scrub	*sc,
395	xfs_dqtype_t		dqtype)
396{
397	struct xfs_bmbt_irec	irec = { 0 };
398	struct xfs_iext_cursor	icur;
399	struct xfs_quotainfo	*qi = sc->mp->m_quotainfo;
400	struct xfs_ifork	*ifp;
401	xfs_fileoff_t		max_dqid_off;
402	xfs_fileoff_t		off;
403	xfs_fsblock_t		fsbno;
404	bool			truncate = false;
405	bool			joined = false;
406	int			error = 0;
407
408	error = xrep_metadata_inode_forks(sc);
409	if (error)
410		goto out;
411
412	/* Check for data fork problems that apply only to quota files. */
413	max_dqid_off = XFS_DQ_ID_MAX / qi->qi_dqperchunk;
414	ifp = xfs_ifork_ptr(sc->ip, XFS_DATA_FORK);
415	for_each_xfs_iext(ifp, &icur, &irec) {
416		if (isnullstartblock(irec.br_startblock)) {
417			error = -EFSCORRUPTED;
418			goto out;
419		}
420
421		if (irec.br_startoff > max_dqid_off ||
422		    irec.br_startoff + irec.br_blockcount - 1 > max_dqid_off) {
423			truncate = true;
424			break;
425		}
426
427		/* Convert unwritten extents to real ones. */
428		if (irec.br_state == XFS_EXT_UNWRITTEN) {
429			struct xfs_bmbt_irec	nrec;
430			int			nmap = 1;
431
432			if (!joined) {
433				xfs_trans_ijoin(sc->tp, sc->ip, 0);
434				joined = true;
435			}
436
437			error = xfs_bmapi_write(sc->tp, sc->ip,
438					irec.br_startoff, irec.br_blockcount,
439					XFS_BMAPI_CONVERT, 0, &nrec, &nmap);
440			if (error)
441				goto out;
442			ASSERT(nrec.br_startoff == irec.br_startoff);
443			ASSERT(nrec.br_blockcount == irec.br_blockcount);
444
445			error = xfs_defer_finish(&sc->tp);
446			if (error)
447				goto out;
448		}
449	}
450
451	if (!joined) {
452		xfs_trans_ijoin(sc->tp, sc->ip, 0);
453		joined = true;
454	}
455
456	if (truncate) {
457		/* Erase everything after the block containing the max dquot */
458		error = xfs_bunmapi_range(&sc->tp, sc->ip, 0,
459				max_dqid_off * sc->mp->m_sb.sb_blocksize,
460				XFS_MAX_FILEOFF);
461		if (error)
462			goto out;
463
464		/* Remove all CoW reservations. */
465		error = xfs_reflink_cancel_cow_blocks(sc->ip, &sc->tp, 0,
466				XFS_MAX_FILEOFF, true);
467		if (error)
468			goto out;
469		sc->ip->i_diflags2 &= ~XFS_DIFLAG2_REFLINK;
470
471		/*
472		 * Always re-log the inode so that our permanent transaction
473		 * can keep on rolling it forward in the log.
474		 */
475		xfs_trans_log_inode(sc->tp, sc->ip, XFS_ILOG_CORE);
476	}
477
478	/* Now go fix anything that fails the verifiers. */
479	for_each_xfs_iext(ifp, &icur, &irec) {
480		for (fsbno = irec.br_startblock, off = irec.br_startoff;
481		     fsbno < irec.br_startblock + irec.br_blockcount;
482		     fsbno += XFS_DQUOT_CLUSTER_SIZE_FSB,
483				off += XFS_DQUOT_CLUSTER_SIZE_FSB) {
484			error = xrep_quota_block(sc,
485					XFS_FSB_TO_DADDR(sc->mp, fsbno),
486					dqtype, off * qi->qi_dqperchunk);
487			if (error)
488				goto out;
489		}
490	}
491
492out:
493	return error;
494}
495
496/*
497 * Go fix anything in the quota items that we could have been mad about.  Now
498 * that we've checked the quota inode data fork we have to drop ILOCK_EXCL to
499 * use the regular dquot functions.
500 */
501STATIC int
502xrep_quota_problems(
503	struct xfs_scrub	*sc,
504	xfs_dqtype_t		dqtype)
505{
506	struct xchk_dqiter	cursor = { };
507	struct xrep_quota_info	rqi = { .sc = sc };
508	struct xfs_dquot	*dq;
509	int			error;
510
511	xchk_dqiter_init(&cursor, sc, dqtype);
512	while ((error = xchk_dquot_iter(&cursor, &dq)) == 1) {
513		error = xrep_quota_item(&rqi, dq);
514		xfs_qm_dqrele(dq);
515		if (error)
516			break;
517	}
518	if (error)
519		return error;
520
521	/* Make a quotacheck happen. */
522	if (rqi.need_quotacheck)
523		xrep_force_quotacheck(sc, dqtype);
524	return 0;
525}
526
527/* Repair all of a quota type's items. */
528int
529xrep_quota(
530	struct xfs_scrub	*sc)
531{
532	xfs_dqtype_t		dqtype;
533	int			error;
534
535	dqtype = xchk_quota_to_dqtype(sc);
536
537	/*
538	 * Re-take the ILOCK so that we can fix any problems that we found
539	 * with the data fork mappings, or with the dquot bufs themselves.
540	 */
541	if (!(sc->ilock_flags & XFS_ILOCK_EXCL))
542		xchk_ilock(sc, XFS_ILOCK_EXCL);
543	error = xrep_quota_data_fork(sc, dqtype);
544	if (error)
545		return error;
546
547	/*
548	 * Finish deferred items and roll the transaction to unjoin the quota
549	 * inode from transaction so that we can unlock the quota inode; we
550	 * play only with dquots from now on.
551	 */
552	error = xrep_defer_finish(sc);
553	if (error)
554		return error;
555	error = xfs_trans_roll(&sc->tp);
556	if (error)
557		return error;
558	xchk_iunlock(sc, sc->ilock_flags);
559
560	/* Fix anything the dquot verifiers don't complain about. */
561	error = xrep_quota_problems(sc, dqtype);
562	if (error)
563		return error;
564
565	return xrep_trans_commit(sc);
566}
~/ Read-only file preview.