xfs: convert the ifork reap code to use xreap_state

Convert the file fork reaping code to use struct xreap_state so that we
can reuse the dynamic state tracking code.

Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
pull/1354/merge
Darrick J. Wong 2025-04-08 16:14:31 -07:00
parent 82e374405e
commit ef930cc371
1 changed files with 46 additions and 32 deletions

View File

@ -91,9 +91,21 @@
struct xreap_state {
struct xfs_scrub *sc;
/* Reverse mapping owner and metadata reservation type. */
const struct xfs_owner_info *oinfo;
enum xfs_ag_resv_type resv;
union {
struct {
/*
* For AG blocks, this is reverse mapping owner and
* metadata reservation type.
*/
const struct xfs_owner_info *oinfo;
enum xfs_ag_resv_type resv;
};
struct {
/* For file blocks, this is the inode and fork. */
struct xfs_inode *ip;
int whichfork;
};
};
/* Number of invalidated buffers logged to the current transaction. */
unsigned int nr_binval;
@ -965,13 +977,12 @@ xrep_reap_metadir_fsblocks(
*/
STATIC int
xreap_bmapi_select(
struct xfs_scrub *sc,
struct xfs_inode *ip,
int whichfork,
struct xreap_state *rs,
struct xfs_bmbt_irec *imap,
bool *crosslinked)
{
struct xfs_owner_info oinfo;
struct xfs_scrub *sc = rs->sc;
struct xfs_btree_cur *cur;
xfs_filblks_t len = 1;
xfs_agblock_t bno;
@ -985,7 +996,8 @@ xreap_bmapi_select(
cur = xfs_rmapbt_init_cursor(sc->mp, sc->tp, sc->sa.agf_bp,
sc->sa.pag);
xfs_rmap_ino_owner(&oinfo, ip->i_ino, whichfork, imap->br_startoff);
xfs_rmap_ino_owner(&oinfo, rs->ip->i_ino, rs->whichfork,
imap->br_startoff);
error = xfs_rmap_has_other_keys(cur, agbno, 1, &oinfo, crosslinked);
if (error)
goto out_cur;
@ -1048,21 +1060,19 @@ xreap_buf_loggable(
*/
STATIC int
xreap_bmapi_binval(
struct xfs_scrub *sc,
struct xfs_inode *ip,
int whichfork,
struct xreap_state *rs,
struct xfs_bmbt_irec *imap)
{
struct xfs_scrub *sc = rs->sc;
struct xfs_mount *mp = sc->mp;
struct xfs_perag *pag = sc->sa.pag;
int bmap_flags = xfs_bmapi_aflag(whichfork);
int bmap_flags = xfs_bmapi_aflag(rs->whichfork);
xfs_fileoff_t off;
xfs_fileoff_t max_off;
xfs_extlen_t scan_blocks;
xfs_agblock_t bno;
xfs_agblock_t agbno;
xfs_agblock_t agbno_next;
unsigned int invalidated = 0;
int error;
/*
@ -1089,7 +1099,7 @@ xreap_bmapi_binval(
struct xfs_bmbt_irec hmap;
int nhmaps = 1;
error = xfs_bmapi_read(ip, off, max_off - off, &hmap,
error = xfs_bmapi_read(rs->ip, off, max_off - off, &hmap,
&nhmaps, bmap_flags);
if (error)
return error;
@ -1130,14 +1140,13 @@ xreap_bmapi_binval(
xfs_buf_stale(bp);
xfs_buf_relse(bp);
}
invalidated++;
/*
* Stop invalidating if we've hit the limit; we should
* still have enough reservation left to free however
* much of the mapping we've seen so far.
* far we've gotten.
*/
if (invalidated > XREAP_MAX_BINVAL) {
if (!xreap_inc_binval(rs)) {
imap->br_blockcount = agbno_next - bno;
goto out;
}
@ -1159,12 +1168,11 @@ out:
*/
STATIC int
xrep_reap_bmapi_iter(
struct xfs_scrub *sc,
struct xfs_inode *ip,
int whichfork,
struct xreap_state *rs,
struct xfs_bmbt_irec *imap,
bool crosslinked)
{
struct xfs_scrub *sc = rs->sc;
int error;
if (crosslinked) {
@ -1185,10 +1193,10 @@ xrep_reap_bmapi_iter(
* deferred log intents in this function to control the exact
* sequence of metadata updates.
*/
xfs_bmap_unmap_extent(sc->tp, ip, whichfork, imap);
xfs_trans_mod_dquot_byino(sc->tp, ip, XFS_TRANS_DQ_BCOUNT,
xfs_bmap_unmap_extent(sc->tp, rs->ip, rs->whichfork, imap);
xfs_trans_mod_dquot_byino(sc->tp, rs->ip, XFS_TRANS_DQ_BCOUNT,
-(int64_t)imap->br_blockcount);
xfs_rmap_unmap_extent(sc->tp, ip, whichfork, imap);
xfs_rmap_unmap_extent(sc->tp, rs->ip, rs->whichfork, imap);
return 0;
}
@ -1209,7 +1217,7 @@ xrep_reap_bmapi_iter(
* transaction is full of logged buffer invalidations, so we need to
* return early so that we can roll and retry.
*/
error = xreap_bmapi_binval(sc, ip, whichfork, imap);
error = xreap_bmapi_binval(rs, imap);
if (error || imap->br_blockcount == 0)
return error;
@ -1218,8 +1226,8 @@ xrep_reap_bmapi_iter(
* intents in this function to control the exact sequence of metadata
* updates.
*/
xfs_bmap_unmap_extent(sc->tp, ip, whichfork, imap);
xfs_trans_mod_dquot_byino(sc->tp, ip, XFS_TRANS_DQ_BCOUNT,
xfs_bmap_unmap_extent(sc->tp, rs->ip, rs->whichfork, imap);
xfs_trans_mod_dquot_byino(sc->tp, rs->ip, XFS_TRANS_DQ_BCOUNT,
-(int64_t)imap->br_blockcount);
return xfs_free_extent_later(sc->tp, imap->br_startblock,
imap->br_blockcount, NULL, XFS_AG_RESV_NONE,
@ -1232,18 +1240,17 @@ xrep_reap_bmapi_iter(
*/
STATIC int
xreap_ifork_extent(
struct xfs_scrub *sc,
struct xfs_inode *ip,
int whichfork,
struct xreap_state *rs,
struct xfs_bmbt_irec *imap)
{
struct xfs_scrub *sc = rs->sc;
xfs_agnumber_t agno;
bool crosslinked;
int error;
ASSERT(sc->sa.pag == NULL);
trace_xreap_ifork_extent(sc, ip, whichfork, imap);
trace_xreap_ifork_extent(sc, rs->ip, rs->whichfork, imap);
agno = XFS_FSB_TO_AGNO(sc->mp, imap->br_startblock);
sc->sa.pag = xfs_perag_get(sc->mp, agno);
@ -1258,11 +1265,11 @@ xreap_ifork_extent(
* Decide the fate of the blocks at the beginning of the mapping, then
* update the mapping to use it with the unmap calls.
*/
error = xreap_bmapi_select(sc, ip, whichfork, imap, &crosslinked);
error = xreap_bmapi_select(rs, imap, &crosslinked);
if (error)
goto out_agf;
error = xrep_reap_bmapi_iter(sc, ip, whichfork, imap, crosslinked);
error = xrep_reap_bmapi_iter(rs, imap, crosslinked);
if (error)
goto out_agf;
@ -1286,6 +1293,12 @@ xrep_reap_ifork(
struct xfs_inode *ip,
int whichfork)
{
struct xreap_state rs = {
.sc = sc,
.ip = ip,
.whichfork = whichfork,
.max_binval = XREAP_MAX_BINVAL,
};
xfs_fileoff_t off = 0;
int bmap_flags = xfs_bmapi_aflag(whichfork);
int error;
@ -1313,13 +1326,14 @@ xrep_reap_ifork(
* can in a single transaction.
*/
if (xfs_bmap_is_real_extent(&imap)) {
error = xreap_ifork_extent(sc, ip, whichfork, &imap);
error = xreap_ifork_extent(&rs, &imap);
if (error)
return error;
error = xfs_defer_finish(&sc->tp);
if (error)
return error;
xreap_defer_finish_reset(&rs);
}
off = imap.br_startoff + imap.br_blockcount;