diff options
author | Darrick J. Wong <djwong@kernel.org> | 2021-09-01 11:16:52 -0700 |
---|---|---|
committer | Darrick J. Wong <djwong@kernel.org> | 2021-10-22 16:41:02 -0700 |
commit | 4a180c6e2d18b683b35fa9c4f2612263760b9567 (patch) | |
tree | e276143a8121d48d54e34956503603a8fb2090ea | |
parent | 5749ea123c075503d41acd30fa1a3638f93434a5 (diff) |
xfs: wire up rmap map and unmap to the realtime rmapbt
Connect the map and unmap reverse-mapping operations to the realtime
rmapbt via the deferred operation callbacks. This enables us to
perform rmap operations against the correct btree.
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
-rw-r--r-- | fs/xfs/libxfs/xfs_rmap.c | 81 | ||||
-rw-r--r-- | fs/xfs/xfs_rtalloc.c | 9 | ||||
-rw-r--r-- | fs/xfs/xfs_rtalloc.h | 4 |
3 files changed, 64 insertions, 30 deletions
diff --git a/fs/xfs/libxfs/xfs_rmap.c b/fs/xfs/libxfs/xfs_rmap.c index 5c1672d3332c..cc5969e8c8be 100644 --- a/fs/xfs/libxfs/xfs_rmap.c +++ b/fs/xfs/libxfs/xfs_rmap.c @@ -24,6 +24,8 @@ #include "xfs_inode.h" #include "xfs_ag.h" #include "xfs_health.h" +#include "xfs_rtrmap_btree.h" +#include "xfs_rtalloc.h" /* Return the maximum length of an rmap record. */ static xfs_filblks_t @@ -2445,16 +2447,31 @@ xfs_rmap_finish_one_cleanup( struct xfs_btree_cur *rcur, int error) { - struct xfs_buf *agbp; + struct xfs_buf *agbp = NULL; if (rcur == NULL) return; - agbp = rcur->bc_ag.agbp; + if (rcur->bc_btnum == XFS_BTNUM_RMAP) + agbp = rcur->bc_ag.agbp; xfs_btree_del_cursor(rcur, error); - if (error) + if (error && agbp) xfs_trans_brelse(tp, agbp); } +/* Does this btree cursor match the given AG? */ +static inline bool +xfs_rmap_is_wrong_cursor( + struct xfs_btree_cur *cur, + struct xfs_perag *pag) +{ + if (!pag) { + /* finishing a realtime rmap */ + return cur->bc_btnum != XFS_BTNUM_RTRMAP; + } + + return cur->bc_ag.pag != pag; +} + /* * Process one of the deferred rmap operations. We pass back the * btree cursor to maintain our lock on the rmapbt between calls. @@ -2468,26 +2485,26 @@ xfs_rmap_finish_one( struct xfs_rmap_intent *ri, struct xfs_btree_cur **pcur) { + struct xfs_owner_info oinfo; struct xfs_mount *mp = tp->t_mountp; struct xfs_perag *pag; struct xfs_btree_cur *rcur; struct xfs_buf *agbp = NULL; - int error = 0; - struct xfs_owner_info oinfo; xfs_fsblock_t bno; bool unwritten; + int error = 0; + + trace_xfs_rmap_deferred(mp, ri); if (ri->ri_realtime) { - /* coming in a subsequent patch */ - ASSERT(0); - return -EFSCORRUPTED; + pag = NULL; + bno = ri->ri_bmap.br_startblock; + } else { + pag = xfs_perag_get(mp, + XFS_FSB_TO_AGNO(mp, ri->ri_bmap.br_startblock)); + bno = XFS_FSB_TO_AGBNO(mp, ri->ri_bmap.br_startblock); } - pag = xfs_perag_get(mp, XFS_FSB_TO_AGNO(mp, ri->ri_bmap.br_startblock)); - bno = XFS_FSB_TO_AGBNO(mp, ri->ri_bmap.br_startblock); - - trace_xfs_rmap_deferred(mp, ri); - if (XFS_TEST_ERROR(false, mp, XFS_ERRTAG_RMAP_FINISH_ONE)) { error = -EIO; goto out_drop; @@ -2498,33 +2515,38 @@ xfs_rmap_finish_one( * the startblock, get one now. */ rcur = *pcur; - if (rcur != NULL && rcur->bc_ag.pag != pag) { + if (rcur != NULL && xfs_rmap_is_wrong_cursor(rcur, pag)) { xfs_rmap_finish_one_cleanup(tp, rcur, 0); rcur = NULL; *pcur = NULL; } if (rcur == NULL) { - /* - * Refresh the freelist before we start changing the - * rmapbt, because a shape change could cause us to - * allocate blocks. - */ - error = xfs_free_extent_fix_freelist(tp, pag, &agbp); - if (error) - goto out_drop; - if (XFS_IS_CORRUPT(tp->t_mountp, !agbp)) { - error = -EFSCORRUPTED; - goto out_drop; - } + if (ri->ri_realtime) { + xfs_rtlock(tp, mp, XFS_RTLOCK_RMAP); + rcur = xfs_rtrmapbt_init_cursor(mp, tp, mp->m_rrmapip); + rcur->bc_ino.flags = 0; + } else { + /* + * Refresh the freelist before we start changing the + * rmapbt, because a shape change could cause us to + * allocate blocks. + */ + error = xfs_free_extent_fix_freelist(tp, pag, &agbp); + if (error) + goto out_drop; + if (XFS_IS_CORRUPT(tp->t_mountp, !agbp)) { + error = -EFSCORRUPTED; + goto out_drop; + } - rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag); + rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag); + } } *pcur = rcur; xfs_rmap_ino_owner(&oinfo, ri->ri_owner, ri->ri_whichfork, ri->ri_bmap.br_startoff); unwritten = ri->ri_bmap.br_state == XFS_EXT_UNWRITTEN; - bno = XFS_FSB_TO_AGBNO(rcur->bc_mp, ri->ri_bmap.br_startblock); switch (ri->ri_type) { case XFS_RMAP_ALLOC: @@ -2558,7 +2580,8 @@ xfs_rmap_finish_one( error = -EFSCORRUPTED; } out_drop: - xfs_perag_put(pag); + if (pag) + xfs_perag_put(pag); return error; } diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index ce135c2e2054..ebdb604e795e 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -1639,6 +1639,12 @@ xfs_rtlock( if (tp) xfs_trans_ijoin(tp, mp->m_rsumip, XFS_ILOCK_EXCL); } + + if ((lock_flags & XFS_RTLOCK_RMAP) && mp->m_rrmapip) { + xfs_ilock(mp->m_rrmapip, XFS_ILOCK_EXCL); + if (tp) + xfs_trans_ijoin(tp, mp->m_rrmapip, XFS_ILOCK_EXCL); + } } /* Unlock the realtime metadata inodes. */ @@ -1653,4 +1659,7 @@ xfs_rtunlock( xfs_iunlock(mp->m_rsumip, XFS_ILOCK_EXCL); xfs_iunlock(mp->m_rbmip, XFS_ILOCK_EXCL); } + + if ((lock_flags & XFS_RTLOCK_RMAP) && mp->m_rrmapip) + xfs_iunlock(mp->m_rrmapip, XFS_ILOCK_EXCL); } diff --git a/fs/xfs/xfs_rtalloc.h b/fs/xfs/xfs_rtalloc.h index 326f13ef6890..2138e2473732 100644 --- a/fs/xfs/xfs_rtalloc.h +++ b/fs/xfs/xfs_rtalloc.h @@ -147,7 +147,9 @@ int xfs_rtfile_convert_unwritten(struct xfs_inode *ip, loff_t pos, uint64_t len); #define XFS_RTLOCK_ALLOC (1 << 0) /* rt allocation */ -#define XFS_RTLOCK_ALL (XFS_RTLOCK_ALLOC) +#define XFS_RTLOCK_RMAP (1 << 1) /* rmap operations */ +#define XFS_RTLOCK_ALL (XFS_RTLOCK_ALLOC | \ + XFS_RTLOCK_RMAP) void xfs_rtlock(struct xfs_trans *tp, struct xfs_mount *mp, unsigned int rtlock_flags); |