diff options
author | Darrick J. Wong <djwong@kernel.org> | 2021-09-01 11:18:45 -0700 |
---|---|---|
committer | Darrick J. Wong <djwong@kernel.org> | 2021-10-22 16:41:09 -0700 |
commit | 2407ce4b1bad9c3846e3351f49718eea95e8cda5 (patch) | |
tree | 119cd3994b15db30d39d5955a7cb2636fcff1c15 /fs/xfs/libxfs | |
parent | 0e56e9ca305bfe65f4fb2c8889636f07e4a20a4c (diff) |
xfs: refcover CoW leftovers in the realtime volume
Scan the realtime refcount tree at mount time to get rid of leftover
CoW staging extents.
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Diffstat (limited to 'fs/xfs/libxfs')
-rw-r--r-- | fs/xfs/libxfs/xfs_refcount.c | 39 |
1 files changed, 26 insertions, 13 deletions
diff --git a/fs/xfs/libxfs/xfs_refcount.c b/fs/xfs/libxfs/xfs_refcount.c index 5f28c9440920..3a0bd1c002ab 100644 --- a/fs/xfs/libxfs/xfs_refcount.c +++ b/fs/xfs/libxfs/xfs_refcount.c @@ -1797,16 +1797,20 @@ xfs_refcount_recover_cow_leftovers( { struct xfs_trans *tp; struct xfs_btree_cur *cur; - struct xfs_buf *agbp; + struct xfs_buf *agbp = NULL; struct xfs_refcount_recovery *rr, *n; struct list_head debris; union xfs_btree_irec low; union xfs_btree_irec high; xfs_fsblock_t fsb; xfs_fsblock_t bno; + xfs_fsblock_t cow_start; + bool isrt = pag == NULL; int error; - if (mp->m_sb.sb_agblocks >= XFS_REFC_COW_START) + if (!isrt && mp->m_sb.sb_agblocks >= XFS_REFC_COW_START) + return -EOPNOTSUPP; + if (isrt && mp->m_sb.sb_rextents >= XFS_RTREFC_COW_START) return -EOPNOTSUPP; INIT_LIST_HEAD(&debris); @@ -1825,20 +1829,29 @@ xfs_refcount_recover_cow_leftovers( if (error) return error; - error = xfs_alloc_read_agf(mp, tp, pag->pag_agno, 0, &agbp); - if (error) - goto out_trans; - cur = xfs_refcountbt_init_cursor(mp, tp, agbp, pag); + if (isrt) { + xfs_rtlock(NULL, mp, XFS_RTLOCK_REFCOUNT); + cur = xfs_rtrefcountbt_init_cursor(mp, tp, mp->m_rrefcountip); + } else { + error = xfs_alloc_read_agf(mp, tp, pag->pag_agno, 0, &agbp); + if (error) + goto out_trans; + cur = xfs_refcountbt_init_cursor(mp, tp, agbp, pag); + } + cow_start = xrefc_cow_start(cur); /* Find all the leftover CoW staging extents. */ memset(&low, 0, sizeof(low)); memset(&high, 0, sizeof(high)); - low.rc.rc_startblock = XFS_REFC_COW_START; - high.rc.rc_startblock = -1U; + low.rc.rc_startblock = cow_start; + high.rc.rc_startblock = -1ULL; error = xfs_btree_query_range(cur, &low, &high, xfs_refcount_recover_extent, &debris); xfs_btree_del_cursor(cur, error); - xfs_trans_brelse(tp, agbp); + if (agbp) + xfs_trans_brelse(tp, agbp); + else + xfs_rtunlock(mp, XFS_RTLOCK_REFCOUNT); xfs_trans_cancel(tp); if (error) goto out_free; @@ -1851,14 +1864,14 @@ xfs_refcount_recover_cow_leftovers( goto out_free; /* Free the orphan record */ - bno = rr->rr_rrec.rc_startblock - XFS_REFC_COW_START; - fsb = XFS_AGB_TO_FSB(mp, pag->pag_agno, bno); - xfs_refcount_free_cow_extent(tp, false, fsb, + bno = rr->rr_rrec.rc_startblock - cow_start; + fsb = isrt ? bno : XFS_AGB_TO_FSB(mp, pag->pag_agno, bno); + xfs_refcount_free_cow_extent(tp, isrt, fsb, rr->rr_rrec.rc_blockcount); /* Free the block. */ xfs_free_extent_later(tp, fsb, rr->rr_rrec.rc_blockcount, NULL, - 0); + isrt ? XFS_FREE_EXTENT_REALTIME : 0); error = xfs_trans_commit(tp); if (error) |