summaryrefslogtreecommitdiff
path: root/fs/xfs/libxfs
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@kernel.org>2021-09-01 11:18:10 -0700
committerDarrick J. Wong <djwong@kernel.org>2021-10-22 16:41:07 -0700
commitbcaa2ad8d03fbf99ff2b9dfc5961f68d211ca53e (patch)
treec5b0da9349488418571fea4e5c08f6f61258febf /fs/xfs/libxfs
parentbd0102e36dd490db38382ec121cdbd31ca0d8c83 (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.c10
-rw-r--r--fs/xfs/libxfs/xfs_log_format.h5
-rw-r--r--fs/xfs/libxfs/xfs_refcount.c116
-rw-r--r--fs/xfs/libxfs/xfs_refcount.h13
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);