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-xfsa @ Mon Jul 31 20:08:27 PDT 2023 Lines: 312 364 85.7 %
Date: 2023-07-31 20:08:27 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         610 : xqcheck_dqacct_free(
      70             :         void                    *ptr,
      71             :         void                    *arg)
      72             : {
      73     2995464 :         struct xqcheck_dqacct   *dqa = ptr;
      74             : 
      75         610 :         kfree(dqa);
      76     2994854 : }
      77             : 
      78             : /* Set us up to scrub quota counters. */
      79             : int
      80       11570 : xchk_setup_quotacheck(
      81             :         struct xfs_scrub        *sc)
      82             : {
      83       11570 :         if (!XFS_IS_QUOTA_ON(sc->mp))
      84             :                 return -ENOENT;
      85             : 
      86       11554 :         xchk_fsgates_enable(sc, XCHK_FSGATES_QUOTA);
      87             : 
      88       11554 :         sc->buf = kzalloc(sizeof(struct xqcheck), XCHK_GFP_FLAGS);
      89       11554 :         if (!sc->buf)
      90             :                 return -ENOMEM;
      91             : 
      92       11554 :         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   250966805 : 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   250966805 :         struct xqcheck_dquot    xcdq;
     136   250966805 :         int                     error;
     137             : 
     138   250966805 :         error = xfarray_load_sparse(counts, id, &xcdq);
     139   250966805 :         if (error)
     140             :                 return error;
     141             : 
     142   250966805 :         xcdq.flags |= XQCHECK_DQUOT_WRITTEN;
     143   250966805 :         xcdq.icount += inodes;
     144   250966805 :         xcdq.bcount += nblks;
     145   250966805 :         xcdq.rtbcount += rtblks;
     146             : 
     147   250966805 :         error = xfarray_store(counts, id, &xcdq);
     148   250966805 :         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    17098323 : xqcheck_dqacct_obj_cmpfn(
     162             :         struct rhashtable_compare_arg   *arg,
     163             :         const void                      *obj)
     164             : {
     165    17098323 :         const uintptr_t                 *tx_idp = arg->key;
     166    17098323 :         const struct xqcheck_dqacct     *dqa = obj;
     167             : 
     168    17098323 :         if (dqa->tx_id != *tx_idp)
     169      141449 :                 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    19952338 : xqcheck_get_dqtrx(
     185             :         struct xqcheck_dqacct   *dqa,
     186             :         xfs_dqtype_t            q_type,
     187             :         xfs_dqid_t              q_id)
     188             : {
     189    19952338 :         int                     i;
     190             : 
     191    40808489 :         for (i = 0; i < XQCHECK_MAX_NR_DQTRXS; i++) {
     192    40808489 :                 if (dqa->dqtrx[i].q_type == 0 ||
     193    11876722 :                     (dqa->dqtrx[i].q_type == q_type &&
     194    11876722 :                      dqa->dqtrx[i].q_id == q_id))
     195    19952338 :                         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    11897672 : xqcheck_mod_live_ino_dqtrx(
     207             :         struct notifier_block           *nb,
     208             :         unsigned long                   action,
     209             :         void                            *data)
     210             : {
     211    11897672 :         struct xfs_mod_ino_dqtrx_params *p = data;
     212    11897672 :         struct xqcheck                  *xqc;
     213    11897672 :         struct xqcheck_dqacct           *dqa;
     214    11897672 :         struct xqcheck_dqtrx            *dqtrx;
     215    11897672 :         int                             error;
     216             : 
     217    11897672 :         xqc = container_of(nb, struct xqcheck, hooks.mod_hook.nb);
     218             : 
     219             :         /* Skip quota reservation fields. */
     220    11897672 :         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    11874813 :                 break;
     227             :         default:
     228             :                 return NOTIFY_DONE;
     229             :         }
     230             : 
     231             :         /* Ignore dqtrx updates for quota types we don't care about. */
     232    11874813 :         switch (p->q_type) {
     233     4184072 :         case XFS_DQTYPE_USER:
     234     4184072 :                 if (!xqc->ucounts)
     235             :                         return NOTIFY_DONE;
     236             :                 break;
     237     4183793 :         case XFS_DQTYPE_GROUP:
     238     4183793 :                 if (!xqc->gcounts)
     239             :                         return NOTIFY_DONE;
     240             :                 break;
     241     3506948 :         case XFS_DQTYPE_PROJ:
     242     3506948 :                 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    11874813 :         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    10854449 :         mutex_lock(&xqc->lock);
     255    10854569 :         dqa = rhashtable_lookup_fast(&xqc->shadow_dquot_acct, &p->tx_id,
     256             :                         xqcheck_dqacct_hash_params);
     257    10854569 :         if (!dqa) {
     258     2995464 :                 dqa = kzalloc(sizeof(struct xqcheck_dqacct), XCHK_GFP_FLAGS);
     259     2995464 :                 if (!dqa)
     260           0 :                         goto out_abort;
     261             : 
     262     2995464 :                 dqa->tx_id = p->tx_id;
     263     2995464 :                 error = rhashtable_insert_fast(&xqc->shadow_dquot_acct,
     264             :                                 &dqa->hash, xqcheck_dqacct_hash_params);
     265     2995464 :                 if (error)
     266           0 :                         goto out_abort;
     267             :         }
     268             : 
     269             :         /* Find the shadow dqtrx (or an empty slot) here. */
     270    10854569 :         dqtrx = xqcheck_get_dqtrx(dqa, p->q_type, p->q_id);
     271    10854569 :         if (!dqtrx)
     272           0 :                 goto out_abort;
     273    10854569 :         if (dqtrx->q_type == 0) {
     274     9089002 :                 dqtrx->q_type = p->q_type;
     275     9089002 :                 dqtrx->q_id = p->q_id;
     276     9089002 :                 dqa->refcount++;
     277             :         }
     278             : 
     279             :         /* Update counter */
     280    10854569 :         switch (action) {
     281     2545911 :         case XFS_TRANS_DQ_BCOUNT:
     282     2545911 :                 dqtrx->bcount_delta += p->delta;
     283     2545911 :                 break;
     284     1428708 :         case XFS_TRANS_DQ_DELBCOUNT:
     285     1428708 :                 dqtrx->delbcnt_delta += p->delta;
     286     1428708 :                 break;
     287     1907692 :         case XFS_TRANS_DQ_ICOUNT:
     288     1907692 :                 dqtrx->icount_delta += p->delta;
     289     1907692 :                 break;
     290     4901364 :         case XFS_TRANS_DQ_RTBCOUNT:
     291     4901364 :                 dqtrx->rtbcount_delta += p->delta;
     292     4901364 :                 break;
     293       70894 :         case XFS_TRANS_DQ_DELRTBCOUNT:
     294       70894 :                 dqtrx->delrtb_delta += p->delta;
     295       70894 :                 break;
     296             :         }
     297             : 
     298    10854569 :         mutex_unlock(&xqc->lock);
     299    10854569 :         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    60464900 : xqcheck_apply_live_dqtrx(
     313             :         struct notifier_block           *nb,
     314             :         unsigned long                   action,
     315             :         void                            *data)
     316             : {
     317    60464900 :         struct xfs_apply_dqtrx_params   *p = data;
     318    60464900 :         struct xqcheck                  *xqc;
     319    60464900 :         struct xqcheck_dqacct           *dqa;
     320    60464900 :         struct xqcheck_dqtrx            *dqtrx;
     321    60464900 :         struct xfarray                  *counts;
     322    60464900 :         int                             error;
     323             : 
     324    60464900 :         xqc = container_of(nb, struct xqcheck, hooks.apply_hook.nb);
     325             : 
     326             :         /* Map the dquot type to an incore counter object. */
     327    60464900 :         switch (p->q_type) {
     328    20239492 :         case XFS_DQTYPE_USER:
     329    20239492 :                 counts = xqc->ucounts;
     330    20239492 :                 break;
     331    20240041 :         case XFS_DQTYPE_GROUP:
     332    20240041 :                 counts = xqc->gcounts;
     333    20240041 :                 break;
     334    19985367 :         case XFS_DQTYPE_PROJ:
     335    19985367 :                 counts = xqc->pcounts;
     336    19985367 :                 break;
     337             :         default:
     338             :                 return NOTIFY_DONE;
     339             :         }
     340             : 
     341    60464900 :         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    60427231 :         mutex_lock(&xqc->lock);
     349    60431010 :         dqa = rhashtable_lookup_fast(&xqc->shadow_dquot_acct, &p->tx_id,
     350             :                         xqcheck_dqacct_hash_params);
     351    60431010 :         if (!dqa)
     352    51333241 :                 goto out_unlock;
     353     9097769 :         dqtrx = xqcheck_get_dqtrx(dqa, p->q_type, p->q_id);
     354     9097769 :         if (!dqtrx || dqtrx->q_type == 0)
     355       10081 :                 goto out_unlock;
     356             : 
     357             :         /* Update our shadow dquot if we're committing. */
     358     9087688 :         if (action == XFS_APPLY_DQTRX_COMMIT) {
     359     8418512 :                 error = xqcheck_update_incore_counts(xqc, counts, p->q_id,
     360             :                                 dqtrx->icount_delta,
     361     8418512 :                                 dqtrx->bcount_delta + dqtrx->delbcnt_delta,
     362     8418512 :                                 dqtrx->rtbcount_delta + dqtrx->delrtb_delta);
     363     8418512 :                 if (error)
     364           0 :                         goto out_abort;
     365             :         }
     366             : 
     367             :         /* Free the shadow accounting structure if that was the last user. */
     368     9087688 :         dqa->refcount--;
     369     9087688 :         if (dqa->refcount == 0) {
     370     2994854 :                 error = rhashtable_remove_fast(&xqc->shadow_dquot_acct,
     371             :                                 &dqa->hash, xqcheck_dqacct_hash_params);
     372     2994854 :                 if (error)
     373           0 :                         goto out_abort;
     374     2994854 :                 xqcheck_dqacct_free(dqa, NULL);
     375             :         }
     376             : 
     377     9087688 :         mutex_unlock(&xqc->lock);
     378     9087688 :         return NOTIFY_DONE;
     379             : 
     380           0 : out_abort:
     381           0 :         xchk_iscan_abort(&xqc->iscan);
     382    51343322 : out_unlock:
     383    51343322 :         mutex_unlock(&xqc->lock);
     384    51343322 :         return NOTIFY_DONE;
     385             : }
     386             : 
     387             : /* Record this inode's quota usage in our shadow quota counter data. */
     388             : STATIC int
     389    80980449 : xqcheck_collect_inode(
     390             :         struct xqcheck          *xqc,
     391             :         struct xfs_inode        *ip)
     392             : {
     393    80980449 :         struct xfs_trans        *tp = xqc->sc->tp;
     394    80980449 :         xfs_filblks_t           nblks, rtblks;
     395    80980449 :         uint                    ilock_flags = 0;
     396    80980449 :         xfs_dqid_t              id;
     397    80980449 :         bool                    isreg = S_ISREG(VFS_I(ip)->i_mode);
     398    80980449 :         int                     error = 0;
     399             : 
     400   161830430 :         if (xfs_is_metadir_inode(ip) ||
     401    80849981 :             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      130612 :                 xchk_iscan_mark_visited(&xqc->iscan, ip);
     409      130612 :                 return 0;
     410             :         }
     411             : 
     412             :         /* Figure out the data / rt device block counts. */
     413    80849837 :         xfs_ilock(ip, XFS_IOLOCK_SHARED);
     414    80849837 :         if (isreg)
     415    35726343 :                 xfs_ilock(ip, XFS_MMAPLOCK_SHARED);
     416    80849837 :         if (XFS_IS_REALTIME_INODE(ip)) {
     417    12576727 :                 ilock_flags = xfs_ilock_data_map_shared(ip);
     418    12576727 :                 error = xfs_iread_extents(tp, ip, XFS_DATA_FORK);
     419    12576727 :                 if (error)
     420           0 :                         goto out_abort;
     421             :         } else {
     422    68273110 :                 ilock_flags = XFS_ILOCK_SHARED;
     423    68273110 :                 xfs_ilock(ip, XFS_ILOCK_SHARED);
     424             :         }
     425    80849837 :         xfs_inode_count_blocks(tp, ip, &nblks, &rtblks);
     426             : 
     427    80849837 :         if (xchk_iscan_aborted(&xqc->iscan)) {
     428           0 :                 error = -ECANCELED;
     429           0 :                 goto out_incomplete;
     430             :         }
     431             : 
     432             :         /* Update the shadow dquot counters. */
     433    80849837 :         mutex_lock(&xqc->lock);
     434    80849837 :         if (xqc->ucounts) {
     435    80849613 :                 id = xfs_qm_id_for_quotatype(ip, XFS_DQTYPE_USER);
     436    80849613 :                 error = xqcheck_update_incore_counts(xqc, xqc->ucounts, id, 1,
     437             :                                 nblks, rtblks);
     438    80849613 :                 if (error)
     439           0 :                         goto out_mutex;
     440             :         }
     441             : 
     442    80849837 :         if (xqc->gcounts) {
     443    80849125 :                 id = xfs_qm_id_for_quotatype(ip, XFS_DQTYPE_GROUP);
     444    80849125 :                 error = xqcheck_update_incore_counts(xqc, xqc->gcounts, id, 1,
     445             :                                 nblks, rtblks);
     446    80849125 :                 if (error)
     447           0 :                         goto out_mutex;
     448             :         }
     449             : 
     450    80849837 :         if (xqc->pcounts) {
     451    80849555 :                 id = xfs_qm_id_for_quotatype(ip, XFS_DQTYPE_PROJ);
     452    80849555 :                 error = xqcheck_update_incore_counts(xqc, xqc->pcounts, id, 1,
     453             :                                 nblks, rtblks);
     454    80849555 :                 if (error)
     455           0 :                         goto out_mutex;
     456             :         }
     457    80849837 :         mutex_unlock(&xqc->lock);
     458             : 
     459    80849837 :         xchk_iscan_mark_visited(&xqc->iscan, ip);
     460    80849837 :         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    80849837 : out_ilock:
     469    80849837 :         xfs_iunlock(ip, ilock_flags);
     470    80849837 :         if (isreg)
     471    35726343 :                 xfs_iunlock(ip, XFS_MMAPLOCK_SHARED);
     472    80849837 :         xfs_iunlock(ip, XFS_IOLOCK_SHARED);
     473    80849837 :         return error;
     474             : }
     475             : 
     476             : /* Walk all the allocated inodes and run a quota scan on them. */
     477             : STATIC int
     478       11554 : xqcheck_collect_counts(
     479             :         struct xqcheck          *xqc)
     480             : {
     481       11554 :         struct xfs_scrub        *sc = xqc->sc;
     482       11554 :         struct xfs_inode        *ip;
     483       11554 :         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       11554 :         xchk_trans_cancel(sc);
     502       11554 :         error = xchk_trans_alloc_empty(sc);
     503       11554 :         if (error)
     504             :                 return error;
     505             : 
     506    80992002 :         while ((error = xchk_iscan_iter(&xqc->iscan, &ip)) == 1) {
     507    80980449 :                 error = xqcheck_collect_inode(xqc, ip);
     508    80980449 :                 xchk_irele(sc, ip);
     509    80980449 :                 if (error)
     510             :                         break;
     511             : 
     512    80980449 :                 if (xchk_should_terminate(sc, &error))
     513             :                         break;
     514             :         }
     515       11554 :         xchk_iscan_iter_finish(&xqc->iscan);
     516       11554 :         if (error) {
     517           1 :                 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           1 :                 if (error == -EBUSY)
     524             :                         return -ECANCELED;
     525           1 :                 return error;
     526             :         }
     527             : 
     528             :         /*
     529             :          * Switch out for a real transaction in preparation for building a new
     530             :          * tree.
     531             :          */
     532       11553 :         xchk_trans_cancel(sc);
     533       11553 :         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    16738386 : xqcheck_compare_dquot(
     549             :         struct xfs_dquot        *dqp,
     550             :         xfs_dqtype_t            dqtype,
     551             :         void                    *priv)
     552             : {
     553    16738386 :         struct xqcheck_dquot    xcdq;
     554    16738386 :         struct xqcheck          *xqc = priv;
     555    16738386 :         struct xfarray          *counts = xqcheck_counters_for(xqc, dqtype);
     556    16738386 :         int                     error;
     557             : 
     558    16738386 :         if (xchk_iscan_aborted(&xqc->iscan)) {
     559           0 :                 xchk_set_incomplete(xqc->sc);
     560           0 :                 return -ECANCELED;
     561             :         }
     562             : 
     563    16738386 :         mutex_lock(&xqc->lock);
     564    16738386 :         error = xfarray_load_sparse(counts, dqp->q_id, &xcdq);
     565    16738386 :         if (error)
     566           0 :                 goto out_unlock;
     567             : 
     568    16738386 :         if (xcdq.icount != dqp->q_ino.count)
     569           0 :                 xchk_qcheck_set_corrupt(xqc->sc, dqtype, dqp->q_id);
     570             : 
     571    16738386 :         if (xcdq.bcount != dqp->q_blk.count)
     572           0 :                 xchk_qcheck_set_corrupt(xqc->sc, dqtype, dqp->q_id);
     573             : 
     574    16738386 :         if (xcdq.rtbcount != dqp->q_rtb.count)
     575           0 :                 xchk_qcheck_set_corrupt(xqc->sc, dqtype, dqp->q_id);
     576             : 
     577    16738386 :         xcdq.flags |= (XQCHECK_DQUOT_COMPARE_SCANNED | XQCHECK_DQUOT_WRITTEN);
     578    16738386 :         error = xfarray_store(counts, dqp->q_id, &xcdq);
     579    16738386 :         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    16738386 :         mutex_unlock(&xqc->lock);
     590    16738386 :         if (error)
     591             :                 return error;
     592             : 
     593    16738386 :         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       34572 : xqcheck_walk_observations(
     609             :         struct xqcheck          *xqc,
     610             :         xfs_dqtype_t            dqtype)
     611             : {
     612       34572 :         struct xqcheck_dquot    xcdq;
     613       34572 :         struct xfs_dquot        *dqp;
     614       34572 :         struct xfarray          *counts = xqcheck_counters_for(xqc, dqtype);
     615       34572 :         xfarray_idx_t           cur = XFARRAY_CURSOR_INIT;
     616       34572 :         int                     error;
     617             : 
     618       34572 :         mutex_lock(&xqc->lock);
     619    16772953 :         while ((error = xfarray_iter(counts, &cur, &xcdq)) == 1) {
     620    16738386 :                 xfs_dqid_t      id = cur - 1;
     621             : 
     622    16738386 :                 if (xcdq.flags & XQCHECK_DQUOT_COMPARE_SCANNED)
     623       34572 :                         continue;
     624             : 
     625    16703814 :                 mutex_unlock(&xqc->lock);
     626             : 
     627    16703814 :                 error = xfs_qm_dqget(xqc->sc->mp, id, dqtype, false, &dqp);
     628    16703814 :                 if (error == -ENOENT) {
     629           0 :                         xchk_qcheck_set_corrupt(xqc->sc, dqtype, id);
     630           0 :                         return 0;
     631             :                 }
     632    16703814 :                 if (error)
     633           0 :                         return error;
     634             : 
     635    16703814 :                 error = xqcheck_compare_dquot(dqp, dqtype, xqc);
     636    16703814 :                 xfs_qm_dqput(dqp);
     637    16703814 :                 if (error)
     638           0 :                         return error;
     639             : 
     640    16703814 :                 if (xchk_should_terminate(xqc->sc, &error))
     641           5 :                         return error;
     642             : 
     643    16703809 :                 mutex_lock(&xqc->lock);
     644             :         }
     645       34567 :         mutex_unlock(&xqc->lock);
     646             : 
     647       34567 :         return error;
     648             : }
     649             : 
     650             : /* Compare the quota counters we observed against the live dquots. */
     651             : STATIC int
     652       34572 : xqcheck_compare_dqtype(
     653             :         struct xqcheck          *xqc,
     654             :         xfs_dqtype_t            dqtype)
     655             : {
     656       34572 :         struct xfs_scrub        *sc = xqc->sc;
     657       34572 :         int                     error;
     658             : 
     659       34572 :         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       69144 :         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       34572 :         error = xfs_qm_dqiterate(sc->mp, dqtype, xqcheck_compare_dquot, xqc);
     670       34572 :         if (error)
     671             :                 return error;
     672             : 
     673             :         /* Walk all the observed dquots and compare to the incore ones. */
     674       34572 :         return xqcheck_walk_observations(xqc, dqtype);
     675             : }
     676             : 
     677             : /* Tear down everything associated with a quotacheck. */
     678             : static void
     679       11554 : xqcheck_teardown_scan(
     680             :         void                    *priv)
     681             : {
     682       11554 :         struct xqcheck          *xqc = priv;
     683       11554 :         struct xfs_quotainfo    *qi = xqc->sc->mp->m_quotainfo;
     684             : 
     685             :         /* Discourage any hook functions that might be running. */
     686       11554 :         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       11554 :         xfs_dqtrx_hook_del(qi, &xqc->hooks);
     697             : 
     698       11554 :         if (xqc->shadow_dquot_acct.key_len) {
     699       11554 :                 rhashtable_free_and_destroy(&xqc->shadow_dquot_acct,
     700             :                                 xqcheck_dqacct_free, NULL);
     701       11554 :                 xqc->shadow_dquot_acct.key_len = 0;
     702             :         }
     703             : 
     704       11554 :         if (xqc->pcounts) {
     705       11518 :                 xfarray_destroy(xqc->pcounts);
     706       11518 :                 xqc->pcounts = NULL;
     707             :         }
     708             : 
     709       11554 :         if (xqc->gcounts) {
     710       11524 :                 xfarray_destroy(xqc->gcounts);
     711       11524 :                 xqc->gcounts = NULL;
     712             :         }
     713             : 
     714       11554 :         if (xqc->ucounts) {
     715       11542 :                 xfarray_destroy(xqc->ucounts);
     716       11542 :                 xqc->ucounts = NULL;
     717             :         }
     718             : 
     719       11554 :         xchk_iscan_teardown(&xqc->iscan);
     720       11554 :         mutex_destroy(&xqc->lock);
     721       11554 :         xqc->sc = NULL;
     722       11554 : }
     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       11554 : xqcheck_setup_scan(
     731             :         struct xfs_scrub        *sc,
     732             :         struct xqcheck          *xqc)
     733             : {
     734       11554 :         char                    *descr;
     735       11554 :         struct xfs_quotainfo    *qi = sc->mp->m_quotainfo;
     736       11554 :         unsigned long long      max_dquots = ((xfs_dqid_t)-1) + 1;
     737       11554 :         int                     error;
     738             : 
     739       11554 :         ASSERT(xqc->sc == NULL);
     740       11554 :         xqc->sc = sc;
     741             : 
     742       11554 :         mutex_init(&xqc->lock);
     743             : 
     744             :         /* Retry iget every tenth of a second for up to 30 seconds. */
     745       11554 :         xchk_iscan_start(sc, 30000, 100, &xqc->iscan);
     746             : 
     747       11554 :         error = -ENOMEM;
     748       11554 :         if (xfs_this_quota_on(sc->mp, XFS_DQTYPE_USER)) {
     749       11542 :                 descr = xchk_xfile_descr(sc, "user dquot records");
     750       11542 :                 error = xfarray_create(descr, max_dquots,
     751             :                                 sizeof(struct xqcheck_dquot), &xqc->ucounts);
     752       11542 :                 kfree(descr);
     753       11542 :                 if (error)
     754           0 :                         goto out_teardown;
     755             :         }
     756             : 
     757       11554 :         if (xfs_this_quota_on(sc->mp, XFS_DQTYPE_GROUP)) {
     758       11524 :                 descr = xchk_xfile_descr(sc, "group dquot records");
     759       11524 :                 error = xfarray_create(descr, max_dquots,
     760             :                                 sizeof(struct xqcheck_dquot), &xqc->gcounts);
     761       11524 :                 kfree(descr);
     762       11524 :                 if (error)
     763           0 :                         goto out_teardown;
     764             :         }
     765             : 
     766       11554 :         if (xfs_this_quota_on(sc->mp, XFS_DQTYPE_PROJ)) {
     767       11518 :                 descr = xchk_xfile_descr(sc, "project dquot records");
     768       11518 :                 error = xfarray_create(descr, max_dquots,
     769             :                                 sizeof(struct xqcheck_dquot), &xqc->pcounts);
     770       11518 :                 kfree(descr);
     771       11518 :                 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       11554 :         error = rhashtable_init(&xqc->shadow_dquot_acct,
     780             :                         &xqcheck_dqacct_hash_params);
     781       11554 :         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       11554 :         ASSERT(sc->flags & XCHK_FSGATES_QUOTA);
     795       11554 :         xfs_hook_setup(&xqc->hooks.mod_hook, xqcheck_mod_live_ino_dqtrx);
     796       11554 :         xfs_hook_setup(&xqc->hooks.apply_hook, xqcheck_apply_live_dqtrx);
     797             : 
     798       11554 :         error = xfs_dqtrx_hook_add(qi, &xqc->hooks);
     799       11554 :         if (error)
     800           0 :                 goto out_teardown;
     801             : 
     802             :         /* Use deferred cleanup to pass the quota count data to repair. */
     803       11554 :         sc->buf_cleanup = xqcheck_teardown_scan;
     804       11554 :         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       11554 : xchk_quotacheck(
     814             :         struct xfs_scrub        *sc)
     815             : {
     816       11554 :         struct xqcheck          *xqc = sc->buf;
     817       11554 :         int                     error = 0;
     818             : 
     819             :         /* Check quota counters on the live filesystem. */
     820       11554 :         error = xqcheck_setup_scan(sc, xqc);
     821       11554 :         if (error)
     822             :                 return error;
     823             : 
     824             :         /* Walk all inodes, picking up quota information. */
     825       11554 :         error = xqcheck_collect_counts(xqc);
     826       11554 :         if (!xchk_xref_process_error(sc, 0, 0, &error))
     827           1 :                 return error;
     828             : 
     829             :         /* Fail fast if we're not playing with a full dataset. */
     830       11553 :         if (xchk_iscan_aborted(&xqc->iscan))
     831           0 :                 xchk_set_incomplete(sc);
     832       11553 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_INCOMPLETE)
     833             :                 return 0;
     834             : 
     835             :         /* Compare quota counters. */
     836       11553 :         if (xqc->ucounts) {
     837       11541 :                 error = xqcheck_compare_dqtype(xqc, XFS_DQTYPE_USER);
     838       11541 :                 if (!xchk_xref_process_error(sc, 0, 0, &error))
     839           4 :                         return error;
     840             :         }
     841       11549 :         if (xqc->gcounts) {
     842       11519 :                 error = xqcheck_compare_dqtype(xqc, XFS_DQTYPE_GROUP);
     843       11519 :                 if (!xchk_xref_process_error(sc, 0, 0, &error))
     844           1 :                         return error;
     845             :         }
     846       11548 :         if (xqc->pcounts) {
     847       11512 :                 error = xqcheck_compare_dqtype(xqc, XFS_DQTYPE_PROJ);
     848       11512 :                 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       11548 :         if (xchk_iscan_aborted(&xqc->iscan))
     854           0 :                 xchk_set_incomplete(sc);
     855             : 
     856             :         return 0;
     857             : }

Generated by: LCOV version 1.14