summaryrefslogtreecommitdiff
path: root/fs/xfs/libxfs
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@kernel.org>2021-09-01 11:18:45 -0700
committerDarrick J. Wong <djwong@kernel.org>2021-10-22 16:41:09 -0700
commit2407ce4b1bad9c3846e3351f49718eea95e8cda5 (patch)
tree119cd3994b15db30d39d5955a7cb2636fcff1c15 /fs/xfs/libxfs
parent0e56e9ca305bfe65f4fb2c8889636f07e4a20a4c (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.c39
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)