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-acha @ Mon Jul 31 20:08:06 PDT 2023 Lines: 301 363 82.9 %
Date: 2023-07-31 20:08:07 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         324 : xqcheck_dqacct_free(
      70             :         void                    *ptr,
      71             :         void                    *arg)
      72             : {
      73     1311198 :         struct xqcheck_dqacct   *dqa = ptr;
      74             : 
      75         324 :         kfree(dqa);
      76     1310874 : }
      77             : 
      78             : /* Set us up to scrub quota counters. */
      79             : int
      80       10457 : xchk_setup_quotacheck(
      81             :         struct xfs_scrub        *sc)
      82             : {
      83       10457 :         if (!XFS_IS_QUOTA_ON(sc->mp))
      84             :                 return -ENOENT;
      85             : 
      86        7647 :         xchk_fsgates_enable(sc, XCHK_FSGATES_QUOTA);
      87             : 
      88        7647 :         sc->buf = kzalloc(sizeof(struct xqcheck), XCHK_GFP_FLAGS);
      89        7647 :         if (!sc->buf)
      90             :                 return -ENOMEM;
      91             : 
      92        7647 :         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   157481982 : 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   157481982 :         struct xqcheck_dquot    xcdq;
     136   157481982 :         int                     error;
     137             : 
     138   157481982 :         error = xfarray_load_sparse(counts, id, &xcdq);
     139   157481982 :         if (error)
     140             :                 return error;
     141             : 
     142   157481982 :         xcdq.flags |= XQCHECK_DQUOT_WRITTEN;
     143   157481982 :         xcdq.icount += inodes;
     144   157481982 :         xcdq.bcount += nblks;
     145   157481982 :         xcdq.rtbcount += rtblks;
     146             : 
     147   157481982 :         error = xfarray_store(counts, id, &xcdq);
     148   157481982 :         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     7416063 : xqcheck_dqacct_obj_cmpfn(
     162             :         struct rhashtable_compare_arg   *arg,
     163             :         const void                      *obj)
     164             : {
     165     7416063 :         const uintptr_t                 *tx_idp = arg->key;
     166     7416063 :         const struct xqcheck_dqacct     *dqa = obj;
     167             : 
     168     7416063 :         if (dqa->tx_id != *tx_idp)
     169       77160 :                 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     8650101 : xqcheck_get_dqtrx(
     185             :         struct xqcheck_dqacct   *dqa,
     186             :         xfs_dqtype_t            q_type,
     187             :         xfs_dqid_t              q_id)
     188             : {
     189     8650101 :         int                     i;
     190             : 
     191    17735620 :         for (i = 0; i < XQCHECK_MAX_NR_DQTRXS; i++) {
     192    17735620 :                 if (dqa->dqtrx[i].q_type == 0 ||
     193     5133482 :                     (dqa->dqtrx[i].q_type == q_type &&
     194     5133482 :                      dqa->dqtrx[i].q_id == q_id))
     195     8650101 :                         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     5010661 : xqcheck_mod_live_ino_dqtrx(
     207             :         struct notifier_block           *nb,
     208             :         unsigned long                   action,
     209             :         void                            *data)
     210             : {
     211     5010661 :         struct xfs_mod_ino_dqtrx_params *p = data;
     212     5010661 :         struct xqcheck                  *xqc;
     213     5010661 :         struct xqcheck_dqacct           *dqa;
     214     5010661 :         struct xqcheck_dqtrx            *dqtrx;
     215     5010661 :         int                             error;
     216             : 
     217     5010661 :         xqc = container_of(nb, struct xqcheck, hooks.mod_hook.nb);
     218             : 
     219             :         /* Skip quota reservation fields. */
     220     5010661 :         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     5010844 :                 break;
     227             :         default:
     228             :                 return NOTIFY_DONE;
     229             :         }
     230             : 
     231             :         /* Ignore dqtrx updates for quota types we don't care about. */
     232     5010844 :         switch (p->q_type) {
     233     1763882 :         case XFS_DQTYPE_USER:
     234     1763882 :                 if (!xqc->ucounts)
     235             :                         return NOTIFY_DONE;
     236             :                 break;
     237     1763812 :         case XFS_DQTYPE_GROUP:
     238     1763812 :                 if (!xqc->gcounts)
     239             :                         return NOTIFY_DONE;
     240             :                 break;
     241     1483150 :         case XFS_DQTYPE_PROJ:
     242     1483150 :                 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     5010844 :         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     4646266 :         mutex_lock(&xqc->lock);
     255     4646274 :         dqa = rhashtable_lookup_fast(&xqc->shadow_dquot_acct, &p->tx_id,
     256             :                         xqcheck_dqacct_hash_params);
     257     4646274 :         if (!dqa) {
     258     1311198 :                 dqa = kzalloc(sizeof(struct xqcheck_dqacct), XCHK_GFP_FLAGS);
     259     1311198 :                 if (!dqa)
     260           0 :                         goto out_abort;
     261             : 
     262     1311198 :                 dqa->tx_id = p->tx_id;
     263     1311198 :                 error = rhashtable_insert_fast(&xqc->shadow_dquot_acct,
     264             :                                 &dqa->hash, xqcheck_dqacct_hash_params);
     265     1311198 :                 if (error)
     266           0 :                         goto out_abort;
     267             :         }
     268             : 
     269             :         /* Find the shadow dqtrx (or an empty slot) here. */
     270     4646274 :         dqtrx = xqcheck_get_dqtrx(dqa, p->q_type, p->q_id);
     271     4646274 :         if (!dqtrx)
     272           0 :                 goto out_abort;
     273     4646274 :         if (dqtrx->q_type == 0) {
     274     3998335 :                 dqtrx->q_type = p->q_type;
     275     3998335 :                 dqtrx->q_id = p->q_id;
     276     3998335 :                 dqa->refcount++;
     277             :         }
     278             : 
     279             :         /* Update counter */
     280     4646274 :         switch (action) {
     281     2103523 :         case XFS_TRANS_DQ_BCOUNT:
     282     2103523 :                 dqtrx->bcount_delta += p->delta;
     283     2103523 :                 break;
     284     1331019 :         case XFS_TRANS_DQ_DELBCOUNT:
     285     1331019 :                 dqtrx->delbcnt_delta += p->delta;
     286     1331019 :                 break;
     287     1211732 :         case XFS_TRANS_DQ_ICOUNT:
     288     1211732 :                 dqtrx->icount_delta += p->delta;
     289     1211732 :                 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     4646274 :         mutex_unlock(&xqc->lock);
     299     4646274 :         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    30971524 : xqcheck_apply_live_dqtrx(
     313             :         struct notifier_block           *nb,
     314             :         unsigned long                   action,
     315             :         void                            *data)
     316             : {
     317    30971524 :         struct xfs_apply_dqtrx_params   *p = data;
     318    30971524 :         struct xqcheck                  *xqc;
     319    30971524 :         struct xqcheck_dqacct           *dqa;
     320    30971524 :         struct xqcheck_dqtrx            *dqtrx;
     321    30971524 :         struct xfarray                  *counts;
     322    30971524 :         int                             error;
     323             : 
     324    30971524 :         xqc = container_of(nb, struct xqcheck, hooks.apply_hook.nb);
     325             : 
     326             :         /* Map the dquot type to an incore counter object. */
     327    30971524 :         switch (p->q_type) {
     328    10377243 :         case XFS_DQTYPE_USER:
     329    10377243 :                 counts = xqc->ucounts;
     330    10377243 :                 break;
     331    10377776 :         case XFS_DQTYPE_GROUP:
     332    10377776 :                 counts = xqc->gcounts;
     333    10377776 :                 break;
     334    10216505 :         case XFS_DQTYPE_PROJ:
     335    10216505 :                 counts = xqc->pcounts;
     336    10216505 :                 break;
     337             :         default:
     338             :                 return NOTIFY_DONE;
     339             :         }
     340             : 
     341    30971524 :         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    30942221 :         mutex_lock(&xqc->lock);
     349    30946897 :         dqa = rhashtable_lookup_fast(&xqc->shadow_dquot_acct, &p->tx_id,
     350             :                         xqcheck_dqacct_hash_params);
     351    30946897 :         if (!dqa)
     352    26943070 :                 goto out_unlock;
     353     4003827 :         dqtrx = xqcheck_get_dqtrx(dqa, p->q_type, p->q_id);
     354     4003827 :         if (!dqtrx || dqtrx->q_type == 0)
     355        6192 :                 goto out_unlock;
     356             : 
     357             :         /* Update our shadow dquot if we're committing. */
     358     3997635 :         if (action == XFS_APPLY_DQTRX_COMMIT) {
     359     3711351 :                 error = xqcheck_update_incore_counts(xqc, counts, p->q_id,
     360             :                                 dqtrx->icount_delta,
     361     3711351 :                                 dqtrx->bcount_delta + dqtrx->delbcnt_delta,
     362     3711351 :                                 dqtrx->rtbcount_delta + dqtrx->delrtb_delta);
     363     3711351 :                 if (error)
     364           0 :                         goto out_abort;
     365             :         }
     366             : 
     367             :         /* Free the shadow accounting structure if that was the last user. */
     368     3997635 :         dqa->refcount--;
     369     3997635 :         if (dqa->refcount == 0) {
     370     1310874 :                 error = rhashtable_remove_fast(&xqc->shadow_dquot_acct,
     371             :                                 &dqa->hash, xqcheck_dqacct_hash_params);
     372     1310874 :                 if (error)
     373           0 :                         goto out_abort;
     374     1310874 :                 xqcheck_dqacct_free(dqa, NULL);
     375             :         }
     376             : 
     377     3997635 :         mutex_unlock(&xqc->lock);
     378     3997635 :         return NOTIFY_DONE;
     379             : 
     380           0 : out_abort:
     381           0 :         xchk_iscan_abort(&xqc->iscan);
     382    26949262 : out_unlock:
     383    26949262 :         mutex_unlock(&xqc->lock);
     384    26949262 :         return NOTIFY_DONE;
     385             : }
     386             : 
     387             : /* Record this inode's quota usage in our shadow quota counter data. */
     388             : STATIC int
     389    51280189 : xqcheck_collect_inode(
     390             :         struct xqcheck          *xqc,
     391             :         struct xfs_inode        *ip)
     392             : {
     393    51280189 :         struct xfs_trans        *tp = xqc->sc->tp;
     394    51280189 :         xfs_filblks_t           nblks, rtblks;
     395    51280189 :         uint                    ilock_flags = 0;
     396    51280189 :         xfs_dqid_t              id;
     397    51280189 :         bool                    isreg = S_ISREG(VFS_I(ip)->i_mode);
     398    51280189 :         int                     error = 0;
     399             : 
     400   102552742 :         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       22866 :                 xchk_iscan_mark_visited(&xqc->iscan, ip);
     406       22866 :                 return 0;
     407             :         }
     408             : 
     409             :         /* Figure out the data / rt device block counts. */
     410    51257323 :         xfs_ilock(ip, XFS_IOLOCK_SHARED);
     411    51257323 :         if (isreg)
     412    23718706 :                 xfs_ilock(ip, XFS_MMAPLOCK_SHARED);
     413    51257323 :         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    51257323 :                 ilock_flags = XFS_ILOCK_SHARED;
     420    51257323 :                 xfs_ilock(ip, XFS_ILOCK_SHARED);
     421             :         }
     422    51257323 :         xfs_inode_count_blocks(tp, ip, &nblks, &rtblks);
     423             : 
     424    51257323 :         if (xchk_iscan_aborted(&xqc->iscan)) {
     425           0 :                 error = -ECANCELED;
     426           0 :                 goto out_incomplete;
     427             :         }
     428             : 
     429             :         /* Update the shadow dquot counters. */
     430    51257323 :         mutex_lock(&xqc->lock);
     431    51257323 :         if (xqc->ucounts) {
     432    51257075 :                 id = xfs_qm_id_for_quotatype(ip, XFS_DQTYPE_USER);
     433    51257075 :                 error = xqcheck_update_incore_counts(xqc, xqc->ucounts, id, 1,
     434             :                                 nblks, rtblks);
     435    51257075 :                 if (error)
     436           0 :                         goto out_mutex;
     437             :         }
     438             : 
     439    51257323 :         if (xqc->gcounts) {
     440    51256587 :                 id = xfs_qm_id_for_quotatype(ip, XFS_DQTYPE_GROUP);
     441    51256587 :                 error = xqcheck_update_incore_counts(xqc, xqc->gcounts, id, 1,
     442             :                                 nblks, rtblks);
     443    51256587 :                 if (error)
     444           0 :                         goto out_mutex;
     445             :         }
     446             : 
     447    51257323 :         if (xqc->pcounts) {
     448    51256969 :                 id = xfs_qm_id_for_quotatype(ip, XFS_DQTYPE_PROJ);
     449    51256969 :                 error = xqcheck_update_incore_counts(xqc, xqc->pcounts, id, 1,
     450             :                                 nblks, rtblks);
     451    51256969 :                 if (error)
     452           0 :                         goto out_mutex;
     453             :         }
     454    51257323 :         mutex_unlock(&xqc->lock);
     455             : 
     456    51257323 :         xchk_iscan_mark_visited(&xqc->iscan, ip);
     457    51257323 :         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    51257323 : out_ilock:
     466    51257323 :         xfs_iunlock(ip, ilock_flags);
     467    51257323 :         if (isreg)
     468    23718706 :                 xfs_iunlock(ip, XFS_MMAPLOCK_SHARED);
     469    51257323 :         xfs_iunlock(ip, XFS_IOLOCK_SHARED);
     470    51257323 :         return error;
     471             : }
     472             : 
     473             : /* Walk all the allocated inodes and run a quota scan on them. */
     474             : STATIC int
     475        7647 : xqcheck_collect_counts(
     476             :         struct xqcheck          *xqc)
     477             : {
     478        7647 :         struct xfs_scrub        *sc = xqc->sc;
     479        7647 :         struct xfs_inode        *ip;
     480        7647 :         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        7647 :         xchk_trans_cancel(sc);
     499        7647 :         error = xchk_trans_alloc_empty(sc);
     500        7647 :         if (error)
     501             :                 return error;
     502             : 
     503    51287835 :         while ((error = xchk_iscan_iter(&xqc->iscan, &ip)) == 1) {
     504    51280189 :                 error = xqcheck_collect_inode(xqc, ip);
     505    51280189 :                 xchk_irele(sc, ip);
     506    51280189 :                 if (error)
     507             :                         break;
     508             : 
     509    51280189 :                 if (xchk_should_terminate(sc, &error))
     510             :                         break;
     511             :         }
     512        7647 :         xchk_iscan_iter_finish(&xqc->iscan);
     513        7647 :         if (error) {
     514           1 :                 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           1 :                 if (error == -EBUSY)
     521             :                         return -ECANCELED;
     522           1 :                 return error;
     523             :         }
     524             : 
     525             :         /*
     526             :          * Switch out for a real transaction in preparation for building a new
     527             :          * tree.
     528             :          */
     529        7646 :         xchk_trans_cancel(sc);
     530        7646 :         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    10110908 : xqcheck_compare_dquot(
     546             :         struct xfs_dquot        *dqp,
     547             :         xfs_dqtype_t            dqtype,
     548             :         void                    *priv)
     549             : {
     550    10110908 :         struct xqcheck_dquot    xcdq;
     551    10110908 :         struct xqcheck          *xqc = priv;
     552    10110908 :         struct xfarray          *counts = xqcheck_counters_for(xqc, dqtype);
     553    10110908 :         int                     error;
     554             : 
     555    10110908 :         if (xchk_iscan_aborted(&xqc->iscan)) {
     556           0 :                 xchk_set_incomplete(xqc->sc);
     557           0 :                 return -ECANCELED;
     558             :         }
     559             : 
     560    10110908 :         mutex_lock(&xqc->lock);
     561    10110908 :         error = xfarray_load_sparse(counts, dqp->q_id, &xcdq);
     562    10110908 :         if (error)
     563           0 :                 goto out_unlock;
     564             : 
     565    10110908 :         if (xcdq.icount != dqp->q_ino.count)
     566           0 :                 xchk_qcheck_set_corrupt(xqc->sc, dqtype, dqp->q_id);
     567             : 
     568    10110908 :         if (xcdq.bcount != dqp->q_blk.count)
     569           0 :                 xchk_qcheck_set_corrupt(xqc->sc, dqtype, dqp->q_id);
     570             : 
     571    10110908 :         if (xcdq.rtbcount != dqp->q_rtb.count)
     572           0 :                 xchk_qcheck_set_corrupt(xqc->sc, dqtype, dqp->q_id);
     573             : 
     574    10110908 :         xcdq.flags |= (XQCHECK_DQUOT_COMPARE_SCANNED | XQCHECK_DQUOT_WRITTEN);
     575    10110908 :         error = xfarray_store(counts, dqp->q_id, &xcdq);
     576    10110908 :         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    10110908 :         mutex_unlock(&xqc->lock);
     587    10110908 :         if (error)
     588             :                 return error;
     589             : 
     590    10110908 :         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       22857 : xqcheck_walk_observations(
     606             :         struct xqcheck          *xqc,
     607             :         xfs_dqtype_t            dqtype)
     608             : {
     609       22857 :         struct xqcheck_dquot    xcdq;
     610       22857 :         struct xfs_dquot        *dqp;
     611       22857 :         struct xfarray          *counts = xqcheck_counters_for(xqc, dqtype);
     612       22857 :         xfarray_idx_t           cur = XFARRAY_CURSOR_INIT;
     613       22857 :         int                     error;
     614             : 
     615       22857 :         mutex_lock(&xqc->lock);
     616    10133762 :         while ((error = xfarray_iter(counts, &cur, &xcdq)) == 1) {
     617    10110908 :                 xfs_dqid_t      id = cur - 1;
     618             : 
     619    10110908 :                 if (xcdq.flags & XQCHECK_DQUOT_COMPARE_SCANNED)
     620       22857 :                         continue;
     621             : 
     622    10088051 :                 mutex_unlock(&xqc->lock);
     623             : 
     624    10088051 :                 error = xfs_qm_dqget(xqc->sc->mp, id, dqtype, false, &dqp);
     625    10088051 :                 if (error == -ENOENT) {
     626           0 :                         xchk_qcheck_set_corrupt(xqc->sc, dqtype, id);
     627           0 :                         return 0;
     628             :                 }
     629    10088051 :                 if (error)
     630           0 :                         return error;
     631             : 
     632    10088051 :                 error = xqcheck_compare_dquot(dqp, dqtype, xqc);
     633    10088051 :                 xfs_qm_dqput(dqp);
     634    10088051 :                 if (error)
     635           0 :                         return error;
     636             : 
     637    10088051 :                 if (xchk_should_terminate(xqc->sc, &error))
     638           3 :                         return error;
     639             : 
     640    10088048 :                 mutex_lock(&xqc->lock);
     641             :         }
     642       22854 :         mutex_unlock(&xqc->lock);
     643             : 
     644       22854 :         return error;
     645             : }
     646             : 
     647             : /* Compare the quota counters we observed against the live dquots. */
     648             : STATIC int
     649       22857 : xqcheck_compare_dqtype(
     650             :         struct xqcheck          *xqc,
     651             :         xfs_dqtype_t            dqtype)
     652             : {
     653       22857 :         struct xfs_scrub        *sc = xqc->sc;
     654       22857 :         int                     error;
     655             : 
     656       22857 :         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       45714 :         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       22857 :         error = xfs_qm_dqiterate(sc->mp, dqtype, xqcheck_compare_dquot, xqc);
     667       22857 :         if (error)
     668             :                 return error;
     669             : 
     670             :         /* Walk all the observed dquots and compare to the incore ones. */
     671       22857 :         return xqcheck_walk_observations(xqc, dqtype);
     672             : }
     673             : 
     674             : /* Tear down everything associated with a quotacheck. */
     675             : static void
     676        7647 : xqcheck_teardown_scan(
     677             :         void                    *priv)
     678             : {
     679        7647 :         struct xqcheck          *xqc = priv;
     680        7647 :         struct xfs_quotainfo    *qi = xqc->sc->mp->m_quotainfo;
     681             : 
     682             :         /* Discourage any hook functions that might be running. */
     683        7647 :         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        7647 :         xfs_dqtrx_hook_del(qi, &xqc->hooks);
     694             : 
     695        7647 :         if (xqc->shadow_dquot_acct.key_len) {
     696        7647 :                 rhashtable_free_and_destroy(&xqc->shadow_dquot_acct,
     697             :                                 xqcheck_dqacct_free, NULL);
     698        7647 :                 xqc->shadow_dquot_acct.key_len = 0;
     699             :         }
     700             : 
     701        7647 :         if (xqc->pcounts) {
     702        7611 :                 xfarray_destroy(xqc->pcounts);
     703        7611 :                 xqc->pcounts = NULL;
     704             :         }
     705             : 
     706        7647 :         if (xqc->gcounts) {
     707        7617 :                 xfarray_destroy(xqc->gcounts);
     708        7617 :                 xqc->gcounts = NULL;
     709             :         }
     710             : 
     711        7647 :         if (xqc->ucounts) {
     712        7635 :                 xfarray_destroy(xqc->ucounts);
     713        7635 :                 xqc->ucounts = NULL;
     714             :         }
     715             : 
     716        7647 :         xchk_iscan_teardown(&xqc->iscan);
     717        7647 :         mutex_destroy(&xqc->lock);
     718        7647 :         xqc->sc = NULL;
     719        7647 : }
     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        7647 : xqcheck_setup_scan(
     728             :         struct xfs_scrub        *sc,
     729             :         struct xqcheck          *xqc)
     730             : {
     731        7647 :         char                    *descr;
     732        7647 :         struct xfs_quotainfo    *qi = sc->mp->m_quotainfo;
     733        7647 :         unsigned long long      max_dquots = ((xfs_dqid_t)-1) + 1;
     734        7647 :         int                     error;
     735             : 
     736        7647 :         ASSERT(xqc->sc == NULL);
     737        7647 :         xqc->sc = sc;
     738             : 
     739        7647 :         mutex_init(&xqc->lock);
     740             : 
     741             :         /* Retry iget every tenth of a second for up to 30 seconds. */
     742        7647 :         xchk_iscan_start(sc, 30000, 100, &xqc->iscan);
     743             : 
     744        7647 :         error = -ENOMEM;
     745        7647 :         if (xfs_this_quota_on(sc->mp, XFS_DQTYPE_USER)) {
     746        7635 :                 descr = xchk_xfile_descr(sc, "user dquot records");
     747        7635 :                 error = xfarray_create(descr, max_dquots,
     748             :                                 sizeof(struct xqcheck_dquot), &xqc->ucounts);
     749        7635 :                 kfree(descr);
     750        7635 :                 if (error)
     751           0 :                         goto out_teardown;
     752             :         }
     753             : 
     754        7647 :         if (xfs_this_quota_on(sc->mp, XFS_DQTYPE_GROUP)) {
     755        7617 :                 descr = xchk_xfile_descr(sc, "group dquot records");
     756        7617 :                 error = xfarray_create(descr, max_dquots,
     757             :                                 sizeof(struct xqcheck_dquot), &xqc->gcounts);
     758        7617 :                 kfree(descr);
     759        7617 :                 if (error)
     760           0 :                         goto out_teardown;
     761             :         }
     762             : 
     763        7647 :         if (xfs_this_quota_on(sc->mp, XFS_DQTYPE_PROJ)) {
     764        7611 :                 descr = xchk_xfile_descr(sc, "project dquot records");
     765        7611 :                 error = xfarray_create(descr, max_dquots,
     766             :                                 sizeof(struct xqcheck_dquot), &xqc->pcounts);
     767        7611 :                 kfree(descr);
     768        7611 :                 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        7647 :         error = rhashtable_init(&xqc->shadow_dquot_acct,
     777             :                         &xqcheck_dqacct_hash_params);
     778        7647 :         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        7647 :         ASSERT(sc->flags & XCHK_FSGATES_QUOTA);
     792        7647 :         xfs_hook_setup(&xqc->hooks.mod_hook, xqcheck_mod_live_ino_dqtrx);
     793        7647 :         xfs_hook_setup(&xqc->hooks.apply_hook, xqcheck_apply_live_dqtrx);
     794             : 
     795        7647 :         error = xfs_dqtrx_hook_add(qi, &xqc->hooks);
     796        7647 :         if (error)
     797           0 :                 goto out_teardown;
     798             : 
     799             :         /* Use deferred cleanup to pass the quota count data to repair. */
     800        7647 :         sc->buf_cleanup = xqcheck_teardown_scan;
     801        7647 :         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        7647 : xchk_quotacheck(
     811             :         struct xfs_scrub        *sc)
     812             : {
     813        7647 :         struct xqcheck          *xqc = sc->buf;
     814        7647 :         int                     error = 0;
     815             : 
     816             :         /* Check quota counters on the live filesystem. */
     817        7647 :         error = xqcheck_setup_scan(sc, xqc);
     818        7647 :         if (error)
     819             :                 return error;
     820             : 
     821             :         /* Walk all inodes, picking up quota information. */
     822        7647 :         error = xqcheck_collect_counts(xqc);
     823        7647 :         if (!xchk_xref_process_error(sc, 0, 0, &error))
     824           1 :                 return error;
     825             : 
     826             :         /* Fail fast if we're not playing with a full dataset. */
     827        7646 :         if (xchk_iscan_aborted(&xqc->iscan))
     828           0 :                 xchk_set_incomplete(sc);
     829        7646 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_INCOMPLETE)
     830             :                 return 0;
     831             : 
     832             :         /* Compare quota counters. */
     833        7646 :         if (xqc->ucounts) {
     834        7634 :                 error = xqcheck_compare_dqtype(xqc, XFS_DQTYPE_USER);
     835        7634 :                 if (!xchk_xref_process_error(sc, 0, 0, &error))
     836           0 :                         return error;
     837             :         }
     838        7646 :         if (xqc->gcounts) {
     839        7616 :                 error = xqcheck_compare_dqtype(xqc, XFS_DQTYPE_GROUP);
     840        7616 :                 if (!xchk_xref_process_error(sc, 0, 0, &error))
     841           3 :                         return error;
     842             :         }
     843        7643 :         if (xqc->pcounts) {
     844        7607 :                 error = xqcheck_compare_dqtype(xqc, XFS_DQTYPE_PROJ);
     845        7607 :                 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        7643 :         if (xchk_iscan_aborted(&xqc->iscan))
     851           0 :                 xchk_set_incomplete(sc);
     852             : 
     853             :         return 0;
     854             : }

Generated by: LCOV version 1.14