diff options
author | Darrick J. Wong <djwong@kernel.org> | 2021-09-01 11:18:10 -0700 |
---|---|---|
committer | Darrick J. Wong <djwong@kernel.org> | 2021-10-22 16:41:07 -0700 |
commit | bcaa2ad8d03fbf99ff2b9dfc5961f68d211ca53e (patch) | |
tree | c5b0da9349488418571fea4e5c08f6f61258febf /fs/xfs/libxfs | |
parent | bd0102e36dd490db38382ec121cdbd31ca0d8c83 (diff) |
xfs: add a realtime flag to the refcount update log redo items
Extend the refcount update (CUI) log items with a new realtime flag that
indicates that the updates apply against the realtime refcountbt. We'll
wire up the actual refcount code later.
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Diffstat (limited to 'fs/xfs/libxfs')
-rw-r--r-- | fs/xfs/libxfs/xfs_bmap.c | 10 | ||||
-rw-r--r-- | fs/xfs/libxfs/xfs_log_format.h | 5 | ||||
-rw-r--r-- | fs/xfs/libxfs/xfs_refcount.c | 116 | ||||
-rw-r--r-- | fs/xfs/libxfs/xfs_refcount.h | 13 |
4 files changed, 98 insertions, 46 deletions
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index ef7772b35e6c..ed3017536fd3 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -4493,8 +4493,9 @@ xfs_bmapi_write( * the refcount btree for orphan recovery. */ if (whichfork == XFS_COW_FORK) - xfs_refcount_alloc_cow_extent(tp, bma.blkno, - bma.length); + xfs_refcount_alloc_cow_extent(tp, + XFS_IS_REALTIME_INODE(ip), + bma.blkno, bma.length); } /* Deal with the allocated space we found. */ @@ -4655,7 +4656,8 @@ xfs_bmapi_convert_delalloc( *seq = READ_ONCE(ifp->if_seq); if (whichfork == XFS_COW_FORK) - xfs_refcount_alloc_cow_extent(tp, bma.blkno, bma.length); + xfs_refcount_alloc_cow_extent(tp, XFS_IS_REALTIME_INODE(ip), + bma.blkno, bma.length); error = xfs_bmap_btree_to_extents(tp, ip, bma.cur, &bma.logflags, whichfork); @@ -5296,7 +5298,7 @@ xfs_bmap_del_extent_real( */ if (want_free) { if (xfs_is_reflink_inode(ip) && whichfork == XFS_DATA_FORK) { - xfs_refcount_decrease_extent(tp, del); + xfs_refcount_decrease_extent(tp, isrt, del); } else { unsigned int flags = 0; diff --git a/fs/xfs/libxfs/xfs_log_format.h b/fs/xfs/libxfs/xfs_log_format.h index 294a6fbe47c8..f28b96fef508 100644 --- a/fs/xfs/libxfs/xfs_log_format.h +++ b/fs/xfs/libxfs/xfs_log_format.h @@ -716,7 +716,10 @@ struct xfs_phys_extent { /* Type codes are taken directly from enum xfs_refcount_intent_type. */ #define XFS_REFCOUNT_EXTENT_TYPE_MASK 0xFF -#define XFS_REFCOUNT_EXTENT_FLAGS (XFS_REFCOUNT_EXTENT_TYPE_MASK) +#define XFS_REFCOUNT_EXTENT_REALTIME (1U << 31) + +#define XFS_REFCOUNT_EXTENT_FLAGS (XFS_REFCOUNT_EXTENT_TYPE_MASK | \ + XFS_REFCOUNT_EXTENT_REALTIME) /* * This is the structure used to lay out a cui log item in the diff --git a/fs/xfs/libxfs/xfs_refcount.c b/fs/xfs/libxfs/xfs_refcount.c index 6a5cf5cdfa3e..32b70f4e9dc8 100644 --- a/fs/xfs/libxfs/xfs_refcount.c +++ b/fs/xfs/libxfs/xfs_refcount.c @@ -24,6 +24,7 @@ #include "xfs_rmap.h" #include "xfs_ag.h" #include "xfs_health.h" +#include "xfs_rtalloc.h" /* Allowable refcount adjustment amounts. */ enum xfs_refc_adjust_op { @@ -983,6 +984,27 @@ xfs_refcount_still_have_space( xrefc_btree_state(cur)->nr_ops * XFS_REFCOUNT_ITEM_OVERHEAD; } +/* Schedule an extent free. */ +static void +xrefc_free_extent( + struct xfs_btree_cur *cur, + struct xfs_refcount_irec *rec) +{ + xfs_fsblock_t fsbno; + unsigned int flags = 0; + + if (cur->bc_btnum == XFS_BTNUM_RTREFC) { + flags |= XFS_FREE_EXTENT_REALTIME; + fsbno = rec->rc_startblock; + } else { + fsbno = XFS_AGB_TO_FSB(cur->bc_mp, cur->bc_ag.pag->pag_agno, + rec->rc_startblock); + } + + xfs_free_extent_later(cur->bc_tp, fsbno, rec->rc_blockcount, NULL, + flags); +} + /* * Adjust the refcounts of middle extents. At this point we should have * split extents that crossed the adjustment range; merged with adjacent @@ -999,7 +1021,6 @@ xfs_refcount_adjust_extents( struct xfs_refcount_irec ext, tmp; int error; int found_rec, found_tmp; - xfs_fsblock_t fsbno; /* Merging did all the work already. */ if (*len == 0) @@ -1048,11 +1069,7 @@ xfs_refcount_adjust_extents( goto out_error; } } else { - fsbno = XFS_AGB_TO_FSB(cur->bc_mp, - cur->bc_ag.pag->pag_agno, - tmp.rc_startblock); - xfs_free_extent_later(cur->bc_tp, fsbno, - tmp.rc_blockcount, NULL, 0); + xrefc_free_extent(cur, &tmp); } (*bno) += tmp.rc_blockcount; @@ -1092,11 +1109,7 @@ xfs_refcount_adjust_extents( } goto advloop; } else { - fsbno = XFS_AGB_TO_FSB(cur->bc_mp, - cur->bc_ag.pag->pag_agno, - ext.rc_startblock); - xfs_free_extent_later(cur->bc_tp, fsbno, - ext.rc_blockcount, NULL, 0); + xrefc_free_extent(cur, &ext); } skip: @@ -1182,16 +1195,31 @@ xfs_refcount_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_REFC) + agbp = rcur->bc_ag.agbp; xfs_btree_del_cursor(rcur, error); - if (error) + if (agbp) xfs_trans_brelse(tp, agbp); } +/* Does this btree cursor match the given AG? */ +static inline bool +xfs_refcount_is_wrong_cursor( + struct xfs_btree_cur *cur, + struct xfs_perag *pag) +{ + if (!pag) { + /* finishing a realtime refcount */ + return cur->bc_btnum != XFS_BTNUM_RTREFC; + } + + return cur->bc_ag.pag != pag; +} + /* * Process one of the deferred refcount operations. We pass back the * btree cursor to maintain our lock on the btree between calls. @@ -1216,11 +1244,16 @@ xfs_refcount_finish_one( int shape_changes = 0; int error = 0; - pag = xfs_perag_get(mp, XFS_FSB_TO_AGNO(mp, ri->ri_startblock)); - bno = XFS_FSB_TO_AGBNO(mp, ri->ri_startblock); - trace_xfs_refcount_deferred(mp, ri); + if (ri->ri_realtime) { + pag = NULL; + bno = ri->ri_startblock; + } else { + pag = xfs_perag_get(mp, XFS_FSB_TO_AGNO(mp, ri->ri_startblock)); + bno = XFS_FSB_TO_AGBNO(mp, ri->ri_startblock); + } + if (XFS_TEST_ERROR(false, mp, XFS_ERRTAG_REFCOUNT_FINISH_ONE)) { error = -EIO; goto out_drop; @@ -1231,7 +1264,7 @@ xfs_refcount_finish_one( * the startblock, get one now. */ rcur = *pcur; - if (rcur != NULL && rcur->bc_ag.pag != pag) { + if (rcur != NULL && xfs_refcount_is_wrong_cursor(rcur, pag)) { nr_ops = xrefc_btree_state(rcur)->nr_ops; shape_changes = xrefc_btree_state(rcur)->shape_changes; xfs_refcount_finish_one_cleanup(tp, rcur, 0); @@ -1239,12 +1272,18 @@ xfs_refcount_finish_one( *pcur = NULL; } if (rcur == NULL) { - error = xfs_alloc_read_agf(tp->t_mountp, tp, pag->pag_agno, - XFS_ALLOC_FLAG_FREEING, &agbp); - if (error) - goto out_drop; + if (ri->ri_realtime) { + /* coming in a later patch */ + ASSERT(0); + return -EFSCORRUPTED; + } else { + error = xfs_alloc_read_agf(mp, tp, pag->pag_agno, + XFS_ALLOC_FLAG_FREEING, &agbp); + if (error) + goto out_drop; - rcur = xfs_refcountbt_init_cursor(mp, tp, agbp, pag); + rcur = xfs_refcountbt_init_cursor(mp, tp, agbp, pag); + } xrefc_btree_state(rcur)->nr_ops = nr_ops; xrefc_btree_state(rcur)->shape_changes = shape_changes; } @@ -1255,16 +1294,16 @@ xfs_refcount_finish_one( error = xfs_refcount_adjust(rcur, bno, ri->ri_blockcount, &new_bno, &new_len, XFS_REFCOUNT_ADJUST_INCREASE); - ri->ri_startblock = XFS_AGB_TO_FSB(mp, pag->pag_agno, - new_bno); + ri->ri_startblock = ri->ri_realtime ? new_bno : + XFS_AGB_TO_FSB(mp, pag->pag_agno, new_bno); ri->ri_blockcount = new_len; break; case XFS_REFCOUNT_DECREASE: error = xfs_refcount_adjust(rcur, bno, ri->ri_blockcount, &new_bno, &new_len, XFS_REFCOUNT_ADJUST_DECREASE); - ri->ri_startblock = XFS_AGB_TO_FSB(mp, pag->pag_agno, - new_bno); + ri->ri_startblock = ri->ri_realtime ? new_bno : + XFS_AGB_TO_FSB(mp, pag->pag_agno, new_bno); ri->ri_blockcount = new_len; break; case XFS_REFCOUNT_ALLOC_COW: @@ -1284,7 +1323,8 @@ xfs_refcount_finish_one( if (!error && ri->ri_blockcount > 0) trace_xfs_refcount_finish_one_leftover(mp, ri); out_drop: - xfs_perag_put(pag); + if (pag) + xfs_perag_put(pag); return error; } @@ -1295,6 +1335,7 @@ static void __xfs_refcount_add( struct xfs_trans *tp, enum xfs_refcount_intent_type type, + bool isrt, xfs_fsblock_t startblock, xfs_filblks_t blockcount) { @@ -1306,6 +1347,7 @@ __xfs_refcount_add( ri->ri_type = type; ri->ri_startblock = startblock; ri->ri_blockcount = blockcount; + ri->ri_realtime = isrt; trace_xfs_refcount_defer(tp->t_mountp, ri); xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_REFCOUNT, &ri->ri_list); @@ -1317,12 +1359,13 @@ __xfs_refcount_add( void xfs_refcount_increase_extent( struct xfs_trans *tp, + bool isrt, struct xfs_bmbt_irec *PREV) { if (!xfs_has_reflink(tp->t_mountp)) return; - __xfs_refcount_add(tp, XFS_REFCOUNT_INCREASE, PREV->br_startblock, + __xfs_refcount_add(tp, XFS_REFCOUNT_INCREASE, isrt, PREV->br_startblock, PREV->br_blockcount); } @@ -1332,12 +1375,13 @@ xfs_refcount_increase_extent( void xfs_refcount_decrease_extent( struct xfs_trans *tp, + bool isrt, struct xfs_bmbt_irec *PREV) { if (!xfs_has_reflink(tp->t_mountp)) return; - __xfs_refcount_add(tp, XFS_REFCOUNT_DECREASE, PREV->br_startblock, + __xfs_refcount_add(tp, XFS_REFCOUNT_DECREASE, isrt, PREV->br_startblock, PREV->br_blockcount); } @@ -1678,6 +1722,7 @@ __xfs_refcount_cow_free( void xfs_refcount_alloc_cow_extent( struct xfs_trans *tp, + bool isrt, xfs_fsblock_t fsb, xfs_filblks_t len) { @@ -1686,16 +1731,17 @@ xfs_refcount_alloc_cow_extent( if (!xfs_has_reflink(mp)) return; - __xfs_refcount_add(tp, XFS_REFCOUNT_ALLOC_COW, fsb, len); + __xfs_refcount_add(tp, XFS_REFCOUNT_ALLOC_COW, isrt, fsb, len); /* Add rmap entry */ - xfs_rmap_alloc_extent(tp, false, fsb, len, XFS_RMAP_OWN_COW); + xfs_rmap_alloc_extent(tp, isrt, fsb, len, XFS_RMAP_OWN_COW); } /* Forget a CoW staging event in the refcount btree. */ void xfs_refcount_free_cow_extent( struct xfs_trans *tp, + bool isrt, xfs_fsblock_t fsb, xfs_filblks_t len) { @@ -1705,8 +1751,8 @@ xfs_refcount_free_cow_extent( return; /* Remove rmap entry */ - xfs_rmap_free_extent(tp, false, fsb, len, XFS_RMAP_OWN_COW); - __xfs_refcount_add(tp, XFS_REFCOUNT_FREE_COW, fsb, len); + xfs_rmap_free_extent(tp, isrt, fsb, len, XFS_RMAP_OWN_COW); + __xfs_refcount_add(tp, XFS_REFCOUNT_FREE_COW, isrt, fsb, len); } struct xfs_refcount_recovery { @@ -1806,7 +1852,7 @@ xfs_refcount_recover_cow_leftovers( /* 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, fsb, + xfs_refcount_free_cow_extent(tp, false, fsb, rr->rr_rrec.rc_blockcount); /* Free the block. */ diff --git a/fs/xfs/libxfs/xfs_refcount.h b/fs/xfs/libxfs/xfs_refcount.h index fe64ef0dc469..15d59693ee67 100644 --- a/fs/xfs/libxfs/xfs_refcount.h +++ b/fs/xfs/libxfs/xfs_refcount.h @@ -40,11 +40,12 @@ struct xfs_refcount_intent { enum xfs_refcount_intent_type ri_type; xfs_fsblock_t ri_startblock; xfs_filblks_t ri_blockcount; + bool ri_realtime; }; -void xfs_refcount_increase_extent(struct xfs_trans *tp, +void xfs_refcount_increase_extent(struct xfs_trans *tp, bool isrt, struct xfs_bmbt_irec *irec); -void xfs_refcount_decrease_extent(struct xfs_trans *tp, +void xfs_refcount_decrease_extent(struct xfs_trans *tp, bool isrt, struct xfs_bmbt_irec *irec); extern void xfs_refcount_finish_one_cleanup(struct xfs_trans *tp, @@ -56,10 +57,10 @@ extern int xfs_refcount_find_shared(struct xfs_btree_cur *cur, xfs_fsblock_t bno, xfs_filblks_t aglen, xfs_fsblock_t *fbno, xfs_filblks_t *flen, bool find_end_of_shared); -void xfs_refcount_alloc_cow_extent(struct xfs_trans *tp, xfs_fsblock_t fsb, - xfs_filblks_t len); -void xfs_refcount_free_cow_extent(struct xfs_trans *tp, xfs_fsblock_t fsb, - xfs_filblks_t len); +void xfs_refcount_alloc_cow_extent(struct xfs_trans *tp, bool isrt, + xfs_fsblock_t fsb, xfs_filblks_t len); +void xfs_refcount_free_cow_extent(struct xfs_trans *tp, bool isrt, + xfs_fsblock_t fsb, xfs_filblks_t len); extern int xfs_refcount_recover_cow_leftovers(struct xfs_mount *mp, struct xfs_perag *pag); |