LCOV - code coverage report
Current view: top level - fs/xfs/scrub - quotacheck.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc4-xfsx @ Mon Jul 31 20:08:34 PDT 2023 Lines: 312 364 85.7 %
Date: 2023-07-31 20:08:34 Functions: 15 15 100.0 %

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

Generated by: LCOV version 1.14