LCOV - code coverage report
Current view: top level - fs/xfs/scrub - quotacheck.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc3-achx @ Mon Jul 31 20:08:12 PDT 2023 Lines: 297 363 81.8 %
Date: 2023-07-31 20:08:12 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        1214 : xqcheck_dqacct_free(
      70             :         void                    *ptr,
      71             :         void                    *arg)
      72             : {
      73     2374643 :         struct xqcheck_dqacct   *dqa = ptr;
      74             : 
      75        1214 :         kfree(dqa);
      76     2373429 : }
      77             : 
      78             : /* Set us up to scrub quota counters. */
      79             : int
      80       27308 : xchk_setup_quotacheck(
      81             :         struct xfs_scrub        *sc)
      82             : {
      83       27308 :         if (!XFS_IS_QUOTA_ON(sc->mp))
      84             :                 return -ENOENT;
      85             : 
      86       18677 :         xchk_fsgates_enable(sc, XCHK_FSGATES_QUOTA);
      87             : 
      88       18677 :         sc->buf = kzalloc(sizeof(struct xqcheck), XCHK_GFP_FLAGS);
      89       18677 :         if (!sc->buf)
      90             :                 return -ENOMEM;
      91             : 
      92       18677 :         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   694947191 : 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   694947191 :         struct xqcheck_dquot    xcdq;
     136   694947191 :         int                     error;
     137             : 
     138   694947191 :         error = xfarray_load_sparse(counts, id, &xcdq);
     139   694947191 :         if (error)
     140             :                 return error;
     141             : 
     142   694947191 :         xcdq.flags |= XQCHECK_DQUOT_WRITTEN;
     143   694947191 :         xcdq.icount += inodes;
     144   694947191 :         xcdq.bcount += nblks;
     145   694947191 :         xcdq.rtbcount += rtblks;
     146             : 
     147   694947191 :         error = xfarray_store(counts, id, &xcdq);
     148   694947191 :         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    13093331 : xqcheck_dqacct_obj_cmpfn(
     162             :         struct rhashtable_compare_arg   *arg,
     163             :         const void                      *obj)
     164             : {
     165    13093331 :         const uintptr_t                 *tx_idp = arg->key;
     166    13093331 :         const struct xqcheck_dqacct     *dqa = obj;
     167             : 
     168    13093331 :         if (dqa->tx_id != *tx_idp)
     169      123340 :                 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    15344634 : xqcheck_get_dqtrx(
     185             :         struct xqcheck_dqacct   *dqa,
     186             :         xfs_dqtype_t            q_type,
     187             :         xfs_dqid_t              q_id)
     188             : {
     189    15344634 :         int                     i;
     190             : 
     191    31194460 :         for (i = 0; i < XQCHECK_MAX_NR_DQTRXS; i++) {
     192    55182040 :                 if (dqa->dqtrx[i].q_type == 0 ||
     193    23987580 :                     (dqa->dqtrx[i].q_type == q_type &&
     194     8700566 :                      dqa->dqtrx[i].q_id == q_id))
     195    15344634 :                         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    10591343 : xqcheck_mod_live_ino_dqtrx(
     207             :         struct notifier_block           *nb,
     208             :         unsigned long                   action,
     209             :         void                            *data)
     210             : {
     211    10591343 :         struct xfs_mod_ino_dqtrx_params *p = data;
     212    10591343 :         struct xqcheck                  *xqc;
     213    10591343 :         struct xqcheck_dqacct           *dqa;
     214    10591343 :         struct xqcheck_dqtrx            *dqtrx;
     215    10591343 :         int                             error;
     216             : 
     217    10591343 :         xqc = container_of(nb, struct xqcheck, hooks.mod_hook.nb);
     218             : 
     219             :         /* Skip quota reservation fields. */
     220    10591343 :         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    10591376 :                 break;
     227             :         default:
     228             :                 return NOTIFY_DONE;
     229             :         }
     230             : 
     231             :         /* Ignore dqtrx updates for quota types we don't care about. */
     232    10591376 :         switch (p->q_type) {
     233     3660527 :         case XFS_DQTYPE_USER:
     234     3660527 :                 if (!xqc->ucounts)
     235             :                         return NOTIFY_DONE;
     236             :                 break;
     237     3660772 :         case XFS_DQTYPE_GROUP:
     238     3660772 :                 if (!xqc->gcounts)
     239             :                         return NOTIFY_DONE;
     240             :                 break;
     241     3270077 :         case XFS_DQTYPE_PROJ:
     242     3270077 :                 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    10591376 :         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     8140615 :         mutex_lock(&xqc->lock);
     255     8140693 :         dqa = rhashtable_lookup_fast(&xqc->shadow_dquot_acct, &p->tx_id,
     256             :                         xqcheck_dqacct_hash_params);
     257     8140693 :         if (!dqa) {
     258     2374643 :                 dqa = kzalloc(sizeof(struct xqcheck_dqacct), XCHK_GFP_FLAGS);
     259     2374643 :                 if (!dqa)
     260           0 :                         goto out_abort;
     261             : 
     262     2374643 :                 dqa->tx_id = p->tx_id;
     263     2374643 :                 error = rhashtable_insert_fast(&xqc->shadow_dquot_acct,
     264             :                                 &dqa->hash, xqcheck_dqacct_hash_params);
     265     2374643 :                 if (error)
     266           0 :                         goto out_abort;
     267             :         }
     268             : 
     269             :         /* Find the shadow dqtrx (or an empty slot) here. */
     270     8140693 :         dqtrx = xqcheck_get_dqtrx(dqa, p->q_type, p->q_id);
     271     8140693 :         if (!dqtrx)
     272           0 :                 goto out_abort;
     273     8140693 :         if (dqtrx->q_type == 0) {
     274     7198858 :                 dqtrx->q_type = p->q_type;
     275     7198858 :                 dqtrx->q_id = p->q_id;
     276     7198858 :                 dqa->refcount++;
     277             :         }
     278             : 
     279             :         /* Update counter */
     280     8140693 :         switch (action) {
     281     5177251 :         case XFS_TRANS_DQ_BCOUNT:
     282     5177251 :                 dqtrx->bcount_delta += p->delta;
     283     5177251 :                 break;
     284     1581745 :         case XFS_TRANS_DQ_DELBCOUNT:
     285     1581745 :                 dqtrx->delbcnt_delta += p->delta;
     286     1581745 :                 break;
     287     1381697 :         case XFS_TRANS_DQ_ICOUNT:
     288     1381697 :                 dqtrx->icount_delta += p->delta;
     289     1381697 :                 break;
     290           0 :         case XFS_TRANS_DQ_RTBCOUNT:
     291           0 :                 dqtrx->rtbcount_delta += p->delta;
     292           0 :                 break;
     293           0 :         case XFS_TRANS_DQ_DELRTBCOUNT:
     294           0 :                 dqtrx->delrtb_delta += p->delta;
     295           0 :                 break;
     296             :         }
     297             : 
     298     8140693 :         mutex_unlock(&xqc->lock);
     299     8140693 :         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    52823226 : xqcheck_apply_live_dqtrx(
     313             :         struct notifier_block           *nb,
     314             :         unsigned long                   action,
     315             :         void                            *data)
     316             : {
     317    52823226 :         struct xfs_apply_dqtrx_params   *p = data;
     318    52823226 :         struct xqcheck                  *xqc;
     319    52823226 :         struct xqcheck_dqacct           *dqa;
     320    52823226 :         struct xqcheck_dqtrx            *dqtrx;
     321    52823226 :         struct xfarray                  *counts;
     322    52823226 :         int                             error;
     323             : 
     324    52823226 :         xqc = container_of(nb, struct xqcheck, hooks.apply_hook.nb);
     325             : 
     326             :         /* Map the dquot type to an incore counter object. */
     327    52823226 :         switch (p->q_type) {
     328    17684485 :         case XFS_DQTYPE_USER:
     329    17684485 :                 counts = xqc->ucounts;
     330    17684485 :                 break;
     331    17680428 :         case XFS_DQTYPE_GROUP:
     332    17680428 :                 counts = xqc->gcounts;
     333    17680428 :                 break;
     334    17458313 :         case XFS_DQTYPE_PROJ:
     335    17458313 :                 counts = xqc->pcounts;
     336    17458313 :                 break;
     337             :         default:
     338             :                 return NOTIFY_DONE;
     339             :         }
     340             : 
     341    52823226 :         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    52783551 :         mutex_lock(&xqc->lock);
     349    52813144 :         dqa = rhashtable_lookup_fast(&xqc->shadow_dquot_acct, &p->tx_id,
     350             :                         xqcheck_dqacct_hash_params);
     351    52813144 :         if (!dqa)
     352    45609203 :                 goto out_unlock;
     353     7203941 :         dqtrx = xqcheck_get_dqtrx(dqa, p->q_type, p->q_id);
     354     7203941 :         if (!dqtrx || dqtrx->q_type == 0)
     355        8022 :                 goto out_unlock;
     356             : 
     357             :         /* Update our shadow dquot if we're committing. */
     358     7195919 :         if (action == XFS_APPLY_DQTRX_COMMIT) {
     359     6212281 :                 error = xqcheck_update_incore_counts(xqc, counts, p->q_id,
     360             :                                 dqtrx->icount_delta,
     361     6212281 :                                 dqtrx->bcount_delta + dqtrx->delbcnt_delta,
     362     6212281 :                                 dqtrx->rtbcount_delta + dqtrx->delrtb_delta);
     363     6212281 :                 if (error)
     364           0 :                         goto out_abort;
     365             :         }
     366             : 
     367             :         /* Free the shadow accounting structure if that was the last user. */
     368     7195919 :         dqa->refcount--;
     369     7195919 :         if (dqa->refcount == 0) {
     370     2373429 :                 error = rhashtable_remove_fast(&xqc->shadow_dquot_acct,
     371             :                                 &dqa->hash, xqcheck_dqacct_hash_params);
     372     2373429 :                 if (error)
     373           0 :                         goto out_abort;
     374     2373429 :                 xqcheck_dqacct_free(dqa, NULL);
     375             :         }
     376             : 
     377     7195919 :         mutex_unlock(&xqc->lock);
     378     7195919 :         return NOTIFY_DONE;
     379             : 
     380           0 : out_abort:
     381           0 :         xchk_iscan_abort(&xqc->iscan);
     382    45617225 : out_unlock:
     383    45617225 :         mutex_unlock(&xqc->lock);
     384    45617225 :         return NOTIFY_DONE;
     385             : }
     386             : 
     387             : /* Record this inode's quota usage in our shadow quota counter data. */
     388             : STATIC int
     389   229635369 : xqcheck_collect_inode(
     390             :         struct xqcheck          *xqc,
     391             :         struct xfs_inode        *ip)
     392             : {
     393   229635369 :         struct xfs_trans        *tp = xqc->sc->tp;
     394   229635369 :         xfs_filblks_t           nblks, rtblks;
     395   229635369 :         uint                    ilock_flags = 0;
     396   229635369 :         xfs_dqid_t              id;
     397   229635369 :         bool                    isreg = S_ISREG(VFS_I(ip)->i_mode);
     398   229635369 :         int                     error = 0;
     399             : 
     400   459252105 :         if (xfs_is_quota_inode(&tp->t_mountp->m_sb, ip->i_ino)) {
     401             :                 /*
     402             :                  * Quota files are never counted towards quota, so we do not
     403             :                  * need to take the lock.
     404             :                  */
     405       55767 :                 xchk_iscan_mark_visited(&xqc->iscan, ip);
     406       55767 :                 return 0;
     407             :         }
     408             : 
     409             :         /* Figure out the data / rt device block counts. */
     410   229579602 :         xfs_ilock(ip, XFS_IOLOCK_SHARED);
     411   229579602 :         if (isreg)
     412   101325633 :                 xfs_ilock(ip, XFS_MMAPLOCK_SHARED);
     413   229579602 :         if (XFS_IS_REALTIME_INODE(ip)) {
     414           0 :                 ilock_flags = xfs_ilock_data_map_shared(ip);
     415           0 :                 error = xfs_iread_extents(tp, ip, XFS_DATA_FORK);
     416           0 :                 if (error)
     417           0 :                         goto out_abort;
     418             :         } else {
     419   229579602 :                 ilock_flags = XFS_ILOCK_SHARED;
     420   229579602 :                 xfs_ilock(ip, XFS_ILOCK_SHARED);
     421             :         }
     422   229579602 :         xfs_inode_count_blocks(tp, ip, &nblks, &rtblks);
     423             : 
     424   229579602 :         if (xchk_iscan_aborted(&xqc->iscan)) {
     425           0 :                 error = -ECANCELED;
     426           0 :                 goto out_incomplete;
     427             :         }
     428             : 
     429             :         /* Update the shadow dquot counters. */
     430   229579602 :         mutex_lock(&xqc->lock);
     431   229579602 :         if (xqc->ucounts) {
     432   229578862 :                 id = xfs_qm_id_for_quotatype(ip, XFS_DQTYPE_USER);
     433   229578862 :                 error = xqcheck_update_incore_counts(xqc, xqc->ucounts, id, 1,
     434             :                                 nblks, rtblks);
     435   229578862 :                 if (error)
     436           0 :                         goto out_mutex;
     437             :         }
     438             : 
     439   229579602 :         if (xqc->gcounts) {
     440   229577574 :                 id = xfs_qm_id_for_quotatype(ip, XFS_DQTYPE_GROUP);
     441   229577574 :                 error = xqcheck_update_incore_counts(xqc, xqc->gcounts, id, 1,
     442             :                                 nblks, rtblks);
     443   229577574 :                 if (error)
     444           0 :                         goto out_mutex;
     445             :         }
     446             : 
     447   229579602 :         if (xqc->pcounts) {
     448   229578474 :                 id = xfs_qm_id_for_quotatype(ip, XFS_DQTYPE_PROJ);
     449   229578474 :                 error = xqcheck_update_incore_counts(xqc, xqc->pcounts, id, 1,
     450             :                                 nblks, rtblks);
     451   229578474 :                 if (error)
     452           0 :                         goto out_mutex;
     453             :         }
     454   229579602 :         mutex_unlock(&xqc->lock);
     455             : 
     456   229579602 :         xchk_iscan_mark_visited(&xqc->iscan, ip);
     457   229579602 :         goto out_ilock;
     458             : 
     459           0 : out_mutex:
     460           0 :         mutex_unlock(&xqc->lock);
     461           0 : out_abort:
     462           0 :         xchk_iscan_abort(&xqc->iscan);
     463           0 : out_incomplete:
     464           0 :         xchk_set_incomplete(xqc->sc);
     465   229579602 : out_ilock:
     466   229579602 :         xfs_iunlock(ip, ilock_flags);
     467   229579602 :         if (isreg)
     468   101325633 :                 xfs_iunlock(ip, XFS_MMAPLOCK_SHARED);
     469   229579602 :         xfs_iunlock(ip, XFS_IOLOCK_SHARED);
     470   229579602 :         return error;
     471             : }
     472             : 
     473             : /* Walk all the allocated inodes and run a quota scan on them. */
     474             : STATIC int
     475       18662 : xqcheck_collect_counts(
     476             :         struct xqcheck          *xqc)
     477             : {
     478       18662 :         struct xfs_scrub        *sc = xqc->sc;
     479       18662 :         struct xfs_inode        *ip;
     480       18662 :         int                     error;
     481             : 
     482             :         /*
     483             :          * Set up for a potentially lengthy filesystem scan by reducing our
     484             :          * transaction resource usage for the duration.  Specifically:
     485             :          *
     486             :          * Cancel the transaction to release the log grant space while we scan
     487             :          * the filesystem.
     488             :          *
     489             :          * Create a new empty transaction to eliminate the possibility of the
     490             :          * inode scan deadlocking on cyclical metadata.
     491             :          *
     492             :          * We pass the empty transaction to the file scanning function to avoid
     493             :          * repeatedly cycling empty transactions.  This can be done without
     494             :          * risk of deadlock between sb_internal and the IOLOCK (we take the
     495             :          * IOLOCK to quiesce the file before scanning) because empty
     496             :          * transactions do not take sb_internal.
     497             :          */
     498       18662 :         xchk_trans_cancel(sc);
     499       18662 :         error = xchk_trans_alloc_empty(sc);
     500       18662 :         if (error)
     501             :                 return error;
     502             : 
     503   229654031 :         while ((error = xchk_iscan_iter(&xqc->iscan, &ip)) == 1) {
     504   229635369 :                 error = xqcheck_collect_inode(xqc, ip);
     505   229635369 :                 xchk_irele(sc, ip);
     506   229635369 :                 if (error)
     507             :                         break;
     508             : 
     509   229635369 :                 if (xchk_should_terminate(sc, &error))
     510             :                         break;
     511             :         }
     512       18662 :         xchk_iscan_iter_finish(&xqc->iscan);
     513       18662 :         if (error) {
     514           0 :                 xchk_set_incomplete(sc);
     515             :                 /*
     516             :                  * If we couldn't grab an inode that was busy with a state
     517             :                  * change, change the error code so that we exit to userspace
     518             :                  * as quickly as possible.
     519             :                  */
     520           0 :                 if (error == -EBUSY)
     521             :                         return -ECANCELED;
     522           0 :                 return error;
     523             :         }
     524             : 
     525             :         /*
     526             :          * Switch out for a real transaction in preparation for building a new
     527             :          * tree.
     528             :          */
     529       18662 :         xchk_trans_cancel(sc);
     530       18662 :         return xchk_setup_fs(sc);
     531             : }
     532             : 
     533             : /*
     534             :  * Part 2: Comparing dquot resource counters.  Walk each xfs_dquot, comparing
     535             :  * the resource usage counters against our shadow dquots; and then walk each
     536             :  * shadow dquot (that wasn't covered in the first part), comparing it against
     537             :  * the xfs_dquot.
     538             :  */
     539             : 
     540             : /*
     541             :  * Check the dquot data against what we observed.  Caller must hold the dquot
     542             :  * lock.
     543             :  */
     544             : STATIC int
     545    56019437 : xqcheck_compare_dquot(
     546             :         struct xfs_dquot        *dqp,
     547             :         xfs_dqtype_t            dqtype,
     548             :         void                    *priv)
     549             : {
     550    56019437 :         struct xqcheck_dquot    xcdq;
     551    56019437 :         struct xqcheck          *xqc = priv;
     552    56019437 :         struct xfarray          *counts = xqcheck_counters_for(xqc, dqtype);
     553    56019437 :         int                     error;
     554             : 
     555    56019437 :         if (xchk_iscan_aborted(&xqc->iscan)) {
     556           0 :                 xchk_set_incomplete(xqc->sc);
     557           0 :                 return -ECANCELED;
     558             :         }
     559             : 
     560    56019437 :         mutex_lock(&xqc->lock);
     561    56019437 :         error = xfarray_load_sparse(counts, dqp->q_id, &xcdq);
     562    56019437 :         if (error)
     563           0 :                 goto out_unlock;
     564             : 
     565    56019437 :         if (xcdq.icount != dqp->q_ino.count)
     566           0 :                 xchk_qcheck_set_corrupt(xqc->sc, dqtype, dqp->q_id);
     567             : 
     568    56019437 :         if (xcdq.bcount != dqp->q_blk.count)
     569           0 :                 xchk_qcheck_set_corrupt(xqc->sc, dqtype, dqp->q_id);
     570             : 
     571    56019437 :         if (xcdq.rtbcount != dqp->q_rtb.count)
     572           0 :                 xchk_qcheck_set_corrupt(xqc->sc, dqtype, dqp->q_id);
     573             : 
     574    56019437 :         xcdq.flags |= (XQCHECK_DQUOT_COMPARE_SCANNED | XQCHECK_DQUOT_WRITTEN);
     575    56019437 :         error = xfarray_store(counts, dqp->q_id, &xcdq);
     576    56019437 :         if (error == -EFBIG) {
     577             :                 /*
     578             :                  * EFBIG means we tried to store data at too high a byte offset
     579             :                  * in the sparse array.  IOWs, we cannot complete the check and
     580             :                  * must notify userspace that the check was incomplete.  This
     581             :                  * should never happen outside of the collection phase.
     582             :                  */
     583           0 :                 xchk_set_incomplete(xqc->sc);
     584           0 :                 error = -ECANCELED;
     585             :         }
     586    56019437 :         mutex_unlock(&xqc->lock);
     587    56019437 :         if (error)
     588             :                 return error;
     589             : 
     590    56019437 :         if (xqc->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     591           0 :                 return -ECANCELED;
     592             : 
     593             :         return 0;
     594             : 
     595             : out_unlock:
     596           0 :         mutex_unlock(&xqc->lock);
     597           0 :         return error;
     598             : }
     599             : 
     600             : /*
     601             :  * Walk all the observed dquots, and make sure there's a matching incore
     602             :  * dquot and that its counts match ours.
     603             :  */
     604             : STATIC int
     605       55747 : xqcheck_walk_observations(
     606             :         struct xqcheck          *xqc,
     607             :         xfs_dqtype_t            dqtype)
     608             : {
     609       55747 :         struct xqcheck_dquot    xcdq;
     610       55747 :         struct xfs_dquot        *dqp;
     611       55747 :         struct xfarray          *counts = xqcheck_counters_for(xqc, dqtype);
     612       55747 :         xfarray_idx_t           cur = XFARRAY_CURSOR_INIT;
     613       55747 :         int                     error;
     614             : 
     615       55747 :         mutex_lock(&xqc->lock);
     616    56075182 :         while ((error = xfarray_iter(counts, &cur, &xcdq)) == 1) {
     617    56019437 :                 xfs_dqid_t      id = cur - 1;
     618             : 
     619    56019437 :                 if (xcdq.flags & XQCHECK_DQUOT_COMPARE_SCANNED)
     620       55747 :                         continue;
     621             : 
     622    55963690 :                 mutex_unlock(&xqc->lock);
     623             : 
     624    55963690 :                 error = xfs_qm_dqget(xqc->sc->mp, id, dqtype, false, &dqp);
     625    55963690 :                 if (error == -ENOENT) {
     626           0 :                         xchk_qcheck_set_corrupt(xqc->sc, dqtype, id);
     627           0 :                         return 0;
     628             :                 }
     629    55963690 :                 if (error)
     630           0 :                         return error;
     631             : 
     632    55963690 :                 error = xqcheck_compare_dquot(dqp, dqtype, xqc);
     633    55963690 :                 xfs_qm_dqput(dqp);
     634    55963690 :                 if (error)
     635           0 :                         return error;
     636             : 
     637    55963690 :                 if (xchk_should_terminate(xqc->sc, &error))
     638           2 :                         return error;
     639             : 
     640    55963688 :                 mutex_lock(&xqc->lock);
     641             :         }
     642       55745 :         mutex_unlock(&xqc->lock);
     643             : 
     644       55745 :         return error;
     645             : }
     646             : 
     647             : /* Compare the quota counters we observed against the live dquots. */
     648             : STATIC int
     649       55747 : xqcheck_compare_dqtype(
     650             :         struct xqcheck          *xqc,
     651             :         xfs_dqtype_t            dqtype)
     652             : {
     653       55747 :         struct xfs_scrub        *sc = xqc->sc;
     654       55747 :         int                     error;
     655             : 
     656       55747 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     657             :                 return 0;
     658             : 
     659             :         /* If the quota CHKD flag is cleared, we need to repair this quota. */
     660      111494 :         if (!(xfs_quota_chkd_flag(dqtype) & sc->mp->m_qflags)) {
     661           0 :                 xchk_qcheck_set_corrupt(xqc->sc, dqtype, 0);
     662           0 :                 return 0;
     663             :         }
     664             : 
     665             :         /* Compare what we observed against the actual dquots. */
     666       55747 :         error = xfs_qm_dqiterate(sc->mp, dqtype, xqcheck_compare_dquot, xqc);
     667       55747 :         if (error)
     668             :                 return error;
     669             : 
     670             :         /* Walk all the observed dquots and compare to the incore ones. */
     671       55747 :         return xqcheck_walk_observations(xqc, dqtype);
     672             : }
     673             : 
     674             : /* Tear down everything associated with a quotacheck. */
     675             : static void
     676       18662 : xqcheck_teardown_scan(
     677             :         void                    *priv)
     678             : {
     679       18662 :         struct xqcheck          *xqc = priv;
     680       18662 :         struct xfs_quotainfo    *qi = xqc->sc->mp->m_quotainfo;
     681             : 
     682             :         /* Discourage any hook functions that might be running. */
     683       18662 :         xchk_iscan_abort(&xqc->iscan);
     684             : 
     685             :         /*
     686             :          * As noted above, the apply hook is responsible for cleaning up the
     687             :          * shadow dquot accounting data when a transaction completes.  The mod
     688             :          * hook must be removed before the apply hook so that we don't
     689             :          * mistakenly leave an active shadow account for the mod hook to get
     690             :          * its hands on.  No hooks should be running after these functions
     691             :          * return.
     692             :          */
     693       18662 :         xfs_dqtrx_hook_del(qi, &xqc->hooks);
     694             : 
     695       18662 :         if (xqc->shadow_dquot_acct.key_len) {
     696       18662 :                 rhashtable_free_and_destroy(&xqc->shadow_dquot_acct,
     697             :                                 xqcheck_dqacct_free, NULL);
     698       18662 :                 xqc->shadow_dquot_acct.key_len = 0;
     699             :         }
     700             : 
     701       18662 :         if (xqc->pcounts) {
     702       18545 :                 xfarray_destroy(xqc->pcounts);
     703       18545 :                 xqc->pcounts = NULL;
     704             :         }
     705             : 
     706       18662 :         if (xqc->gcounts) {
     707       18577 :                 xfarray_destroy(xqc->gcounts);
     708       18577 :                 xqc->gcounts = NULL;
     709             :         }
     710             : 
     711       18662 :         if (xqc->ucounts) {
     712       18627 :                 xfarray_destroy(xqc->ucounts);
     713       18627 :                 xqc->ucounts = NULL;
     714             :         }
     715             : 
     716       18662 :         xchk_iscan_teardown(&xqc->iscan);
     717       18662 :         mutex_destroy(&xqc->lock);
     718       18662 :         xqc->sc = NULL;
     719       18662 : }
     720             : 
     721             : /*
     722             :  * Scan all inodes in the entire filesystem to generate quota counter data.
     723             :  * If the scan is successful, the quota data will be left alive for a repair.
     724             :  * If any error occurs, we'll tear everything down.
     725             :  */
     726             : STATIC int
     727       18662 : xqcheck_setup_scan(
     728             :         struct xfs_scrub        *sc,
     729             :         struct xqcheck          *xqc)
     730             : {
     731       18662 :         char                    *descr;
     732       18662 :         struct xfs_quotainfo    *qi = sc->mp->m_quotainfo;
     733       18662 :         unsigned long long      max_dquots = ((xfs_dqid_t)-1) + 1;
     734       18662 :         int                     error;
     735             : 
     736       18662 :         ASSERT(xqc->sc == NULL);
     737       18662 :         xqc->sc = sc;
     738             : 
     739       18662 :         mutex_init(&xqc->lock);
     740             : 
     741             :         /* Retry iget every tenth of a second for up to 30 seconds. */
     742       18662 :         xchk_iscan_start(sc, 30000, 100, &xqc->iscan);
     743             : 
     744       18662 :         error = -ENOMEM;
     745       18662 :         if (xfs_this_quota_on(sc->mp, XFS_DQTYPE_USER)) {
     746       18627 :                 descr = xchk_xfile_descr(sc, "user dquot records");
     747       18627 :                 error = xfarray_create(descr, max_dquots,
     748             :                                 sizeof(struct xqcheck_dquot), &xqc->ucounts);
     749       18627 :                 kfree(descr);
     750       18627 :                 if (error)
     751           0 :                         goto out_teardown;
     752             :         }
     753             : 
     754       18662 :         if (xfs_this_quota_on(sc->mp, XFS_DQTYPE_GROUP)) {
     755       18577 :                 descr = xchk_xfile_descr(sc, "group dquot records");
     756       18577 :                 error = xfarray_create(descr, max_dquots,
     757             :                                 sizeof(struct xqcheck_dquot), &xqc->gcounts);
     758       18577 :                 kfree(descr);
     759       18577 :                 if (error)
     760           0 :                         goto out_teardown;
     761             :         }
     762             : 
     763       18662 :         if (xfs_this_quota_on(sc->mp, XFS_DQTYPE_PROJ)) {
     764       18545 :                 descr = xchk_xfile_descr(sc, "project dquot records");
     765       18545 :                 error = xfarray_create(descr, max_dquots,
     766             :                                 sizeof(struct xqcheck_dquot), &xqc->pcounts);
     767       18545 :                 kfree(descr);
     768       18545 :                 if (error)
     769           0 :                         goto out_teardown;
     770             :         }
     771             : 
     772             :         /*
     773             :          * Set up hash table to map transactions to our internal shadow dqtrx
     774             :          * structures.
     775             :          */
     776       18662 :         error = rhashtable_init(&xqc->shadow_dquot_acct,
     777             :                         &xqcheck_dqacct_hash_params);
     778       18662 :         if (error)
     779           0 :                 goto out_teardown;
     780             : 
     781             :         /*
     782             :          * Hook into the quota code.  The hook only triggers for inodes that
     783             :          * were already scanned, and the scanner thread takes each inode's
     784             :          * ILOCK, which means that any in-progress inode updates will finish
     785             :          * before we can scan the inode.
     786             :          *
     787             :          * The apply hook (which removes the shadow dquot accounting struct)
     788             :          * must be installed before the mod hook so that we never fail to catch
     789             :          * the end of a quota update sequence and leave stale shadow data.
     790             :          */
     791       18662 :         ASSERT(sc->flags & XCHK_FSGATES_QUOTA);
     792       18662 :         xfs_hook_setup(&xqc->hooks.mod_hook, xqcheck_mod_live_ino_dqtrx);
     793       18662 :         xfs_hook_setup(&xqc->hooks.apply_hook, xqcheck_apply_live_dqtrx);
     794             : 
     795       18662 :         error = xfs_dqtrx_hook_add(qi, &xqc->hooks);
     796       18662 :         if (error)
     797           0 :                 goto out_teardown;
     798             : 
     799             :         /* Use deferred cleanup to pass the quota count data to repair. */
     800       18662 :         sc->buf_cleanup = xqcheck_teardown_scan;
     801       18662 :         return 0;
     802             : 
     803           0 : out_teardown:
     804           0 :         xqcheck_teardown_scan(xqc);
     805           0 :         return error;
     806             : }
     807             : 
     808             : /* Scrub all counters for a given quota type. */
     809             : int
     810       18662 : xchk_quotacheck(
     811             :         struct xfs_scrub        *sc)
     812             : {
     813       18662 :         struct xqcheck          *xqc = sc->buf;
     814       18662 :         int                     error = 0;
     815             : 
     816             :         /* Check quota counters on the live filesystem. */
     817       18662 :         error = xqcheck_setup_scan(sc, xqc);
     818       18662 :         if (error)
     819             :                 return error;
     820             : 
     821             :         /* Walk all inodes, picking up quota information. */
     822       18662 :         error = xqcheck_collect_counts(xqc);
     823       18662 :         if (!xchk_xref_process_error(sc, 0, 0, &error))
     824           0 :                 return error;
     825             : 
     826             :         /* Fail fast if we're not playing with a full dataset. */
     827       18662 :         if (xchk_iscan_aborted(&xqc->iscan))
     828           0 :                 xchk_set_incomplete(sc);
     829       18662 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_INCOMPLETE)
     830             :                 return 0;
     831             : 
     832             :         /* Compare quota counters. */
     833       18662 :         if (xqc->ucounts) {
     834       18627 :                 error = xqcheck_compare_dqtype(xqc, XFS_DQTYPE_USER);
     835       18627 :                 if (!xchk_xref_process_error(sc, 0, 0, &error))
     836           0 :                         return error;
     837             :         }
     838       18662 :         if (xqc->gcounts) {
     839       18577 :                 error = xqcheck_compare_dqtype(xqc, XFS_DQTYPE_GROUP);
     840       18577 :                 if (!xchk_xref_process_error(sc, 0, 0, &error))
     841           2 :                         return error;
     842             :         }
     843       18660 :         if (xqc->pcounts) {
     844       18543 :                 error = xqcheck_compare_dqtype(xqc, XFS_DQTYPE_PROJ);
     845       18543 :                 if (!xchk_xref_process_error(sc, 0, 0, &error))
     846           0 :                         return error;
     847             :         }
     848             : 
     849             :         /* Check one last time for an incomplete dataset. */
     850       18660 :         if (xchk_iscan_aborted(&xqc->iscan))
     851           0 :                 xchk_set_incomplete(sc);
     852             : 
     853             :         return 0;
     854             : }

Generated by: LCOV version 1.14