File Index
Files and directories
Sign in
FILE

quotacheck.c

File preview with syntax highlighting.

linux-6.19.14/fs/xfs/scrub/quotacheck.c C
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * Copyright (c) 2020-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_quota.h"
 16#include "xfs_qm.h"
 17#include "xfs_icache.h"
 18#include "xfs_bmap_util.h"
 19#include "xfs_ialloc.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/quota.h"
 28#include "scrub/quotacheck.h"
 29#include "scrub/trace.h"
 30
 31/*
 32 * Live Quotacheck
 33 * ===============
 34 *
 35 * Quota counters are "summary" metadata, in the sense that they are computed
 36 * as the summation of the block usage counts for every file on the filesystem.
 37 * Therefore, we compute the correct icount, bcount, and rtbcount values by
 38 * creating a shadow quota counter structure and walking every inode.
 39 */
 40
 41/* Track the quota deltas for a dquot in a transaction. */
 42struct xqcheck_dqtrx {
 43	xfs_dqtype_t		q_type;
 44	xfs_dqid_t		q_id;
 45
 46	int64_t			icount_delta;
 47
 48	int64_t			bcount_delta;
 49	int64_t			delbcnt_delta;
 50
 51	int64_t			rtbcount_delta;
 52	int64_t			delrtb_delta;
 53};
 54
 55#define XQCHECK_MAX_NR_DQTRXS	(XFS_QM_TRANS_DQTYPES * XFS_QM_TRANS_MAXDQS)
 56
 57/*
 58 * Track the quota deltas for all dquots attached to a transaction if the
 59 * quota deltas are being applied to an inode that we already scanned.
 60 */
 61struct xqcheck_dqacct {
 62	struct rhash_head	hash;
 63	uintptr_t		tx_id;
 64	struct xqcheck_dqtrx	dqtrx[XQCHECK_MAX_NR_DQTRXS];
 65	unsigned int		refcount;
 66};
 67
 68/* Free a shadow dquot accounting structure. */
 69static void
 70xqcheck_dqacct_free(
 71	void			*ptr,
 72	void			*arg)
 73{
 74	struct xqcheck_dqacct	*dqa = ptr;
 75
 76	kfree(dqa);
 77}
 78
 79/* Set us up to scrub quota counters. */
 80int
 81xchk_setup_quotacheck(
 82	struct xfs_scrub	*sc)
 83{
 84	if (!XFS_IS_QUOTA_ON(sc->mp))
 85		return -ENOENT;
 86
 87	xchk_fsgates_enable(sc, XCHK_FSGATES_QUOTA);
 88
 89	sc->buf = kzalloc(sizeof(struct xqcheck), XCHK_GFP_FLAGS);
 90	if (!sc->buf)
 91		return -ENOMEM;
 92
 93	return xchk_setup_fs(sc);
 94}
 95
 96/*
 97 * Part 1: Collecting dquot resource usage counts.  For each xfs_dquot attached
 98 * to each inode, we create a shadow dquot, and compute the inode count and add
 99 * the data/rt block usage from what we see.
100 *
101 * To avoid false corruption reports in part 2, any failure in this part must
102 * set the INCOMPLETE flag even when a negative errno is returned.  This care
103 * must be taken with certain errno values (i.e. EFSBADCRC, EFSCORRUPTED,
104 * ECANCELED) that are absorbed into a scrub state flag update by
105 * xchk_*_process_error.  Scrub and repair share the same incore data
106 * structures, so the INCOMPLETE flag is critical to prevent a repair based on
107 * insufficient information.
108 *
109 * Because we are scanning a live filesystem, it's possible that another thread
110 * will try to update the quota counters for an inode that we've already
111 * scanned.  This will cause our counts to be incorrect.  Therefore, we hook
112 * the live transaction code in two places: (1) when the callers update the
113 * per-transaction dqtrx structure to log quota counter updates; and (2) when
114 * transaction commit actually logs those updates to the incore dquot.  By
115 * shadowing transaction updates in this manner, live quotacheck can ensure
116 * by locking the dquot and the shadow structure that its own copies are not
117 * out of date.  Because the hook code runs in a different process context from
118 * the scrub code and the scrub state flags are not accessed atomically,
119 * failures in the hook code must abort the iscan and the scrubber must notice
120 * the aborted scan and set the incomplete flag.
121 *
122 * Note that we use srcu notifier hooks to minimize the overhead when live
123 * quotacheck is /not/ running.
124 */
125
126/* Update an incore dquot counter information from a live update. */
127static int
128xqcheck_update_incore_counts(
129	struct xqcheck		*xqc,
130	struct xfarray		*counts,
131	xfs_dqid_t		id,
132	int64_t			inodes,
133	int64_t			nblks,
134	int64_t			rtblks)
135{
136	struct xqcheck_dquot	xcdq;
137	int			error;
138
139	error = xfarray_load_sparse(counts, id, &xcdq);
140	if (error)
141		return error;
142
143	xcdq.flags |= XQCHECK_DQUOT_WRITTEN;
144	xcdq.icount += inodes;
145	xcdq.bcount += nblks;
146	xcdq.rtbcount += rtblks;
147
148	error = xfarray_store(counts, id, &xcdq);
149	if (error == -EFBIG) {
150		/*
151		 * EFBIG means we tried to store data at too high a byte offset
152		 * in the sparse array.  IOWs, we cannot complete the check and
153		 * must notify userspace that the check was incomplete.
154		 */
155		error = -ECANCELED;
156	}
157	return error;
158}
159
160/* Decide if this is the shadow dquot accounting structure for a transaction. */
161static int
162xqcheck_dqacct_obj_cmpfn(
163	struct rhashtable_compare_arg	*arg,
164	const void			*obj)
165{
166	const uintptr_t			*tx_idp = arg->key;
167	const struct xqcheck_dqacct	*dqa = obj;
168
169	if (dqa->tx_id != *tx_idp)
170		return 1;
171	return 0;
172}
173
174static const struct rhashtable_params xqcheck_dqacct_hash_params = {
175	.min_size		= 32,
176	.key_len		= sizeof(uintptr_t),
177	.key_offset		= offsetof(struct xqcheck_dqacct, tx_id),
178	.head_offset		= offsetof(struct xqcheck_dqacct, hash),
179	.automatic_shrinking	= true,
180	.obj_cmpfn		= xqcheck_dqacct_obj_cmpfn,
181};
182
183/* Find a shadow dqtrx slot for the given dquot. */
184STATIC struct xqcheck_dqtrx *
185xqcheck_get_dqtrx(
186	struct xqcheck_dqacct	*dqa,
187	xfs_dqtype_t		q_type,
188	xfs_dqid_t		q_id)
189{
190	int			i;
191
192	for (i = 0; i < XQCHECK_MAX_NR_DQTRXS; i++) {
193		if (dqa->dqtrx[i].q_type == 0 ||
194		    (dqa->dqtrx[i].q_type == q_type &&
195		     dqa->dqtrx[i].q_id == q_id))
196			return &dqa->dqtrx[i];
197	}
198
199	return NULL;
200}
201
202/*
203 * Create and fill out a quota delta tracking structure to shadow the updates
204 * going on in the regular quota code.
205 */
206static int
207xqcheck_mod_live_ino_dqtrx(
208	struct notifier_block		*nb,
209	unsigned long			action,
210	void				*data)
211{
212	struct xfs_mod_ino_dqtrx_params *p = data;
213	struct xqcheck			*xqc;
214	struct xqcheck_dqacct		*dqa;
215	struct xqcheck_dqtrx		*dqtrx;
216	int				error;
217
218	xqc = container_of(nb, struct xqcheck, qhook.mod_hook.nb);
219
220	/* Skip quota reservation fields. */
221	switch (action) {
222	case XFS_TRANS_DQ_BCOUNT:
223	case XFS_TRANS_DQ_DELBCOUNT:
224	case XFS_TRANS_DQ_ICOUNT:
225	case XFS_TRANS_DQ_RTBCOUNT:
226	case XFS_TRANS_DQ_DELRTBCOUNT:
227		break;
228	default:
229		return NOTIFY_DONE;
230	}
231
232	/* Ignore dqtrx updates for quota types we don't care about. */
233	switch (p->q_type) {
234	case XFS_DQTYPE_USER:
235		if (!xqc->ucounts)
236			return NOTIFY_DONE;
237		break;
238	case XFS_DQTYPE_GROUP:
239		if (!xqc->gcounts)
240			return NOTIFY_DONE;
241		break;
242	case XFS_DQTYPE_PROJ:
243		if (!xqc->pcounts)
244			return NOTIFY_DONE;
245		break;
246	default:
247		return NOTIFY_DONE;
248	}
249
250	/* Skip inodes that haven't been scanned yet. */
251	if (!xchk_iscan_want_live_update(&xqc->iscan, p->ino))
252		return NOTIFY_DONE;
253
254	/* Make a shadow quota accounting tracker for this transaction. */
255	mutex_lock(&xqc->lock);
256	dqa = rhashtable_lookup_fast(&xqc->shadow_dquot_acct, &p->tx_id,
257			xqcheck_dqacct_hash_params);
258	if (!dqa) {
259		dqa = kzalloc(sizeof(struct xqcheck_dqacct), XCHK_GFP_FLAGS);
260		if (!dqa)
261			goto out_abort;
262
263		dqa->tx_id = p->tx_id;
264		error = rhashtable_insert_fast(&xqc->shadow_dquot_acct,
265				&dqa->hash, xqcheck_dqacct_hash_params);
266		if (error)
267			goto out_abort;
268	}
269
270	/* Find the shadow dqtrx (or an empty slot) here. */
271	dqtrx = xqcheck_get_dqtrx(dqa, p->q_type, p->q_id);
272	if (!dqtrx)
273		goto out_abort;
274	if (dqtrx->q_type == 0) {
275		dqtrx->q_type = p->q_type;
276		dqtrx->q_id = p->q_id;
277		dqa->refcount++;
278	}
279
280	/* Update counter */
281	switch (action) {
282	case XFS_TRANS_DQ_BCOUNT:
283		dqtrx->bcount_delta += p->delta;
284		break;
285	case XFS_TRANS_DQ_DELBCOUNT:
286		dqtrx->delbcnt_delta += p->delta;
287		break;
288	case XFS_TRANS_DQ_ICOUNT:
289		dqtrx->icount_delta += p->delta;
290		break;
291	case XFS_TRANS_DQ_RTBCOUNT:
292		dqtrx->rtbcount_delta += p->delta;
293		break;
294	case XFS_TRANS_DQ_DELRTBCOUNT:
295		dqtrx->delrtb_delta += p->delta;
296		break;
297	}
298
299	mutex_unlock(&xqc->lock);
300	return NOTIFY_DONE;
301
302out_abort:
303	xchk_iscan_abort(&xqc->iscan);
304	mutex_unlock(&xqc->lock);
305	return NOTIFY_DONE;
306}
307
308/*
309 * Apply the transaction quota deltas to our shadow quota accounting info when
310 * the regular quota code are doing the same.
311 */
312static int
313xqcheck_apply_live_dqtrx(
314	struct notifier_block		*nb,
315	unsigned long			action,
316	void				*data)
317{
318	struct xfs_apply_dqtrx_params	*p = data;
319	struct xqcheck			*xqc;
320	struct xqcheck_dqacct		*dqa;
321	struct xqcheck_dqtrx		*dqtrx;
322	struct xfarray			*counts;
323	int				error;
324
325	xqc = container_of(nb, struct xqcheck, qhook.apply_hook.nb);
326
327	/* Map the dquot type to an incore counter object. */
328	switch (p->q_type) {
329	case XFS_DQTYPE_USER:
330		counts = xqc->ucounts;
331		break;
332	case XFS_DQTYPE_GROUP:
333		counts = xqc->gcounts;
334		break;
335	case XFS_DQTYPE_PROJ:
336		counts = xqc->pcounts;
337		break;
338	default:
339		return NOTIFY_DONE;
340	}
341
342	if (xchk_iscan_aborted(&xqc->iscan) || counts == NULL)
343		return NOTIFY_DONE;
344
345	/*
346	 * Find the shadow dqtrx for this transaction and dquot, if any deltas
347	 * need to be applied here.  If not, we're finished early.
348	 */
349	mutex_lock(&xqc->lock);
350	dqa = rhashtable_lookup_fast(&xqc->shadow_dquot_acct, &p->tx_id,
351			xqcheck_dqacct_hash_params);
352	if (!dqa)
353		goto out_unlock;
354	dqtrx = xqcheck_get_dqtrx(dqa, p->q_type, p->q_id);
355	if (!dqtrx || dqtrx->q_type == 0)
356		goto out_unlock;
357
358	/* Update our shadow dquot if we're committing. */
359	if (action == XFS_APPLY_DQTRX_COMMIT) {
360		error = xqcheck_update_incore_counts(xqc, counts, p->q_id,
361				dqtrx->icount_delta,
362				dqtrx->bcount_delta + dqtrx->delbcnt_delta,
363				dqtrx->rtbcount_delta + dqtrx->delrtb_delta);
364		if (error)
365			goto out_abort;
366	}
367
368	/* Free the shadow accounting structure if that was the last user. */
369	dqa->refcount--;
370	if (dqa->refcount == 0) {
371		error = rhashtable_remove_fast(&xqc->shadow_dquot_acct,
372				&dqa->hash, xqcheck_dqacct_hash_params);
373		if (error)
374			goto out_abort;
375		xqcheck_dqacct_free(dqa, NULL);
376	}
377
378	mutex_unlock(&xqc->lock);
379	return NOTIFY_DONE;
380
381out_abort:
382	xchk_iscan_abort(&xqc->iscan);
383out_unlock:
384	mutex_unlock(&xqc->lock);
385	return NOTIFY_DONE;
386}
387
388/* Record this inode's quota usage in our shadow quota counter data. */
389STATIC int
390xqcheck_collect_inode(
391	struct xqcheck		*xqc,
392	struct xfs_inode	*ip)
393{
394	struct xfs_trans	*tp = xqc->sc->tp;
395	xfs_filblks_t		nblks, rtblks;
396	uint			ilock_flags = 0;
397	xfs_dqid_t		id;
398	bool			isreg = S_ISREG(VFS_I(ip)->i_mode);
399	int			error = 0;
400
401	if (xfs_is_metadir_inode(ip) ||
402	    xfs_is_quota_inode(&tp->t_mountp->m_sb, ip->i_ino)) {
403		/*
404		 * Quota files are never counted towards quota, so we do not
405		 * need to take the lock.  Files do not switch between the
406		 * metadata and regular directory trees without a reallocation,
407		 * so we do not need to ILOCK them either.
408		 */
409		xchk_iscan_mark_visited(&xqc->iscan, ip);
410		return 0;
411	}
412
413	/* Figure out the data / rt device block counts. */
414	xfs_ilock(ip, XFS_IOLOCK_SHARED);
415	if (isreg)
416		xfs_ilock(ip, XFS_MMAPLOCK_SHARED);
417	if (XFS_IS_REALTIME_INODE(ip)) {
418		/*
419		 * Read in the data fork for rt files so that _count_blocks
420		 * can count the number of blocks allocated from the rt volume.
421		 * Inodes do not track that separately.
422		 */
423		ilock_flags = xfs_ilock_data_map_shared(ip);
424		error = xfs_iread_extents(tp, ip, XFS_DATA_FORK);
425		if (error)
426			goto out_abort;
427	} else {
428		ilock_flags = XFS_ILOCK_SHARED;
429		xfs_ilock(ip, XFS_ILOCK_SHARED);
430	}
431	xfs_inode_count_blocks(tp, ip, &nblks, &rtblks);
432
433	if (xchk_iscan_aborted(&xqc->iscan)) {
434		error = -ECANCELED;
435		goto out_incomplete;
436	}
437
438	/* Update the shadow dquot counters. */
439	mutex_lock(&xqc->lock);
440	if (xqc->ucounts) {
441		id = xfs_qm_id_for_quotatype(ip, XFS_DQTYPE_USER);
442		error = xqcheck_update_incore_counts(xqc, xqc->ucounts, id, 1,
443				nblks, rtblks);
444		if (error)
445			goto out_mutex;
446	}
447
448	if (xqc->gcounts) {
449		id = xfs_qm_id_for_quotatype(ip, XFS_DQTYPE_GROUP);
450		error = xqcheck_update_incore_counts(xqc, xqc->gcounts, id, 1,
451				nblks, rtblks);
452		if (error)
453			goto out_mutex;
454	}
455
456	if (xqc->pcounts) {
457		id = xfs_qm_id_for_quotatype(ip, XFS_DQTYPE_PROJ);
458		error = xqcheck_update_incore_counts(xqc, xqc->pcounts, id, 1,
459				nblks, rtblks);
460		if (error)
461			goto out_mutex;
462	}
463	mutex_unlock(&xqc->lock);
464
465	xchk_iscan_mark_visited(&xqc->iscan, ip);
466	goto out_ilock;
467
468out_mutex:
469	mutex_unlock(&xqc->lock);
470out_abort:
471	xchk_iscan_abort(&xqc->iscan);
472out_incomplete:
473	xchk_set_incomplete(xqc->sc);
474out_ilock:
475	xfs_iunlock(ip, ilock_flags);
476	if (isreg)
477		xfs_iunlock(ip, XFS_MMAPLOCK_SHARED);
478	xfs_iunlock(ip, XFS_IOLOCK_SHARED);
479	return error;
480}
481
482/* Walk all the allocated inodes and run a quota scan on them. */
483STATIC int
484xqcheck_collect_counts(
485	struct xqcheck		*xqc)
486{
487	struct xfs_scrub	*sc = xqc->sc;
488	struct xfs_inode	*ip;
489	int			error;
490
491	/*
492	 * Set up for a potentially lengthy filesystem scan by reducing our
493	 * transaction resource usage for the duration.  Specifically:
494	 *
495	 * Cancel the transaction to release the log grant space while we scan
496	 * the filesystem.
497	 *
498	 * Create a new empty transaction to eliminate the possibility of the
499	 * inode scan deadlocking on cyclical metadata.
500	 *
501	 * We pass the empty transaction to the file scanning function to avoid
502	 * repeatedly cycling empty transactions.  This can be done without
503	 * risk of deadlock between sb_internal and the IOLOCK (we take the
504	 * IOLOCK to quiesce the file before scanning) because empty
505	 * transactions do not take sb_internal.
506	 */
507	xchk_trans_cancel(sc);
508	xchk_trans_alloc_empty(sc);
509
510	while ((error = xchk_iscan_iter(&xqc->iscan, &ip)) == 1) {
511		error = xqcheck_collect_inode(xqc, ip);
512		xchk_irele(sc, ip);
513		if (error)
514			break;
515
516		if (xchk_should_terminate(sc, &error))
517			break;
518	}
519	xchk_iscan_iter_finish(&xqc->iscan);
520	if (error) {
521		xchk_set_incomplete(sc);
522		/*
523		 * If we couldn't grab an inode that was busy with a state
524		 * change, change the error code so that we exit to userspace
525		 * as quickly as possible.
526		 */
527		if (error == -EBUSY)
528			return -ECANCELED;
529		return error;
530	}
531
532	/*
533	 * Switch out for a real transaction in preparation for building a new
534	 * tree.
535	 */
536	xchk_trans_cancel(sc);
537	return xchk_setup_fs(sc);
538}
539
540/*
541 * Part 2: Comparing dquot resource counters.  Walk each xfs_dquot, comparing
542 * the resource usage counters against our shadow dquots; and then walk each
543 * shadow dquot (that wasn't covered in the first part), comparing it against
544 * the xfs_dquot.
545 */
546
547/*
548 * Check the dquot data against what we observed.  Caller must hold the dquot
549 * lock.
550 */
551STATIC int
552xqcheck_compare_dquot(
553	struct xqcheck		*xqc,
554	xfs_dqtype_t		dqtype,
555	struct xfs_dquot	*dq)
556{
557	struct xqcheck_dquot	xcdq;
558	struct xfarray		*counts = xqcheck_counters_for(xqc, dqtype);
559	int			error;
560
561	if (xchk_iscan_aborted(&xqc->iscan)) {
562		xchk_set_incomplete(xqc->sc);
563		return -ECANCELED;
564	}
565
566	mutex_lock(&dq->q_qlock);
567	mutex_lock(&xqc->lock);
568	error = xfarray_load_sparse(counts, dq->q_id, &xcdq);
569	if (error)
570		goto out_unlock;
571
572	if (xcdq.icount != dq->q_ino.count)
573		xchk_qcheck_set_corrupt(xqc->sc, dqtype, dq->q_id);
574
575	if (xcdq.bcount != dq->q_blk.count)
576		xchk_qcheck_set_corrupt(xqc->sc, dqtype, dq->q_id);
577
578	if (xcdq.rtbcount != dq->q_rtb.count)
579		xchk_qcheck_set_corrupt(xqc->sc, dqtype, dq->q_id);
580
581	xcdq.flags |= (XQCHECK_DQUOT_COMPARE_SCANNED | XQCHECK_DQUOT_WRITTEN);
582	error = xfarray_store(counts, dq->q_id, &xcdq);
583	if (error == -EFBIG) {
584		/*
585		 * EFBIG means we tried to store data at too high a byte offset
586		 * in the sparse array.  IOWs, we cannot complete the check and
587		 * must notify userspace that the check was incomplete.  This
588		 * should never happen outside of the collection phase.
589		 */
590		xchk_set_incomplete(xqc->sc);
591		error = -ECANCELED;
592	}
593out_unlock:
594	mutex_unlock(&xqc->lock);
595	mutex_unlock(&dq->q_qlock);
596	if (error)
597		return error;
598
599	if (xqc->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
600		return -ECANCELED;
601
602	return 0;
603}
604
605/*
606 * Walk all the observed dquots, and make sure there's a matching incore
607 * dquot and that its counts match ours.
608 */
609STATIC int
610xqcheck_walk_observations(
611	struct xqcheck		*xqc,
612	xfs_dqtype_t		dqtype)
613{
614	struct xqcheck_dquot	xcdq;
615	struct xfs_dquot	*dq;
616	struct xfarray		*counts = xqcheck_counters_for(xqc, dqtype);
617	xfarray_idx_t		cur = XFARRAY_CURSOR_INIT;
618	int			error;
619
620	mutex_lock(&xqc->lock);
621	while ((error = xfarray_iter(counts, &cur, &xcdq)) == 1) {
622		xfs_dqid_t	id = cur - 1;
623
624		if (xcdq.flags & XQCHECK_DQUOT_COMPARE_SCANNED)
625			continue;
626
627		mutex_unlock(&xqc->lock);
628
629		error = xfs_qm_dqget(xqc->sc->mp, id, dqtype, false, &dq);
630		if (error == -ENOENT) {
631			xchk_qcheck_set_corrupt(xqc->sc, dqtype, id);
632			return 0;
633		}
634		if (error)
635			return error;
636
637		error = xqcheck_compare_dquot(xqc, dqtype, dq);
638		xfs_qm_dqrele(dq);
639		if (error)
640			return error;
641
642		if (xchk_should_terminate(xqc->sc, &error))
643			return error;
644
645		mutex_lock(&xqc->lock);
646	}
647	mutex_unlock(&xqc->lock);
648
649	return error;
650}
651
652/* Compare the quota counters we observed against the live dquots. */
653STATIC int
654xqcheck_compare_dqtype(
655	struct xqcheck		*xqc,
656	xfs_dqtype_t		dqtype)
657{
658	struct xchk_dqiter	cursor = { };
659	struct xfs_scrub	*sc = xqc->sc;
660	struct xfs_dquot	*dq;
661	int			error;
662
663	if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
664		return 0;
665
666	/* If the quota CHKD flag is cleared, we need to repair this quota. */
667	if (!(xfs_quota_chkd_flag(dqtype) & sc->mp->m_qflags)) {
668		xchk_qcheck_set_corrupt(xqc->sc, dqtype, 0);
669		return 0;
670	}
671
672	/* Compare what we observed against the actual dquots. */
673	xchk_dqiter_init(&cursor, sc, dqtype);
674	while ((error = xchk_dquot_iter(&cursor, &dq)) == 1) {
675		error = xqcheck_compare_dquot(xqc, dqtype, dq);
676		xfs_qm_dqrele(dq);
677		if (error)
678			break;
679	}
680	if (error)
681		return error;
682
683	/* Walk all the observed dquots and compare to the incore ones. */
684	return xqcheck_walk_observations(xqc, dqtype);
685}
686
687/* Tear down everything associated with a quotacheck. */
688static void
689xqcheck_teardown_scan(
690	void			*priv)
691{
692	struct xqcheck		*xqc = priv;
693	struct xfs_quotainfo	*qi = xqc->sc->mp->m_quotainfo;
694
695	/* Discourage any hook functions that might be running. */
696	xchk_iscan_abort(&xqc->iscan);
697
698	/*
699	 * As noted above, the apply hook is responsible for cleaning up the
700	 * shadow dquot accounting data when a transaction completes.  The mod
701	 * hook must be removed before the apply hook so that we don't
702	 * mistakenly leave an active shadow account for the mod hook to get
703	 * its hands on.  No hooks should be running after these functions
704	 * return.
705	 */
706	xfs_dqtrx_hook_del(qi, &xqc->qhook);
707
708	if (xqc->shadow_dquot_acct.key_len) {
709		rhashtable_free_and_destroy(&xqc->shadow_dquot_acct,
710				xqcheck_dqacct_free, NULL);
711		xqc->shadow_dquot_acct.key_len = 0;
712	}
713
714	if (xqc->pcounts) {
715		xfarray_destroy(xqc->pcounts);
716		xqc->pcounts = NULL;
717	}
718
719	if (xqc->gcounts) {
720		xfarray_destroy(xqc->gcounts);
721		xqc->gcounts = NULL;
722	}
723
724	if (xqc->ucounts) {
725		xfarray_destroy(xqc->ucounts);
726		xqc->ucounts = NULL;
727	}
728
729	xchk_iscan_teardown(&xqc->iscan);
730	mutex_destroy(&xqc->lock);
731	xqc->sc = NULL;
732}
733
734/*
735 * Scan all inodes in the entire filesystem to generate quota counter data.
736 * If the scan is successful, the quota data will be left alive for a repair.
737 * If any error occurs, we'll tear everything down.
738 */
739STATIC int
740xqcheck_setup_scan(
741	struct xfs_scrub	*sc,
742	struct xqcheck		*xqc)
743{
744	struct xfs_quotainfo	*qi = sc->mp->m_quotainfo;
745	unsigned long long	max_dquots = XFS_DQ_ID_MAX + 1ULL;
746	int			error;
747
748	ASSERT(xqc->sc == NULL);
749	xqc->sc = sc;
750
751	mutex_init(&xqc->lock);
752
753	/* Retry iget every tenth of a second for up to 30 seconds. */
754	xchk_iscan_start(sc, 30000, 100, &xqc->iscan);
755
756	error = -ENOMEM;
757	if (xfs_this_quota_on(sc->mp, XFS_DQTYPE_USER)) {
758		error = xfarray_create("user dquot records", max_dquots,
759				sizeof(struct xqcheck_dquot), &xqc->ucounts);
760		if (error)
761			goto out_teardown;
762	}
763
764	if (xfs_this_quota_on(sc->mp, XFS_DQTYPE_GROUP)) {
765		error = xfarray_create("group dquot records", max_dquots,
766				sizeof(struct xqcheck_dquot), &xqc->gcounts);
767		if (error)
768			goto out_teardown;
769	}
770
771	if (xfs_this_quota_on(sc->mp, XFS_DQTYPE_PROJ)) {
772		error = xfarray_create("project dquot records", max_dquots,
773				sizeof(struct xqcheck_dquot), &xqc->pcounts);
774		if (error)
775			goto out_teardown;
776	}
777
778	/*
779	 * Set up hash table to map transactions to our internal shadow dqtrx
780	 * structures.
781	 */
782	error = rhashtable_init(&xqc->shadow_dquot_acct,
783			&xqcheck_dqacct_hash_params);
784	if (error)
785		goto out_teardown;
786
787	/*
788	 * Hook into the quota code.  The hook only triggers for inodes that
789	 * were already scanned, and the scanner thread takes each inode's
790	 * ILOCK, which means that any in-progress inode updates will finish
791	 * before we can scan the inode.
792	 *
793	 * The apply hook (which removes the shadow dquot accounting struct)
794	 * must be installed before the mod hook so that we never fail to catch
795	 * the end of a quota update sequence and leave stale shadow data.
796	 */
797	ASSERT(sc->flags & XCHK_FSGATES_QUOTA);
798	xfs_dqtrx_hook_setup(&xqc->qhook, xqcheck_mod_live_ino_dqtrx,
799			xqcheck_apply_live_dqtrx);
800
801	error = xfs_dqtrx_hook_add(qi, &xqc->qhook);
802	if (error)
803		goto out_teardown;
804
805	/* Use deferred cleanup to pass the quota count data to repair. */
806	sc->buf_cleanup = xqcheck_teardown_scan;
807	return 0;
808
809out_teardown:
810	xqcheck_teardown_scan(xqc);
811	return error;
812}
813
814/* Scrub all counters for a given quota type. */
815int
816xchk_quotacheck(
817	struct xfs_scrub	*sc)
818{
819	struct xqcheck		*xqc = sc->buf;
820	int			error = 0;
821
822	/* Check quota counters on the live filesystem. */
823	error = xqcheck_setup_scan(sc, xqc);
824	if (error)
825		return error;
826
827	/* Walk all inodes, picking up quota information. */
828	error = xqcheck_collect_counts(xqc);
829	if (!xchk_xref_process_error(sc, 0, 0, &error))
830		return error;
831
832	/* Fail fast if we're not playing with a full dataset. */
833	if (xchk_iscan_aborted(&xqc->iscan))
834		xchk_set_incomplete(sc);
835	if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_INCOMPLETE)
836		return 0;
837
838	/* Compare quota counters. */
839	if (xqc->ucounts) {
840		error = xqcheck_compare_dqtype(xqc, XFS_DQTYPE_USER);
841		if (!xchk_xref_process_error(sc, 0, 0, &error))
842			return error;
843	}
844	if (xqc->gcounts) {
845		error = xqcheck_compare_dqtype(xqc, XFS_DQTYPE_GROUP);
846		if (!xchk_xref_process_error(sc, 0, 0, &error))
847			return error;
848	}
849	if (xqc->pcounts) {
850		error = xqcheck_compare_dqtype(xqc, XFS_DQTYPE_PROJ);
851		if (!xchk_xref_process_error(sc, 0, 0, &error))
852			return error;
853	}
854
855	/* Check one last time for an incomplete dataset. */
856	if (xchk_iscan_aborted(&xqc->iscan))
857		xchk_set_incomplete(sc);
858
859	return 0;
860}
~/ Read-only file preview.