xfs: make intent items take a perag reference [v24.5]
Now that we've cleaned up some code warts in the deferred work item processing code, let's make intent items take an active perag reference from their creation until they are finally freed by the defer ops machinery. This change facilitates the scrub drain in the next patchset and will make it easier for the future AG removal code to detect a busy AG in need of quiescing. Signed-off-by: Darrick J. Wong <djwong@kernel.org> -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQQ2qTKExjcn+O1o2YRKO3ySh0YRpgUCZDYdnAAKCRBKO3ySh0YR poBzAP9+tx/LNTZeLtmjj/d7tVLMm2/f8LPyhDmkF85JWnjknwEAnLQxkqRMfF9i ah3ACAZ30o+Mp7Qe6tnYVIdOSD2xCAM= =mRAy -----END PGP SIGNATURE----- Merge tag 'intents-perag-refs-6.4_2023-04-11' of git://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux into guilt/xfs-for-next xfs: make intent items take a perag reference [v24.5] Now that we've cleaned up some code warts in the deferred work item processing code, let's make intent items take an active perag reference from their creation until they are finally freed by the defer ops machinery. This change facilitates the scrub drain in the next patchset and will make it easier for the future AG removal code to detect a busy AG in need of quiescing. Signed-off-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Dave Chinner <david@fromorbit.com>
This commit is contained in:
commit
826053db98
@ -1043,10 +1043,8 @@ xfs_ag_extend_space(
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
error = xfs_free_extent(tp, XFS_AGB_TO_FSB(pag->pag_mount, pag->pag_agno,
|
||||
be32_to_cpu(agf->agf_length) - len),
|
||||
len, &XFS_RMAP_OINFO_SKIP_UPDATE,
|
||||
XFS_AG_RESV_NONE);
|
||||
error = xfs_free_extent(tp, pag, be32_to_cpu(agf->agf_length) - len,
|
||||
len, &XFS_RMAP_OINFO_SKIP_UPDATE, XFS_AG_RESV_NONE);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
|
@ -2405,6 +2405,7 @@ xfs_defer_agfl_block(
|
||||
|
||||
trace_xfs_agfl_free_defer(mp, agno, 0, agbno, 1);
|
||||
|
||||
xfs_extent_free_get_group(mp, xefi);
|
||||
xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_AGFL_FREE, &xefi->xefi_list);
|
||||
}
|
||||
|
||||
@ -2421,8 +2422,8 @@ __xfs_free_extent_later(
|
||||
bool skip_discard)
|
||||
{
|
||||
struct xfs_extent_free_item *xefi;
|
||||
#ifdef DEBUG
|
||||
struct xfs_mount *mp = tp->t_mountp;
|
||||
#ifdef DEBUG
|
||||
xfs_agnumber_t agno;
|
||||
xfs_agblock_t agbno;
|
||||
|
||||
@ -2456,9 +2457,11 @@ __xfs_free_extent_later(
|
||||
} else {
|
||||
xefi->xefi_owner = XFS_RMAP_OWN_NULL;
|
||||
}
|
||||
trace_xfs_bmap_free_defer(tp->t_mountp,
|
||||
trace_xfs_bmap_free_defer(mp,
|
||||
XFS_FSB_TO_AGNO(tp->t_mountp, bno), 0,
|
||||
XFS_FSB_TO_AGBNO(tp->t_mountp, bno), len);
|
||||
|
||||
xfs_extent_free_get_group(mp, xefi);
|
||||
xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_FREE, &xefi->xefi_list);
|
||||
}
|
||||
|
||||
@ -3596,7 +3599,8 @@ xfs_free_extent_fix_freelist(
|
||||
int
|
||||
__xfs_free_extent(
|
||||
struct xfs_trans *tp,
|
||||
xfs_fsblock_t bno,
|
||||
struct xfs_perag *pag,
|
||||
xfs_agblock_t agbno,
|
||||
xfs_extlen_t len,
|
||||
const struct xfs_owner_info *oinfo,
|
||||
enum xfs_ag_resv_type type,
|
||||
@ -3604,12 +3608,9 @@ __xfs_free_extent(
|
||||
{
|
||||
struct xfs_mount *mp = tp->t_mountp;
|
||||
struct xfs_buf *agbp;
|
||||
xfs_agnumber_t agno = XFS_FSB_TO_AGNO(mp, bno);
|
||||
xfs_agblock_t agbno = XFS_FSB_TO_AGBNO(mp, bno);
|
||||
struct xfs_agf *agf;
|
||||
int error;
|
||||
unsigned int busy_flags = 0;
|
||||
struct xfs_perag *pag;
|
||||
|
||||
ASSERT(len != 0);
|
||||
ASSERT(type != XFS_AG_RESV_AGFL);
|
||||
@ -3618,10 +3619,9 @@ __xfs_free_extent(
|
||||
XFS_ERRTAG_FREE_EXTENT))
|
||||
return -EIO;
|
||||
|
||||
pag = xfs_perag_get(mp, agno);
|
||||
error = xfs_free_extent_fix_freelist(tp, pag, &agbp);
|
||||
if (error)
|
||||
goto err;
|
||||
return error;
|
||||
agf = agbp->b_addr;
|
||||
|
||||
if (XFS_IS_CORRUPT(mp, agbno >= mp->m_sb.sb_agblocks)) {
|
||||
@ -3635,20 +3635,18 @@ __xfs_free_extent(
|
||||
goto err_release;
|
||||
}
|
||||
|
||||
error = xfs_free_ag_extent(tp, agbp, agno, agbno, len, oinfo, type);
|
||||
error = xfs_free_ag_extent(tp, agbp, pag->pag_agno, agbno, len, oinfo,
|
||||
type);
|
||||
if (error)
|
||||
goto err_release;
|
||||
|
||||
if (skip_discard)
|
||||
busy_flags |= XFS_EXTENT_BUSY_SKIP_DISCARD;
|
||||
xfs_extent_busy_insert(tp, pag, agbno, len, busy_flags);
|
||||
xfs_perag_put(pag);
|
||||
return 0;
|
||||
|
||||
err_release:
|
||||
xfs_trans_brelse(tp, agbp);
|
||||
err:
|
||||
xfs_perag_put(pag);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -141,7 +141,8 @@ int xfs_alloc_vextent_first_ag(struct xfs_alloc_arg *args,
|
||||
int /* error */
|
||||
__xfs_free_extent(
|
||||
struct xfs_trans *tp, /* transaction pointer */
|
||||
xfs_fsblock_t bno, /* starting block number of extent */
|
||||
struct xfs_perag *pag,
|
||||
xfs_agblock_t agbno,
|
||||
xfs_extlen_t len, /* length of extent */
|
||||
const struct xfs_owner_info *oinfo, /* extent owner */
|
||||
enum xfs_ag_resv_type type, /* block reservation type */
|
||||
@ -150,12 +151,13 @@ __xfs_free_extent(
|
||||
static inline int
|
||||
xfs_free_extent(
|
||||
struct xfs_trans *tp,
|
||||
xfs_fsblock_t bno,
|
||||
struct xfs_perag *pag,
|
||||
xfs_agblock_t agbno,
|
||||
xfs_extlen_t len,
|
||||
const struct xfs_owner_info *oinfo,
|
||||
enum xfs_ag_resv_type type)
|
||||
{
|
||||
return __xfs_free_extent(tp, bno, len, oinfo, type, false);
|
||||
return __xfs_free_extent(tp, pag, agbno, len, oinfo, type, false);
|
||||
}
|
||||
|
||||
int /* error */
|
||||
@ -235,9 +237,13 @@ struct xfs_extent_free_item {
|
||||
uint64_t xefi_owner;
|
||||
xfs_fsblock_t xefi_startblock;/* starting fs block number */
|
||||
xfs_extlen_t xefi_blockcount;/* number of blocks in extent */
|
||||
struct xfs_perag *xefi_pag;
|
||||
unsigned int xefi_flags;
|
||||
};
|
||||
|
||||
void xfs_extent_free_get_group(struct xfs_mount *mp,
|
||||
struct xfs_extent_free_item *xefi);
|
||||
|
||||
#define XFS_EFI_SKIP_DISCARD (1U << 0) /* don't issue discard */
|
||||
#define XFS_EFI_ATTR_FORK (1U << 1) /* freeing attr fork block */
|
||||
#define XFS_EFI_BMBT_BLOCK (1U << 2) /* freeing bmap btree block */
|
||||
|
@ -6081,6 +6081,7 @@ __xfs_bmap_add(
|
||||
bi->bi_whichfork = whichfork;
|
||||
bi->bi_bmap = *bmap;
|
||||
|
||||
xfs_bmap_update_get_group(tp->t_mountp, bi);
|
||||
xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_BMAP, &bi->bi_list);
|
||||
return 0;
|
||||
}
|
||||
|
@ -238,9 +238,13 @@ struct xfs_bmap_intent {
|
||||
enum xfs_bmap_intent_type bi_type;
|
||||
int bi_whichfork;
|
||||
struct xfs_inode *bi_owner;
|
||||
struct xfs_perag *bi_pag;
|
||||
struct xfs_bmbt_irec bi_bmap;
|
||||
};
|
||||
|
||||
void xfs_bmap_update_get_group(struct xfs_mount *mp,
|
||||
struct xfs_bmap_intent *bi);
|
||||
|
||||
int xfs_bmap_finish_one(struct xfs_trans *tp, struct xfs_bmap_intent *bi);
|
||||
void xfs_bmap_map_extent(struct xfs_trans *tp, struct xfs_inode *ip,
|
||||
struct xfs_bmbt_irec *imap);
|
||||
|
@ -156,9 +156,12 @@ __xfs_inobt_free_block(
|
||||
struct xfs_buf *bp,
|
||||
enum xfs_ag_resv_type resv)
|
||||
{
|
||||
xfs_fsblock_t fsbno;
|
||||
|
||||
xfs_inobt_mod_blockcount(cur, -1);
|
||||
return xfs_free_extent(cur->bc_tp,
|
||||
XFS_DADDR_TO_FSB(cur->bc_mp, xfs_buf_daddr(bp)), 1,
|
||||
fsbno = XFS_DADDR_TO_FSB(cur->bc_mp, xfs_buf_daddr(bp));
|
||||
return xfs_free_extent(cur->bc_tp, cur->bc_ag.pag,
|
||||
XFS_FSB_TO_AGBNO(cur->bc_mp, fsbno), 1,
|
||||
&XFS_RMAP_OINFO_INOBT, resv);
|
||||
}
|
||||
|
||||
|
@ -1332,26 +1332,22 @@ xfs_refcount_finish_one(
|
||||
xfs_agblock_t bno;
|
||||
unsigned long nr_ops = 0;
|
||||
int shape_changes = 0;
|
||||
struct xfs_perag *pag;
|
||||
|
||||
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, XFS_FSB_TO_AGNO(mp, ri->ri_startblock),
|
||||
ri->ri_type, XFS_FSB_TO_AGBNO(mp, ri->ri_startblock),
|
||||
ri->ri_blockcount);
|
||||
|
||||
if (XFS_TEST_ERROR(false, mp, XFS_ERRTAG_REFCOUNT_FINISH_ONE)) {
|
||||
error = -EIO;
|
||||
goto out_drop;
|
||||
}
|
||||
if (XFS_TEST_ERROR(false, mp, XFS_ERRTAG_REFCOUNT_FINISH_ONE))
|
||||
return -EIO;
|
||||
|
||||
/*
|
||||
* If we haven't gotten a cursor or the cursor AG doesn't match
|
||||
* the startblock, get one now.
|
||||
*/
|
||||
rcur = *pcur;
|
||||
if (rcur != NULL && rcur->bc_ag.pag != pag) {
|
||||
if (rcur != NULL && rcur->bc_ag.pag != ri->ri_pag) {
|
||||
nr_ops = rcur->bc_ag.refc.nr_ops;
|
||||
shape_changes = rcur->bc_ag.refc.shape_changes;
|
||||
xfs_refcount_finish_one_cleanup(tp, rcur, 0);
|
||||
@ -1359,12 +1355,12 @@ xfs_refcount_finish_one(
|
||||
*pcur = NULL;
|
||||
}
|
||||
if (rcur == NULL) {
|
||||
error = xfs_alloc_read_agf(pag, tp, XFS_ALLOC_FLAG_FREEING,
|
||||
&agbp);
|
||||
error = xfs_alloc_read_agf(ri->ri_pag, tp,
|
||||
XFS_ALLOC_FLAG_FREEING, &agbp);
|
||||
if (error)
|
||||
goto out_drop;
|
||||
return error;
|
||||
|
||||
rcur = xfs_refcountbt_init_cursor(mp, tp, agbp, pag);
|
||||
rcur = xfs_refcountbt_init_cursor(mp, tp, agbp, ri->ri_pag);
|
||||
rcur->bc_ag.refc.nr_ops = nr_ops;
|
||||
rcur->bc_ag.refc.shape_changes = shape_changes;
|
||||
}
|
||||
@ -1375,7 +1371,7 @@ xfs_refcount_finish_one(
|
||||
error = xfs_refcount_adjust(rcur, &bno, &ri->ri_blockcount,
|
||||
XFS_REFCOUNT_ADJUST_INCREASE);
|
||||
if (error)
|
||||
goto out_drop;
|
||||
return error;
|
||||
if (ri->ri_blockcount > 0)
|
||||
error = xfs_refcount_continue_op(rcur, ri, bno);
|
||||
break;
|
||||
@ -1383,31 +1379,29 @@ xfs_refcount_finish_one(
|
||||
error = xfs_refcount_adjust(rcur, &bno, &ri->ri_blockcount,
|
||||
XFS_REFCOUNT_ADJUST_DECREASE);
|
||||
if (error)
|
||||
goto out_drop;
|
||||
return error;
|
||||
if (ri->ri_blockcount > 0)
|
||||
error = xfs_refcount_continue_op(rcur, ri, bno);
|
||||
break;
|
||||
case XFS_REFCOUNT_ALLOC_COW:
|
||||
error = __xfs_refcount_cow_alloc(rcur, bno, ri->ri_blockcount);
|
||||
if (error)
|
||||
goto out_drop;
|
||||
return error;
|
||||
ri->ri_blockcount = 0;
|
||||
break;
|
||||
case XFS_REFCOUNT_FREE_COW:
|
||||
error = __xfs_refcount_cow_free(rcur, bno, ri->ri_blockcount);
|
||||
if (error)
|
||||
goto out_drop;
|
||||
return error;
|
||||
ri->ri_blockcount = 0;
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
error = -EFSCORRUPTED;
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
if (!error && ri->ri_blockcount > 0)
|
||||
trace_xfs_refcount_finish_one_leftover(mp, pag->pag_agno,
|
||||
trace_xfs_refcount_finish_one_leftover(mp, ri->ri_pag->pag_agno,
|
||||
ri->ri_type, bno, ri->ri_blockcount);
|
||||
out_drop:
|
||||
xfs_perag_put(pag);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -1435,6 +1429,7 @@ __xfs_refcount_add(
|
||||
ri->ri_startblock = startblock;
|
||||
ri->ri_blockcount = blockcount;
|
||||
|
||||
xfs_refcount_update_get_group(tp->t_mountp, ri);
|
||||
xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_REFCOUNT, &ri->ri_list);
|
||||
}
|
||||
|
||||
|
@ -50,6 +50,7 @@ enum xfs_refcount_intent_type {
|
||||
|
||||
struct xfs_refcount_intent {
|
||||
struct list_head ri_list;
|
||||
struct xfs_perag *ri_pag;
|
||||
enum xfs_refcount_intent_type ri_type;
|
||||
xfs_extlen_t ri_blockcount;
|
||||
xfs_fsblock_t ri_startblock;
|
||||
@ -67,6 +68,9 @@ xfs_refcount_check_domain(
|
||||
return true;
|
||||
}
|
||||
|
||||
void xfs_refcount_update_get_group(struct xfs_mount *mp,
|
||||
struct xfs_refcount_intent *ri);
|
||||
|
||||
void xfs_refcount_increase_extent(struct xfs_trans *tp,
|
||||
struct xfs_bmbt_irec *irec);
|
||||
void xfs_refcount_decrease_extent(struct xfs_trans *tp,
|
||||
|
@ -112,8 +112,9 @@ xfs_refcountbt_free_block(
|
||||
XFS_FSB_TO_AGBNO(cur->bc_mp, fsbno), 1);
|
||||
be32_add_cpu(&agf->agf_refcount_blocks, -1);
|
||||
xfs_alloc_log_agf(cur->bc_tp, agbp, XFS_AGF_REFCOUNT_BLOCKS);
|
||||
error = xfs_free_extent(cur->bc_tp, fsbno, 1, &XFS_RMAP_OINFO_REFC,
|
||||
XFS_AG_RESV_METADATA);
|
||||
error = xfs_free_extent(cur->bc_tp, cur->bc_ag.pag,
|
||||
XFS_FSB_TO_AGBNO(cur->bc_mp, fsbno), 1,
|
||||
&XFS_RMAP_OINFO_REFC, XFS_AG_RESV_METADATA);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
|
@ -2394,7 +2394,6 @@ xfs_rmap_finish_one(
|
||||
struct xfs_btree_cur **pcur)
|
||||
{
|
||||
struct xfs_mount *mp = tp->t_mountp;
|
||||
struct xfs_perag *pag;
|
||||
struct xfs_btree_cur *rcur;
|
||||
struct xfs_buf *agbp = NULL;
|
||||
int error = 0;
|
||||
@ -2402,26 +2401,22 @@ xfs_rmap_finish_one(
|
||||
xfs_agblock_t bno;
|
||||
bool unwritten;
|
||||
|
||||
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, pag->pag_agno, ri->ri_type, bno,
|
||||
trace_xfs_rmap_deferred(mp, ri->ri_pag->pag_agno, ri->ri_type, bno,
|
||||
ri->ri_owner, ri->ri_whichfork,
|
||||
ri->ri_bmap.br_startoff, ri->ri_bmap.br_blockcount,
|
||||
ri->ri_bmap.br_state);
|
||||
|
||||
if (XFS_TEST_ERROR(false, mp, XFS_ERRTAG_RMAP_FINISH_ONE)) {
|
||||
error = -EIO;
|
||||
goto out_drop;
|
||||
}
|
||||
|
||||
if (XFS_TEST_ERROR(false, mp, XFS_ERRTAG_RMAP_FINISH_ONE))
|
||||
return -EIO;
|
||||
|
||||
/*
|
||||
* If we haven't gotten a cursor or the cursor AG doesn't match
|
||||
* the startblock, get one now.
|
||||
*/
|
||||
rcur = *pcur;
|
||||
if (rcur != NULL && rcur->bc_ag.pag != pag) {
|
||||
if (rcur != NULL && rcur->bc_ag.pag != ri->ri_pag) {
|
||||
xfs_rmap_finish_one_cleanup(tp, rcur, 0);
|
||||
rcur = NULL;
|
||||
*pcur = NULL;
|
||||
@ -2432,15 +2427,13 @@ xfs_rmap_finish_one(
|
||||
* rmapbt, because a shape change could cause us to
|
||||
* allocate blocks.
|
||||
*/
|
||||
error = xfs_free_extent_fix_freelist(tp, pag, &agbp);
|
||||
error = xfs_free_extent_fix_freelist(tp, ri->ri_pag, &agbp);
|
||||
if (error)
|
||||
goto out_drop;
|
||||
if (XFS_IS_CORRUPT(tp->t_mountp, !agbp)) {
|
||||
error = -EFSCORRUPTED;
|
||||
goto out_drop;
|
||||
}
|
||||
return error;
|
||||
if (XFS_IS_CORRUPT(tp->t_mountp, !agbp))
|
||||
return -EFSCORRUPTED;
|
||||
|
||||
rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag);
|
||||
rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, ri->ri_pag);
|
||||
}
|
||||
*pcur = rcur;
|
||||
|
||||
@ -2480,8 +2473,7 @@ xfs_rmap_finish_one(
|
||||
ASSERT(0);
|
||||
error = -EFSCORRUPTED;
|
||||
}
|
||||
out_drop:
|
||||
xfs_perag_put(pag);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -2526,6 +2518,7 @@ __xfs_rmap_add(
|
||||
ri->ri_whichfork = whichfork;
|
||||
ri->ri_bmap = *bmap;
|
||||
|
||||
xfs_rmap_update_get_group(tp->t_mountp, ri);
|
||||
xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_RMAP, &ri->ri_list);
|
||||
}
|
||||
|
||||
|
@ -162,8 +162,12 @@ struct xfs_rmap_intent {
|
||||
int ri_whichfork;
|
||||
uint64_t ri_owner;
|
||||
struct xfs_bmbt_irec ri_bmap;
|
||||
struct xfs_perag *ri_pag;
|
||||
};
|
||||
|
||||
void xfs_rmap_update_get_group(struct xfs_mount *mp,
|
||||
struct xfs_rmap_intent *ri);
|
||||
|
||||
/* functions for updating the rmapbt based on bmbt map/unmap operations */
|
||||
void xfs_rmap_map_extent(struct xfs_trans *tp, struct xfs_inode *ip,
|
||||
int whichfork, struct xfs_bmbt_irec *imap);
|
||||
|
@ -598,7 +598,8 @@ xrep_reap_block(
|
||||
else if (resv == XFS_AG_RESV_AGFL)
|
||||
error = xrep_put_freelist(sc, agbno);
|
||||
else
|
||||
error = xfs_free_extent(sc->tp, fsbno, 1, oinfo, resv);
|
||||
error = xfs_free_extent(sc->tp, sc->sa.pag, agbno, 1, oinfo,
|
||||
resv);
|
||||
if (agf_bp != sc->sa.agf_bp)
|
||||
xfs_trans_brelse(sc->tp, agf_bp);
|
||||
if (error)
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "xfs_error.h"
|
||||
#include "xfs_log_priv.h"
|
||||
#include "xfs_log_recover.h"
|
||||
#include "xfs_ag.h"
|
||||
|
||||
struct kmem_cache *xfs_bui_cache;
|
||||
struct kmem_cache *xfs_bud_cache;
|
||||
@ -363,6 +364,26 @@ xfs_bmap_update_create_done(
|
||||
return &xfs_trans_get_bud(tp, BUI_ITEM(intent))->bud_item;
|
||||
}
|
||||
|
||||
/* Take a passive ref to the AG containing the space we're mapping. */
|
||||
void
|
||||
xfs_bmap_update_get_group(
|
||||
struct xfs_mount *mp,
|
||||
struct xfs_bmap_intent *bi)
|
||||
{
|
||||
xfs_agnumber_t agno;
|
||||
|
||||
agno = XFS_FSB_TO_AGNO(mp, bi->bi_bmap.br_startblock);
|
||||
bi->bi_pag = xfs_perag_get(mp, agno);
|
||||
}
|
||||
|
||||
/* Release a passive AG ref after finishing mapping work. */
|
||||
static inline void
|
||||
xfs_bmap_update_put_group(
|
||||
struct xfs_bmap_intent *bi)
|
||||
{
|
||||
xfs_perag_put(bi->bi_pag);
|
||||
}
|
||||
|
||||
/* Process a deferred rmap update. */
|
||||
STATIC int
|
||||
xfs_bmap_update_finish_item(
|
||||
@ -381,6 +402,8 @@ xfs_bmap_update_finish_item(
|
||||
ASSERT(bi->bi_type == XFS_BMAP_UNMAP);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
xfs_bmap_update_put_group(bi);
|
||||
kmem_cache_free(xfs_bmap_intent_cache, bi);
|
||||
return error;
|
||||
}
|
||||
@ -393,7 +416,7 @@ xfs_bmap_update_abort_intent(
|
||||
xfs_bui_release(BUI_ITEM(intent));
|
||||
}
|
||||
|
||||
/* Cancel a deferred rmap update. */
|
||||
/* Cancel a deferred bmap update. */
|
||||
STATIC void
|
||||
xfs_bmap_update_cancel_item(
|
||||
struct list_head *item)
|
||||
@ -401,6 +424,8 @@ xfs_bmap_update_cancel_item(
|
||||
struct xfs_bmap_intent *bi;
|
||||
|
||||
bi = container_of(item, struct xfs_bmap_intent, bi_list);
|
||||
|
||||
xfs_bmap_update_put_group(bi);
|
||||
kmem_cache_free(xfs_bmap_intent_cache, bi);
|
||||
}
|
||||
|
||||
@ -509,10 +534,12 @@ xfs_bui_item_recover(
|
||||
fake.bi_bmap.br_state = (map->me_flags & XFS_BMAP_EXTENT_UNWRITTEN) ?
|
||||
XFS_EXT_UNWRITTEN : XFS_EXT_NORM;
|
||||
|
||||
xfs_bmap_update_get_group(mp, &fake);
|
||||
error = xfs_trans_log_finish_bmap_update(tp, budp, &fake);
|
||||
if (error == -EFSCORRUPTED)
|
||||
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, map,
|
||||
sizeof(*map));
|
||||
xfs_bmap_update_put_group(&fake);
|
||||
if (error)
|
||||
goto err_cancel;
|
||||
|
||||
|
@ -351,8 +351,6 @@ xfs_trans_free_extent(
|
||||
struct xfs_mount *mp = tp->t_mountp;
|
||||
struct xfs_extent *extp;
|
||||
uint next_extent;
|
||||
xfs_agnumber_t agno = XFS_FSB_TO_AGNO(mp,
|
||||
xefi->xefi_startblock);
|
||||
xfs_agblock_t agbno = XFS_FSB_TO_AGBNO(mp,
|
||||
xefi->xefi_startblock);
|
||||
int error;
|
||||
@ -363,12 +361,13 @@ xfs_trans_free_extent(
|
||||
if (xefi->xefi_flags & XFS_EFI_BMBT_BLOCK)
|
||||
oinfo.oi_flags |= XFS_OWNER_INFO_BMBT_BLOCK;
|
||||
|
||||
trace_xfs_bmap_free_deferred(tp->t_mountp, agno, 0, agbno,
|
||||
xefi->xefi_blockcount);
|
||||
trace_xfs_bmap_free_deferred(tp->t_mountp, xefi->xefi_pag->pag_agno, 0,
|
||||
agbno, xefi->xefi_blockcount);
|
||||
|
||||
error = __xfs_free_extent(tp, xefi->xefi_startblock,
|
||||
error = __xfs_free_extent(tp, xefi->xefi_pag, agbno,
|
||||
xefi->xefi_blockcount, &oinfo, XFS_AG_RESV_NONE,
|
||||
xefi->xefi_flags & XFS_EFI_SKIP_DISCARD);
|
||||
|
||||
/*
|
||||
* Mark the transaction dirty, even on error. This ensures the
|
||||
* transaction is aborted, which:
|
||||
@ -396,14 +395,13 @@ xfs_extent_free_diff_items(
|
||||
const struct list_head *a,
|
||||
const struct list_head *b)
|
||||
{
|
||||
struct xfs_mount *mp = priv;
|
||||
struct xfs_extent_free_item *ra;
|
||||
struct xfs_extent_free_item *rb;
|
||||
|
||||
ra = container_of(a, struct xfs_extent_free_item, xefi_list);
|
||||
rb = container_of(b, struct xfs_extent_free_item, xefi_list);
|
||||
return XFS_FSB_TO_AGNO(mp, ra->xefi_startblock) -
|
||||
XFS_FSB_TO_AGNO(mp, rb->xefi_startblock);
|
||||
|
||||
return ra->xefi_pag->pag_agno - rb->xefi_pag->pag_agno;
|
||||
}
|
||||
|
||||
/* Log a free extent to the intent item. */
|
||||
@ -462,6 +460,26 @@ xfs_extent_free_create_done(
|
||||
return &xfs_trans_get_efd(tp, EFI_ITEM(intent), count)->efd_item;
|
||||
}
|
||||
|
||||
/* Take a passive ref to the AG containing the space we're freeing. */
|
||||
void
|
||||
xfs_extent_free_get_group(
|
||||
struct xfs_mount *mp,
|
||||
struct xfs_extent_free_item *xefi)
|
||||
{
|
||||
xfs_agnumber_t agno;
|
||||
|
||||
agno = XFS_FSB_TO_AGNO(mp, xefi->xefi_startblock);
|
||||
xefi->xefi_pag = xfs_perag_get(mp, agno);
|
||||
}
|
||||
|
||||
/* Release a passive AG ref after some freeing work. */
|
||||
static inline void
|
||||
xfs_extent_free_put_group(
|
||||
struct xfs_extent_free_item *xefi)
|
||||
{
|
||||
xfs_perag_put(xefi->xefi_pag);
|
||||
}
|
||||
|
||||
/* Process a free extent. */
|
||||
STATIC int
|
||||
xfs_extent_free_finish_item(
|
||||
@ -476,6 +494,8 @@ xfs_extent_free_finish_item(
|
||||
xefi = container_of(item, struct xfs_extent_free_item, xefi_list);
|
||||
|
||||
error = xfs_trans_free_extent(tp, EFD_ITEM(done), xefi);
|
||||
|
||||
xfs_extent_free_put_group(xefi);
|
||||
kmem_cache_free(xfs_extfree_item_cache, xefi);
|
||||
return error;
|
||||
}
|
||||
@ -496,6 +516,8 @@ xfs_extent_free_cancel_item(
|
||||
struct xfs_extent_free_item *xefi;
|
||||
|
||||
xefi = container_of(item, struct xfs_extent_free_item, xefi_list);
|
||||
|
||||
xfs_extent_free_put_group(xefi);
|
||||
kmem_cache_free(xfs_extfree_item_cache, xefi);
|
||||
}
|
||||
|
||||
@ -526,24 +548,21 @@ xfs_agfl_free_finish_item(
|
||||
struct xfs_extent *extp;
|
||||
struct xfs_buf *agbp;
|
||||
int error;
|
||||
xfs_agnumber_t agno;
|
||||
xfs_agblock_t agbno;
|
||||
uint next_extent;
|
||||
struct xfs_perag *pag;
|
||||
|
||||
xefi = container_of(item, struct xfs_extent_free_item, xefi_list);
|
||||
ASSERT(xefi->xefi_blockcount == 1);
|
||||
agno = XFS_FSB_TO_AGNO(mp, xefi->xefi_startblock);
|
||||
agbno = XFS_FSB_TO_AGBNO(mp, xefi->xefi_startblock);
|
||||
oinfo.oi_owner = xefi->xefi_owner;
|
||||
|
||||
trace_xfs_agfl_free_deferred(mp, agno, 0, agbno, xefi->xefi_blockcount);
|
||||
trace_xfs_agfl_free_deferred(mp, xefi->xefi_pag->pag_agno, 0, agbno,
|
||||
xefi->xefi_blockcount);
|
||||
|
||||
pag = xfs_perag_get(mp, agno);
|
||||
error = xfs_alloc_read_agf(pag, tp, 0, &agbp);
|
||||
error = xfs_alloc_read_agf(xefi->xefi_pag, tp, 0, &agbp);
|
||||
if (!error)
|
||||
error = xfs_free_agfl_block(tp, agno, agbno, agbp, &oinfo);
|
||||
xfs_perag_put(pag);
|
||||
error = xfs_free_agfl_block(tp, xefi->xefi_pag->pag_agno,
|
||||
agbno, agbp, &oinfo);
|
||||
|
||||
/*
|
||||
* Mark the transaction dirty, even on error. This ensures the
|
||||
@ -562,6 +581,7 @@ xfs_agfl_free_finish_item(
|
||||
extp->ext_len = xefi->xefi_blockcount;
|
||||
efdp->efd_next_extent++;
|
||||
|
||||
xfs_extent_free_put_group(xefi);
|
||||
kmem_cache_free(xfs_extfree_item_cache, xefi);
|
||||
return error;
|
||||
}
|
||||
@ -632,7 +652,9 @@ xfs_efi_item_recover(
|
||||
fake.xefi_startblock = extp->ext_start;
|
||||
fake.xefi_blockcount = extp->ext_len;
|
||||
|
||||
xfs_extent_free_get_group(mp, &fake);
|
||||
error = xfs_trans_free_extent(tp, efdp, &fake);
|
||||
xfs_extent_free_put_group(&fake);
|
||||
if (error == -EFSCORRUPTED)
|
||||
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
|
||||
extp, sizeof(*extp));
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "xfs_error.h"
|
||||
#include "xfs_log_priv.h"
|
||||
#include "xfs_log_recover.h"
|
||||
#include "xfs_ag.h"
|
||||
|
||||
struct kmem_cache *xfs_cui_cache;
|
||||
struct kmem_cache *xfs_cud_cache;
|
||||
@ -279,14 +280,13 @@ xfs_refcount_update_diff_items(
|
||||
const struct list_head *a,
|
||||
const struct list_head *b)
|
||||
{
|
||||
struct xfs_mount *mp = priv;
|
||||
struct xfs_refcount_intent *ra;
|
||||
struct xfs_refcount_intent *rb;
|
||||
|
||||
ra = container_of(a, struct xfs_refcount_intent, ri_list);
|
||||
rb = container_of(b, struct xfs_refcount_intent, ri_list);
|
||||
return XFS_FSB_TO_AGNO(mp, ra->ri_startblock) -
|
||||
XFS_FSB_TO_AGNO(mp, rb->ri_startblock);
|
||||
|
||||
return ra->ri_pag->pag_agno - rb->ri_pag->pag_agno;
|
||||
}
|
||||
|
||||
/* Set the phys extent flags for this reverse mapping. */
|
||||
@ -365,6 +365,26 @@ xfs_refcount_update_create_done(
|
||||
return &xfs_trans_get_cud(tp, CUI_ITEM(intent))->cud_item;
|
||||
}
|
||||
|
||||
/* Take a passive ref to the AG containing the space we're refcounting. */
|
||||
void
|
||||
xfs_refcount_update_get_group(
|
||||
struct xfs_mount *mp,
|
||||
struct xfs_refcount_intent *ri)
|
||||
{
|
||||
xfs_agnumber_t agno;
|
||||
|
||||
agno = XFS_FSB_TO_AGNO(mp, ri->ri_startblock);
|
||||
ri->ri_pag = xfs_perag_get(mp, agno);
|
||||
}
|
||||
|
||||
/* Release a passive AG ref after finishing refcounting work. */
|
||||
static inline void
|
||||
xfs_refcount_update_put_group(
|
||||
struct xfs_refcount_intent *ri)
|
||||
{
|
||||
xfs_perag_put(ri->ri_pag);
|
||||
}
|
||||
|
||||
/* Process a deferred refcount update. */
|
||||
STATIC int
|
||||
xfs_refcount_update_finish_item(
|
||||
@ -386,6 +406,8 @@ xfs_refcount_update_finish_item(
|
||||
ri->ri_type == XFS_REFCOUNT_DECREASE);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
xfs_refcount_update_put_group(ri);
|
||||
kmem_cache_free(xfs_refcount_intent_cache, ri);
|
||||
return error;
|
||||
}
|
||||
@ -406,6 +428,8 @@ xfs_refcount_update_cancel_item(
|
||||
struct xfs_refcount_intent *ri;
|
||||
|
||||
ri = container_of(item, struct xfs_refcount_intent, ri_list);
|
||||
|
||||
xfs_refcount_update_put_group(ri);
|
||||
kmem_cache_free(xfs_refcount_intent_cache, ri);
|
||||
}
|
||||
|
||||
@ -520,9 +544,13 @@ xfs_cui_item_recover(
|
||||
|
||||
fake.ri_startblock = pmap->pe_startblock;
|
||||
fake.ri_blockcount = pmap->pe_len;
|
||||
if (!requeue_only)
|
||||
|
||||
if (!requeue_only) {
|
||||
xfs_refcount_update_get_group(mp, &fake);
|
||||
error = xfs_trans_log_finish_refcount_update(tp, cudp,
|
||||
&fake, &rcur);
|
||||
xfs_refcount_update_put_group(&fake);
|
||||
}
|
||||
if (error == -EFSCORRUPTED)
|
||||
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
|
||||
&cuip->cui_format,
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "xfs_error.h"
|
||||
#include "xfs_log_priv.h"
|
||||
#include "xfs_log_recover.h"
|
||||
#include "xfs_ag.h"
|
||||
|
||||
struct kmem_cache *xfs_rui_cache;
|
||||
struct kmem_cache *xfs_rud_cache;
|
||||
@ -320,14 +321,13 @@ xfs_rmap_update_diff_items(
|
||||
const struct list_head *a,
|
||||
const struct list_head *b)
|
||||
{
|
||||
struct xfs_mount *mp = priv;
|
||||
struct xfs_rmap_intent *ra;
|
||||
struct xfs_rmap_intent *rb;
|
||||
|
||||
ra = container_of(a, struct xfs_rmap_intent, ri_list);
|
||||
rb = container_of(b, struct xfs_rmap_intent, ri_list);
|
||||
return XFS_FSB_TO_AGNO(mp, ra->ri_bmap.br_startblock) -
|
||||
XFS_FSB_TO_AGNO(mp, rb->ri_bmap.br_startblock);
|
||||
|
||||
return ra->ri_pag->pag_agno - rb->ri_pag->pag_agno;
|
||||
}
|
||||
|
||||
/* Log rmap updates in the intent item. */
|
||||
@ -390,6 +390,26 @@ xfs_rmap_update_create_done(
|
||||
return &xfs_trans_get_rud(tp, RUI_ITEM(intent))->rud_item;
|
||||
}
|
||||
|
||||
/* Take a passive ref to the AG containing the space we're rmapping. */
|
||||
void
|
||||
xfs_rmap_update_get_group(
|
||||
struct xfs_mount *mp,
|
||||
struct xfs_rmap_intent *ri)
|
||||
{
|
||||
xfs_agnumber_t agno;
|
||||
|
||||
agno = XFS_FSB_TO_AGNO(mp, ri->ri_bmap.br_startblock);
|
||||
ri->ri_pag = xfs_perag_get(mp, agno);
|
||||
}
|
||||
|
||||
/* Release a passive AG ref after finishing rmapping work. */
|
||||
static inline void
|
||||
xfs_rmap_update_put_group(
|
||||
struct xfs_rmap_intent *ri)
|
||||
{
|
||||
xfs_perag_put(ri->ri_pag);
|
||||
}
|
||||
|
||||
/* Process a deferred rmap update. */
|
||||
STATIC int
|
||||
xfs_rmap_update_finish_item(
|
||||
@ -405,6 +425,8 @@ xfs_rmap_update_finish_item(
|
||||
|
||||
error = xfs_trans_log_finish_rmap_update(tp, RUD_ITEM(done), ri,
|
||||
state);
|
||||
|
||||
xfs_rmap_update_put_group(ri);
|
||||
kmem_cache_free(xfs_rmap_intent_cache, ri);
|
||||
return error;
|
||||
}
|
||||
@ -425,6 +447,8 @@ xfs_rmap_update_cancel_item(
|
||||
struct xfs_rmap_intent *ri;
|
||||
|
||||
ri = container_of(item, struct xfs_rmap_intent, ri_list);
|
||||
|
||||
xfs_rmap_update_put_group(ri);
|
||||
kmem_cache_free(xfs_rmap_intent_cache, ri);
|
||||
}
|
||||
|
||||
@ -559,11 +583,13 @@ xfs_rui_item_recover(
|
||||
fake.ri_bmap.br_state = (map->me_flags & XFS_RMAP_EXTENT_UNWRITTEN) ?
|
||||
XFS_EXT_UNWRITTEN : XFS_EXT_NORM;
|
||||
|
||||
xfs_rmap_update_get_group(mp, &fake);
|
||||
error = xfs_trans_log_finish_rmap_update(tp, rudp, &fake,
|
||||
&rcur);
|
||||
if (error == -EFSCORRUPTED)
|
||||
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
|
||||
map, sizeof(*map));
|
||||
xfs_rmap_update_put_group(&fake);
|
||||
if (error)
|
||||
goto abort_error;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user