Lines Matching +full:down +full:- +full:counters
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (c) 2020-2024 Oracle. All Rights Reserved.
35 * Quota counters are "summary" metadata, in the sense that they are computed
79 /* Set us up to scrub quota counters. */
84 if (!XFS_IS_QUOTA_ON(sc->mp)) in xchk_setup_quotacheck()
85 return -ENOENT; in xchk_setup_quotacheck()
89 sc->buf = kzalloc(sizeof(struct xqcheck), XCHK_GFP_FLAGS); in xchk_setup_quotacheck()
90 if (!sc->buf) in xchk_setup_quotacheck()
91 return -ENOMEM; in xchk_setup_quotacheck()
110 * will try to update the quota counters for an inode that we've already
113 * per-transaction dqtrx structure to log quota counter updates; and (2) when
149 if (error == -EFBIG) { in xqcheck_update_incore_counts()
155 error = -ECANCELED; in xqcheck_update_incore_counts()
166 const uintptr_t *tx_idp = arg->key; in xqcheck_dqacct_obj_cmpfn()
169 if (dqa->tx_id != *tx_idp) in xqcheck_dqacct_obj_cmpfn()
193 if (dqa->dqtrx[i].q_type == 0 || in xqcheck_get_dqtrx()
194 (dqa->dqtrx[i].q_type == q_type && in xqcheck_get_dqtrx()
195 dqa->dqtrx[i].q_id == q_id)) in xqcheck_get_dqtrx()
196 return &dqa->dqtrx[i]; in xqcheck_get_dqtrx()
233 switch (p->q_type) { in xqcheck_mod_live_ino_dqtrx()
235 if (!xqc->ucounts) in xqcheck_mod_live_ino_dqtrx()
239 if (!xqc->gcounts) in xqcheck_mod_live_ino_dqtrx()
243 if (!xqc->pcounts) in xqcheck_mod_live_ino_dqtrx()
251 if (!xchk_iscan_want_live_update(&xqc->iscan, p->ino)) in xqcheck_mod_live_ino_dqtrx()
255 mutex_lock(&xqc->lock); in xqcheck_mod_live_ino_dqtrx()
256 dqa = rhashtable_lookup_fast(&xqc->shadow_dquot_acct, &p->tx_id, in xqcheck_mod_live_ino_dqtrx()
263 dqa->tx_id = p->tx_id; in xqcheck_mod_live_ino_dqtrx()
264 error = rhashtable_insert_fast(&xqc->shadow_dquot_acct, in xqcheck_mod_live_ino_dqtrx()
265 &dqa->hash, xqcheck_dqacct_hash_params); in xqcheck_mod_live_ino_dqtrx()
271 dqtrx = xqcheck_get_dqtrx(dqa, p->q_type, p->q_id); in xqcheck_mod_live_ino_dqtrx()
274 if (dqtrx->q_type == 0) { in xqcheck_mod_live_ino_dqtrx()
275 dqtrx->q_type = p->q_type; in xqcheck_mod_live_ino_dqtrx()
276 dqtrx->q_id = p->q_id; in xqcheck_mod_live_ino_dqtrx()
277 dqa->refcount++; in xqcheck_mod_live_ino_dqtrx()
283 dqtrx->bcount_delta += p->delta; in xqcheck_mod_live_ino_dqtrx()
286 dqtrx->delbcnt_delta += p->delta; in xqcheck_mod_live_ino_dqtrx()
289 dqtrx->icount_delta += p->delta; in xqcheck_mod_live_ino_dqtrx()
292 dqtrx->rtbcount_delta += p->delta; in xqcheck_mod_live_ino_dqtrx()
295 dqtrx->delrtb_delta += p->delta; in xqcheck_mod_live_ino_dqtrx()
299 mutex_unlock(&xqc->lock); in xqcheck_mod_live_ino_dqtrx()
303 xchk_iscan_abort(&xqc->iscan); in xqcheck_mod_live_ino_dqtrx()
304 mutex_unlock(&xqc->lock); in xqcheck_mod_live_ino_dqtrx()
328 switch (p->q_type) { in xqcheck_apply_live_dqtrx()
330 counts = xqc->ucounts; in xqcheck_apply_live_dqtrx()
333 counts = xqc->gcounts; in xqcheck_apply_live_dqtrx()
336 counts = xqc->pcounts; in xqcheck_apply_live_dqtrx()
342 if (xchk_iscan_aborted(&xqc->iscan) || counts == NULL) in xqcheck_apply_live_dqtrx()
349 mutex_lock(&xqc->lock); in xqcheck_apply_live_dqtrx()
350 dqa = rhashtable_lookup_fast(&xqc->shadow_dquot_acct, &p->tx_id, in xqcheck_apply_live_dqtrx()
354 dqtrx = xqcheck_get_dqtrx(dqa, p->q_type, p->q_id); in xqcheck_apply_live_dqtrx()
355 if (!dqtrx || dqtrx->q_type == 0) in xqcheck_apply_live_dqtrx()
360 error = xqcheck_update_incore_counts(xqc, counts, p->q_id, in xqcheck_apply_live_dqtrx()
361 dqtrx->icount_delta, in xqcheck_apply_live_dqtrx()
362 dqtrx->bcount_delta + dqtrx->delbcnt_delta, in xqcheck_apply_live_dqtrx()
363 dqtrx->rtbcount_delta + dqtrx->delrtb_delta); in xqcheck_apply_live_dqtrx()
369 dqa->refcount--; in xqcheck_apply_live_dqtrx()
370 if (dqa->refcount == 0) { in xqcheck_apply_live_dqtrx()
371 error = rhashtable_remove_fast(&xqc->shadow_dquot_acct, in xqcheck_apply_live_dqtrx()
372 &dqa->hash, xqcheck_dqacct_hash_params); in xqcheck_apply_live_dqtrx()
378 mutex_unlock(&xqc->lock); in xqcheck_apply_live_dqtrx()
382 xchk_iscan_abort(&xqc->iscan); in xqcheck_apply_live_dqtrx()
384 mutex_unlock(&xqc->lock); in xqcheck_apply_live_dqtrx()
394 struct xfs_trans *tp = xqc->sc->tp; in xqcheck_collect_inode()
398 bool isreg = S_ISREG(VFS_I(ip)->i_mode); in xqcheck_collect_inode()
401 if (xfs_is_quota_inode(&tp->t_mountp->m_sb, ip->i_ino)) { in xqcheck_collect_inode()
406 xchk_iscan_mark_visited(&xqc->iscan, ip); in xqcheck_collect_inode()
430 if (xchk_iscan_aborted(&xqc->iscan)) { in xqcheck_collect_inode()
431 error = -ECANCELED; in xqcheck_collect_inode()
435 /* Update the shadow dquot counters. */ in xqcheck_collect_inode()
436 mutex_lock(&xqc->lock); in xqcheck_collect_inode()
437 if (xqc->ucounts) { in xqcheck_collect_inode()
439 error = xqcheck_update_incore_counts(xqc, xqc->ucounts, id, 1, in xqcheck_collect_inode()
445 if (xqc->gcounts) { in xqcheck_collect_inode()
447 error = xqcheck_update_incore_counts(xqc, xqc->gcounts, id, 1, in xqcheck_collect_inode()
453 if (xqc->pcounts) { in xqcheck_collect_inode()
455 error = xqcheck_update_incore_counts(xqc, xqc->pcounts, id, 1, in xqcheck_collect_inode()
460 mutex_unlock(&xqc->lock); in xqcheck_collect_inode()
462 xchk_iscan_mark_visited(&xqc->iscan, ip); in xqcheck_collect_inode()
466 mutex_unlock(&xqc->lock); in xqcheck_collect_inode()
468 xchk_iscan_abort(&xqc->iscan); in xqcheck_collect_inode()
470 xchk_set_incomplete(xqc->sc); in xqcheck_collect_inode()
484 struct xfs_scrub *sc = xqc->sc; in xqcheck_collect_counts()
509 while ((error = xchk_iscan_iter(&xqc->iscan, &ip)) == 1) { in xqcheck_collect_counts()
518 xchk_iscan_iter_finish(&xqc->iscan); in xqcheck_collect_counts()
526 if (error == -EBUSY) in xqcheck_collect_counts()
527 return -ECANCELED; in xqcheck_collect_counts()
540 * Part 2: Comparing dquot resource counters. Walk each xfs_dquot, comparing
541 * the resource usage counters against our shadow dquots; and then walk each
560 if (xchk_iscan_aborted(&xqc->iscan)) { in xqcheck_compare_dquot()
561 xchk_set_incomplete(xqc->sc); in xqcheck_compare_dquot()
562 return -ECANCELED; in xqcheck_compare_dquot()
565 mutex_lock(&xqc->lock); in xqcheck_compare_dquot()
566 error = xfarray_load_sparse(counts, dq->q_id, &xcdq); in xqcheck_compare_dquot()
570 if (xcdq.icount != dq->q_ino.count) in xqcheck_compare_dquot()
571 xchk_qcheck_set_corrupt(xqc->sc, dqtype, dq->q_id); in xqcheck_compare_dquot()
573 if (xcdq.bcount != dq->q_blk.count) in xqcheck_compare_dquot()
574 xchk_qcheck_set_corrupt(xqc->sc, dqtype, dq->q_id); in xqcheck_compare_dquot()
576 if (xcdq.rtbcount != dq->q_rtb.count) in xqcheck_compare_dquot()
577 xchk_qcheck_set_corrupt(xqc->sc, dqtype, dq->q_id); in xqcheck_compare_dquot()
580 error = xfarray_store(counts, dq->q_id, &xcdq); in xqcheck_compare_dquot()
581 if (error == -EFBIG) { in xqcheck_compare_dquot()
588 xchk_set_incomplete(xqc->sc); in xqcheck_compare_dquot()
589 error = -ECANCELED; in xqcheck_compare_dquot()
591 mutex_unlock(&xqc->lock); in xqcheck_compare_dquot()
595 if (xqc->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) in xqcheck_compare_dquot()
596 return -ECANCELED; in xqcheck_compare_dquot()
601 mutex_unlock(&xqc->lock); in xqcheck_compare_dquot()
620 mutex_lock(&xqc->lock); in xqcheck_walk_observations()
622 xfs_dqid_t id = cur - 1; in xqcheck_walk_observations()
627 mutex_unlock(&xqc->lock); in xqcheck_walk_observations()
629 error = xfs_qm_dqget(xqc->sc->mp, id, dqtype, false, &dq); in xqcheck_walk_observations()
630 if (error == -ENOENT) { in xqcheck_walk_observations()
631 xchk_qcheck_set_corrupt(xqc->sc, dqtype, id); in xqcheck_walk_observations()
642 if (xchk_should_terminate(xqc->sc, &error)) in xqcheck_walk_observations()
645 mutex_lock(&xqc->lock); in xqcheck_walk_observations()
647 mutex_unlock(&xqc->lock); in xqcheck_walk_observations()
652 /* Compare the quota counters we observed against the live dquots. */
659 struct xfs_scrub *sc = xqc->sc; in xqcheck_compare_dqtype()
663 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) in xqcheck_compare_dqtype()
667 if (!(xfs_quota_chkd_flag(dqtype) & sc->mp->m_qflags)) { in xqcheck_compare_dqtype()
668 xchk_qcheck_set_corrupt(xqc->sc, dqtype, 0); in xqcheck_compare_dqtype()
687 /* Tear down everything associated with a quotacheck. */
693 struct xfs_quotainfo *qi = xqc->sc->mp->m_quotainfo; in xqcheck_teardown_scan()
696 xchk_iscan_abort(&xqc->iscan); in xqcheck_teardown_scan()
706 xfs_dqtrx_hook_del(qi, &xqc->qhook); in xqcheck_teardown_scan()
708 if (xqc->shadow_dquot_acct.key_len) { in xqcheck_teardown_scan()
709 rhashtable_free_and_destroy(&xqc->shadow_dquot_acct, in xqcheck_teardown_scan()
711 xqc->shadow_dquot_acct.key_len = 0; in xqcheck_teardown_scan()
714 if (xqc->pcounts) { in xqcheck_teardown_scan()
715 xfarray_destroy(xqc->pcounts); in xqcheck_teardown_scan()
716 xqc->pcounts = NULL; in xqcheck_teardown_scan()
719 if (xqc->gcounts) { in xqcheck_teardown_scan()
720 xfarray_destroy(xqc->gcounts); in xqcheck_teardown_scan()
721 xqc->gcounts = NULL; in xqcheck_teardown_scan()
724 if (xqc->ucounts) { in xqcheck_teardown_scan()
725 xfarray_destroy(xqc->ucounts); in xqcheck_teardown_scan()
726 xqc->ucounts = NULL; in xqcheck_teardown_scan()
729 xchk_iscan_teardown(&xqc->iscan); in xqcheck_teardown_scan()
730 mutex_destroy(&xqc->lock); in xqcheck_teardown_scan()
731 xqc->sc = NULL; in xqcheck_teardown_scan()
737 * If any error occurs, we'll tear everything down.
745 struct xfs_quotainfo *qi = sc->mp->m_quotainfo; in xqcheck_setup_scan()
749 ASSERT(xqc->sc == NULL); in xqcheck_setup_scan()
750 xqc->sc = sc; in xqcheck_setup_scan()
752 mutex_init(&xqc->lock); in xqcheck_setup_scan()
755 xchk_iscan_start(sc, 30000, 100, &xqc->iscan); in xqcheck_setup_scan()
757 error = -ENOMEM; in xqcheck_setup_scan()
758 if (xfs_this_quota_on(sc->mp, XFS_DQTYPE_USER)) { in xqcheck_setup_scan()
761 sizeof(struct xqcheck_dquot), &xqc->ucounts); in xqcheck_setup_scan()
767 if (xfs_this_quota_on(sc->mp, XFS_DQTYPE_GROUP)) { in xqcheck_setup_scan()
770 sizeof(struct xqcheck_dquot), &xqc->gcounts); in xqcheck_setup_scan()
776 if (xfs_this_quota_on(sc->mp, XFS_DQTYPE_PROJ)) { in xqcheck_setup_scan()
779 sizeof(struct xqcheck_dquot), &xqc->pcounts); in xqcheck_setup_scan()
789 error = rhashtable_init(&xqc->shadow_dquot_acct, in xqcheck_setup_scan()
797 * ILOCK, which means that any in-progress inode updates will finish in xqcheck_setup_scan()
804 ASSERT(sc->flags & XCHK_FSGATES_QUOTA); in xqcheck_setup_scan()
805 xfs_dqtrx_hook_setup(&xqc->qhook, xqcheck_mod_live_ino_dqtrx, in xqcheck_setup_scan()
808 error = xfs_dqtrx_hook_add(qi, &xqc->qhook); in xqcheck_setup_scan()
813 sc->buf_cleanup = xqcheck_teardown_scan; in xqcheck_setup_scan()
821 /* Scrub all counters for a given quota type. */
826 struct xqcheck *xqc = sc->buf; in xchk_quotacheck()
829 /* Check quota counters on the live filesystem. */ in xchk_quotacheck()
840 if (xchk_iscan_aborted(&xqc->iscan)) in xchk_quotacheck()
842 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_INCOMPLETE) in xchk_quotacheck()
845 /* Compare quota counters. */ in xchk_quotacheck()
846 if (xqc->ucounts) { in xchk_quotacheck()
851 if (xqc->gcounts) { in xchk_quotacheck()
856 if (xqc->pcounts) { in xchk_quotacheck()
863 if (xchk_iscan_aborted(&xqc->iscan)) in xchk_quotacheck()