summaryrefslogtreecommitdiff
path: root/fs/xfs/scrub
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@kernel.org>2021-09-01 10:45:54 -0700
committerDarrick J. Wong <djwong@kernel.org>2021-10-22 16:40:36 -0700
commit48bec246f88d06c80d2918284cb9d78fa767c140 (patch)
tree0a3c0feabdef35a1f9e31c28c214ed2cba5c4e65 /fs/xfs/scrub
parent86fd53a2c51b3253bb407bd1003c1e86c017c53c (diff)
xfs: reintroduce reaping of file extents to xrep_reap_extents
Reintroduce to xrep_reap_extents the ability to reap extents from any AG. We dropped this before because it was buggy, but in the next patch we will gain the ability to reap old bmap btrees, which can have blocks in any AG. To do this, we require that sc->sa is uninitialized, so that we can use it to hold all the per-AG context for a given extent. Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Diffstat (limited to 'fs/xfs/scrub')
-rw-r--r--fs/xfs/scrub/repair.c43
1 files changed, 41 insertions, 2 deletions
diff --git a/fs/xfs/scrub/repair.c b/fs/xfs/scrub/repair.c
index 832926c1fa9d..20667b8b2754 100644
--- a/fs/xfs/scrub/repair.c
+++ b/fs/xfs/scrub/repair.c
@@ -1027,6 +1027,20 @@ xrep_reap_ag_extent(
roll_out:
rs->deferred = 0;
+ if (sc->ip) {
+ /*
+ * If we're reaping file data, hold the AGF buffer across the
+ * transaction roll so that we don't have to reattach it to the
+ * xchk_ag structure.
+ */
+ xfs_trans_bhold(sc->tp, sc->sa.agf_bp);
+ error = xfs_trans_roll_inode(&sc->tp, sc->ip);
+ if (error)
+ return error;
+ xfs_trans_bjoin(sc->tp, sc->sa.agf_bp);
+ return 0;
+ }
+
return xrep_roll_ag_trans(sc);
}
@@ -1086,8 +1100,24 @@ xrep_reap_extent(
ASSERT(len <= MAXEXTLEN);
- /* We don't support reaping file extents yet. */
- if (sc->ip != NULL || sc->sa.pag->pag_agno != agno) {
+ if (sc->ip != NULL) {
+ /*
+ * We're reaping blocks after repairing file metadata, which
+ * means that the blocks can be in any AG, so we have to init
+ * the xchk_ag structure before we can reap each extent and
+ * release it afterwards.
+ */
+ ASSERT(!sc->sa.pag);
+
+ sc->sa.pag = xfs_perag_get(sc->mp, agno);
+ if (!sc->sa.pag)
+ return -EFSCORRUPTED;
+
+ error = xfs_alloc_read_agf(sc->mp, sc->tp, agno, 0,
+ &sc->sa.agf_bp);
+ if (error)
+ goto out_pag;
+ } else if (sc->sa.pag == NULL || sc->sa.pag->pag_agno != agno) {
ASSERT(0);
return -EFSCORRUPTED;
}
@@ -1124,6 +1154,15 @@ xrep_reap_extent(
out_cur:
if (cur)
xfs_btree_del_cursor(cur, error);
+ if (sc->ip != NULL) {
+ xfs_trans_brelse(sc->tp, sc->sa.agf_bp);
+ sc->sa.agf_bp = NULL;
+ }
+out_pag:
+ if (sc->ip != NULL) {
+ xfs_perag_put(sc->sa.pag);
+ sc->sa.pag = NULL;
+ }
return error;
}