]> Git Repo - linux.git/blob - fs/xfs/scrub/quotacheck.c
Merge patch series "riscv: Extension parsing fixes"
[linux.git] / fs / xfs / scrub / quotacheck.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 <[email protected]>
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. */
42 struct 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  */
61 struct 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. */
69 static void
70 xqcheck_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. */
80 int
81 xchk_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. */
127 static int
128 xqcheck_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. */
161 static int
162 xqcheck_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
174 static 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. */
184 STATIC struct xqcheck_dqtrx *
185 xqcheck_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  */
206 static int
207 xqcheck_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
302 out_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  */
312 static int
313 xqcheck_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
381 out_abort:
382         xchk_iscan_abort(&xqc->iscan);
383 out_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. */
389 STATIC int
390 xqcheck_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_quota_inode(&tp->t_mountp->m_sb, ip->i_ino)) {
402                 /*
403                  * Quota files are never counted towards quota, so we do not
404                  * need to take the lock.
405                  */
406                 xchk_iscan_mark_visited(&xqc->iscan, ip);
407                 return 0;
408         }
409
410         /* Figure out the data / rt device block counts. */
411         xfs_ilock(ip, XFS_IOLOCK_SHARED);
412         if (isreg)
413                 xfs_ilock(ip, XFS_MMAPLOCK_SHARED);
414         if (XFS_IS_REALTIME_INODE(ip)) {
415                 /*
416                  * Read in the data fork for rt files so that _count_blocks
417                  * can count the number of blocks allocated from the rt volume.
418                  * Inodes do not track that separately.
419                  */
420                 ilock_flags = xfs_ilock_data_map_shared(ip);
421                 error = xfs_iread_extents(tp, ip, XFS_DATA_FORK);
422                 if (error)
423                         goto out_abort;
424         } else {
425                 ilock_flags = XFS_ILOCK_SHARED;
426                 xfs_ilock(ip, XFS_ILOCK_SHARED);
427         }
428         xfs_inode_count_blocks(tp, ip, &nblks, &rtblks);
429
430         if (xchk_iscan_aborted(&xqc->iscan)) {
431                 error = -ECANCELED;
432                 goto out_incomplete;
433         }
434
435         /* Update the shadow dquot counters. */
436         mutex_lock(&xqc->lock);
437         if (xqc->ucounts) {
438                 id = xfs_qm_id_for_quotatype(ip, XFS_DQTYPE_USER);
439                 error = xqcheck_update_incore_counts(xqc, xqc->ucounts, id, 1,
440                                 nblks, rtblks);
441                 if (error)
442                         goto out_mutex;
443         }
444
445         if (xqc->gcounts) {
446                 id = xfs_qm_id_for_quotatype(ip, XFS_DQTYPE_GROUP);
447                 error = xqcheck_update_incore_counts(xqc, xqc->gcounts, id, 1,
448                                 nblks, rtblks);
449                 if (error)
450                         goto out_mutex;
451         }
452
453         if (xqc->pcounts) {
454                 id = xfs_qm_id_for_quotatype(ip, XFS_DQTYPE_PROJ);
455                 error = xqcheck_update_incore_counts(xqc, xqc->pcounts, id, 1,
456                                 nblks, rtblks);
457                 if (error)
458                         goto out_mutex;
459         }
460         mutex_unlock(&xqc->lock);
461
462         xchk_iscan_mark_visited(&xqc->iscan, ip);
463         goto out_ilock;
464
465 out_mutex:
466         mutex_unlock(&xqc->lock);
467 out_abort:
468         xchk_iscan_abort(&xqc->iscan);
469 out_incomplete:
470         xchk_set_incomplete(xqc->sc);
471 out_ilock:
472         xfs_iunlock(ip, ilock_flags);
473         if (isreg)
474                 xfs_iunlock(ip, XFS_MMAPLOCK_SHARED);
475         xfs_iunlock(ip, XFS_IOLOCK_SHARED);
476         return error;
477 }
478
479 /* Walk all the allocated inodes and run a quota scan on them. */
480 STATIC int
481 xqcheck_collect_counts(
482         struct xqcheck          *xqc)
483 {
484         struct xfs_scrub        *sc = xqc->sc;
485         struct xfs_inode        *ip;
486         int                     error;
487
488         /*
489          * Set up for a potentially lengthy filesystem scan by reducing our
490          * transaction resource usage for the duration.  Specifically:
491          *
492          * Cancel the transaction to release the log grant space while we scan
493          * the filesystem.
494          *
495          * Create a new empty transaction to eliminate the possibility of the
496          * inode scan deadlocking on cyclical metadata.
497          *
498          * We pass the empty transaction to the file scanning function to avoid
499          * repeatedly cycling empty transactions.  This can be done without
500          * risk of deadlock between sb_internal and the IOLOCK (we take the
501          * IOLOCK to quiesce the file before scanning) because empty
502          * transactions do not take sb_internal.
503          */
504         xchk_trans_cancel(sc);
505         error = xchk_trans_alloc_empty(sc);
506         if (error)
507                 return error;
508
509         while ((error = xchk_iscan_iter(&xqc->iscan, &ip)) == 1) {
510                 error = xqcheck_collect_inode(xqc, ip);
511                 xchk_irele(sc, ip);
512                 if (error)
513                         break;
514
515                 if (xchk_should_terminate(sc, &error))
516                         break;
517         }
518         xchk_iscan_iter_finish(&xqc->iscan);
519         if (error) {
520                 xchk_set_incomplete(sc);
521                 /*
522                  * If we couldn't grab an inode that was busy with a state
523                  * change, change the error code so that we exit to userspace
524                  * as quickly as possible.
525                  */
526                 if (error == -EBUSY)
527                         return -ECANCELED;
528                 return error;
529         }
530
531         /*
532          * Switch out for a real transaction in preparation for building a new
533          * tree.
534          */
535         xchk_trans_cancel(sc);
536         return xchk_setup_fs(sc);
537 }
538
539 /*
540  * Part 2: Comparing dquot resource counters.  Walk each xfs_dquot, comparing
541  * the resource usage counters against our shadow dquots; and then walk each
542  * shadow dquot (that wasn't covered in the first part), comparing it against
543  * the xfs_dquot.
544  */
545
546 /*
547  * Check the dquot data against what we observed.  Caller must hold the dquot
548  * lock.
549  */
550 STATIC int
551 xqcheck_compare_dquot(
552         struct xqcheck          *xqc,
553         xfs_dqtype_t            dqtype,
554         struct xfs_dquot        *dq)
555 {
556         struct xqcheck_dquot    xcdq;
557         struct xfarray          *counts = xqcheck_counters_for(xqc, dqtype);
558         int                     error;
559
560         if (xchk_iscan_aborted(&xqc->iscan)) {
561                 xchk_set_incomplete(xqc->sc);
562                 return -ECANCELED;
563         }
564
565         mutex_lock(&xqc->lock);
566         error = xfarray_load_sparse(counts, dq->q_id, &xcdq);
567         if (error)
568                 goto out_unlock;
569
570         if (xcdq.icount != dq->q_ino.count)
571                 xchk_qcheck_set_corrupt(xqc->sc, dqtype, dq->q_id);
572
573         if (xcdq.bcount != dq->q_blk.count)
574                 xchk_qcheck_set_corrupt(xqc->sc, dqtype, dq->q_id);
575
576         if (xcdq.rtbcount != dq->q_rtb.count)
577                 xchk_qcheck_set_corrupt(xqc->sc, dqtype, dq->q_id);
578
579         xcdq.flags |= (XQCHECK_DQUOT_COMPARE_SCANNED | XQCHECK_DQUOT_WRITTEN);
580         error = xfarray_store(counts, dq->q_id, &xcdq);
581         if (error == -EFBIG) {
582                 /*
583                  * EFBIG means we tried to store data at too high a byte offset
584                  * in the sparse array.  IOWs, we cannot complete the check and
585                  * must notify userspace that the check was incomplete.  This
586                  * should never happen outside of the collection phase.
587                  */
588                 xchk_set_incomplete(xqc->sc);
589                 error = -ECANCELED;
590         }
591         mutex_unlock(&xqc->lock);
592         if (error)
593                 return error;
594
595         if (xqc->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
596                 return -ECANCELED;
597
598         return 0;
599
600 out_unlock:
601         mutex_unlock(&xqc->lock);
602         return error;
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  */
609 STATIC int
610 xqcheck_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_dqput(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. */
653 STATIC int
654 xqcheck_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_dqput(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. */
688 static void
689 xqcheck_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  */
739 STATIC int
740 xqcheck_setup_scan(
741         struct xfs_scrub        *sc,
742         struct xqcheck          *xqc)
743 {
744         char                    *descr;
745         struct xfs_quotainfo    *qi = sc->mp->m_quotainfo;
746         unsigned long long      max_dquots = XFS_DQ_ID_MAX + 1ULL;
747         int                     error;
748
749         ASSERT(xqc->sc == NULL);
750         xqc->sc = sc;
751
752         mutex_init(&xqc->lock);
753
754         /* Retry iget every tenth of a second for up to 30 seconds. */
755         xchk_iscan_start(sc, 30000, 100, &xqc->iscan);
756
757         error = -ENOMEM;
758         if (xfs_this_quota_on(sc->mp, XFS_DQTYPE_USER)) {
759                 descr = xchk_xfile_descr(sc, "user dquot records");
760                 error = xfarray_create(descr, max_dquots,
761                                 sizeof(struct xqcheck_dquot), &xqc->ucounts);
762                 kfree(descr);
763                 if (error)
764                         goto out_teardown;
765         }
766
767         if (xfs_this_quota_on(sc->mp, XFS_DQTYPE_GROUP)) {
768                 descr = xchk_xfile_descr(sc, "group dquot records");
769                 error = xfarray_create(descr, max_dquots,
770                                 sizeof(struct xqcheck_dquot), &xqc->gcounts);
771                 kfree(descr);
772                 if (error)
773                         goto out_teardown;
774         }
775
776         if (xfs_this_quota_on(sc->mp, XFS_DQTYPE_PROJ)) {
777                 descr = xchk_xfile_descr(sc, "project dquot records");
778                 error = xfarray_create(descr, max_dquots,
779                                 sizeof(struct xqcheck_dquot), &xqc->pcounts);
780                 kfree(descr);
781                 if (error)
782                         goto out_teardown;
783         }
784
785         /*
786          * Set up hash table to map transactions to our internal shadow dqtrx
787          * structures.
788          */
789         error = rhashtable_init(&xqc->shadow_dquot_acct,
790                         &xqcheck_dqacct_hash_params);
791         if (error)
792                 goto out_teardown;
793
794         /*
795          * Hook into the quota code.  The hook only triggers for inodes that
796          * were already scanned, and the scanner thread takes each inode's
797          * ILOCK, which means that any in-progress inode updates will finish
798          * before we can scan the inode.
799          *
800          * The apply hook (which removes the shadow dquot accounting struct)
801          * must be installed before the mod hook so that we never fail to catch
802          * the end of a quota update sequence and leave stale shadow data.
803          */
804         ASSERT(sc->flags & XCHK_FSGATES_QUOTA);
805         xfs_dqtrx_hook_setup(&xqc->qhook, xqcheck_mod_live_ino_dqtrx,
806                         xqcheck_apply_live_dqtrx);
807
808         error = xfs_dqtrx_hook_add(qi, &xqc->qhook);
809         if (error)
810                 goto out_teardown;
811
812         /* Use deferred cleanup to pass the quota count data to repair. */
813         sc->buf_cleanup = xqcheck_teardown_scan;
814         return 0;
815
816 out_teardown:
817         xqcheck_teardown_scan(xqc);
818         return error;
819 }
820
821 /* Scrub all counters for a given quota type. */
822 int
823 xchk_quotacheck(
824         struct xfs_scrub        *sc)
825 {
826         struct xqcheck          *xqc = sc->buf;
827         int                     error = 0;
828
829         /* Check quota counters on the live filesystem. */
830         error = xqcheck_setup_scan(sc, xqc);
831         if (error)
832                 return error;
833
834         /* Walk all inodes, picking up quota information. */
835         error = xqcheck_collect_counts(xqc);
836         if (!xchk_xref_process_error(sc, 0, 0, &error))
837                 return error;
838
839         /* Fail fast if we're not playing with a full dataset. */
840         if (xchk_iscan_aborted(&xqc->iscan))
841                 xchk_set_incomplete(sc);
842         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_INCOMPLETE)
843                 return 0;
844
845         /* Compare quota counters. */
846         if (xqc->ucounts) {
847                 error = xqcheck_compare_dqtype(xqc, XFS_DQTYPE_USER);
848                 if (!xchk_xref_process_error(sc, 0, 0, &error))
849                         return error;
850         }
851         if (xqc->gcounts) {
852                 error = xqcheck_compare_dqtype(xqc, XFS_DQTYPE_GROUP);
853                 if (!xchk_xref_process_error(sc, 0, 0, &error))
854                         return error;
855         }
856         if (xqc->pcounts) {
857                 error = xqcheck_compare_dqtype(xqc, XFS_DQTYPE_PROJ);
858                 if (!xchk_xref_process_error(sc, 0, 0, &error))
859                         return error;
860         }
861
862         /* Check one last time for an incomplete dataset. */
863         if (xchk_iscan_aborted(&xqc->iscan))
864                 xchk_set_incomplete(sc);
865
866         return 0;
867 }
This page took 0.082163 seconds and 4 git commands to generate.