Commit f6b38463 authored by Darrick J. Wong's avatar Darrick J. Wong

xfs: give xfs_extfree_intent its own perag reference

Give the xfs_extfree_intent an passive reference to the perag structure
data.  This reference will be used to enable scrub intent draining
functionality in subsequent patches.  The space being freed must already
be allocated, so we need to able to run even if the AG is being offlined
or shrunk.
Signed-off-by: default avatarDarrick J. Wong <djwong@kernel.org>
Reviewed-by: default avatarDave Chinner <dchinner@redhat.com>
parent b2ccab31
...@@ -2405,6 +2405,7 @@ xfs_defer_agfl_block( ...@@ -2405,6 +2405,7 @@ xfs_defer_agfl_block(
trace_xfs_agfl_free_defer(mp, agno, 0, agbno, 1); 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); xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_AGFL_FREE, &xefi->xefi_list);
} }
...@@ -2421,8 +2422,8 @@ __xfs_free_extent_later( ...@@ -2421,8 +2422,8 @@ __xfs_free_extent_later(
bool skip_discard) bool skip_discard)
{ {
struct xfs_extent_free_item *xefi; struct xfs_extent_free_item *xefi;
#ifdef DEBUG
struct xfs_mount *mp = tp->t_mountp; struct xfs_mount *mp = tp->t_mountp;
#ifdef DEBUG
xfs_agnumber_t agno; xfs_agnumber_t agno;
xfs_agblock_t agbno; xfs_agblock_t agbno;
...@@ -2456,9 +2457,11 @@ __xfs_free_extent_later( ...@@ -2456,9 +2457,11 @@ __xfs_free_extent_later(
} else { } else {
xefi->xefi_owner = XFS_RMAP_OWN_NULL; 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_AGNO(tp->t_mountp, bno), 0,
XFS_FSB_TO_AGBNO(tp->t_mountp, bno), len); 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); xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_FREE, &xefi->xefi_list);
} }
......
...@@ -237,9 +237,13 @@ struct xfs_extent_free_item { ...@@ -237,9 +237,13 @@ struct xfs_extent_free_item {
uint64_t xefi_owner; uint64_t xefi_owner;
xfs_fsblock_t xefi_startblock;/* starting fs block number */ xfs_fsblock_t xefi_startblock;/* starting fs block number */
xfs_extlen_t xefi_blockcount;/* number of blocks in extent */ xfs_extlen_t xefi_blockcount;/* number of blocks in extent */
struct xfs_perag *xefi_pag;
unsigned int xefi_flags; 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_SKIP_DISCARD (1U << 0) /* don't issue discard */
#define XFS_EFI_ATTR_FORK (1U << 1) /* freeing attr fork block */ #define XFS_EFI_ATTR_FORK (1U << 1) /* freeing attr fork block */
#define XFS_EFI_BMBT_BLOCK (1U << 2) /* freeing bmap btree block */ #define XFS_EFI_BMBT_BLOCK (1U << 2) /* freeing bmap btree block */
......
...@@ -350,10 +350,7 @@ xfs_trans_free_extent( ...@@ -350,10 +350,7 @@ xfs_trans_free_extent(
struct xfs_owner_info oinfo = { }; struct xfs_owner_info oinfo = { };
struct xfs_mount *mp = tp->t_mountp; struct xfs_mount *mp = tp->t_mountp;
struct xfs_extent *extp; struct xfs_extent *extp;
struct xfs_perag *pag;
uint next_extent; uint next_extent;
xfs_agnumber_t agno = XFS_FSB_TO_AGNO(mp,
xefi->xefi_startblock);
xfs_agblock_t agbno = XFS_FSB_TO_AGBNO(mp, xfs_agblock_t agbno = XFS_FSB_TO_AGBNO(mp,
xefi->xefi_startblock); xefi->xefi_startblock);
int error; int error;
...@@ -364,14 +361,12 @@ xfs_trans_free_extent( ...@@ -364,14 +361,12 @@ xfs_trans_free_extent(
if (xefi->xefi_flags & XFS_EFI_BMBT_BLOCK) if (xefi->xefi_flags & XFS_EFI_BMBT_BLOCK)
oinfo.oi_flags |= XFS_OWNER_INFO_BMBT_BLOCK; oinfo.oi_flags |= XFS_OWNER_INFO_BMBT_BLOCK;
trace_xfs_bmap_free_deferred(tp->t_mountp, agno, 0, agbno, trace_xfs_bmap_free_deferred(tp->t_mountp, xefi->xefi_pag->pag_agno, 0,
xefi->xefi_blockcount); agbno, xefi->xefi_blockcount);
pag = xfs_perag_get(mp, agno); error = __xfs_free_extent(tp, xefi->xefi_pag, agbno,
error = __xfs_free_extent(tp, pag, agbno, xefi->xefi_blockcount, xefi->xefi_blockcount, &oinfo, XFS_AG_RESV_NONE,
&oinfo, XFS_AG_RESV_NONE,
xefi->xefi_flags & XFS_EFI_SKIP_DISCARD); xefi->xefi_flags & XFS_EFI_SKIP_DISCARD);
xfs_perag_put(pag);
/* /*
* Mark the transaction dirty, even on error. This ensures the * Mark the transaction dirty, even on error. This ensures the
...@@ -400,14 +395,13 @@ xfs_extent_free_diff_items( ...@@ -400,14 +395,13 @@ xfs_extent_free_diff_items(
const struct list_head *a, const struct list_head *a,
const struct list_head *b) const struct list_head *b)
{ {
struct xfs_mount *mp = priv;
struct xfs_extent_free_item *ra; struct xfs_extent_free_item *ra;
struct xfs_extent_free_item *rb; struct xfs_extent_free_item *rb;
ra = container_of(a, struct xfs_extent_free_item, xefi_list); ra = container_of(a, struct xfs_extent_free_item, xefi_list);
rb = container_of(b, 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. */ /* Log a free extent to the intent item. */
...@@ -466,6 +460,26 @@ xfs_extent_free_create_done( ...@@ -466,6 +460,26 @@ xfs_extent_free_create_done(
return &xfs_trans_get_efd(tp, EFI_ITEM(intent), count)->efd_item; 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. */ /* Process a free extent. */
STATIC int STATIC int
xfs_extent_free_finish_item( xfs_extent_free_finish_item(
...@@ -480,6 +494,8 @@ xfs_extent_free_finish_item( ...@@ -480,6 +494,8 @@ xfs_extent_free_finish_item(
xefi = container_of(item, struct xfs_extent_free_item, xefi_list); xefi = container_of(item, struct xfs_extent_free_item, xefi_list);
error = xfs_trans_free_extent(tp, EFD_ITEM(done), xefi); error = xfs_trans_free_extent(tp, EFD_ITEM(done), xefi);
xfs_extent_free_put_group(xefi);
kmem_cache_free(xfs_extfree_item_cache, xefi); kmem_cache_free(xfs_extfree_item_cache, xefi);
return error; return error;
} }
...@@ -500,6 +516,8 @@ xfs_extent_free_cancel_item( ...@@ -500,6 +516,8 @@ xfs_extent_free_cancel_item(
struct xfs_extent_free_item *xefi; struct xfs_extent_free_item *xefi;
xefi = container_of(item, struct xfs_extent_free_item, xefi_list); 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); kmem_cache_free(xfs_extfree_item_cache, xefi);
} }
...@@ -530,24 +548,21 @@ xfs_agfl_free_finish_item( ...@@ -530,24 +548,21 @@ xfs_agfl_free_finish_item(
struct xfs_extent *extp; struct xfs_extent *extp;
struct xfs_buf *agbp; struct xfs_buf *agbp;
int error; int error;
xfs_agnumber_t agno;
xfs_agblock_t agbno; xfs_agblock_t agbno;
uint next_extent; uint next_extent;
struct xfs_perag *pag;
xefi = container_of(item, struct xfs_extent_free_item, xefi_list); xefi = container_of(item, struct xfs_extent_free_item, xefi_list);
ASSERT(xefi->xefi_blockcount == 1); ASSERT(xefi->xefi_blockcount == 1);
agno = XFS_FSB_TO_AGNO(mp, xefi->xefi_startblock);
agbno = XFS_FSB_TO_AGBNO(mp, xefi->xefi_startblock); agbno = XFS_FSB_TO_AGBNO(mp, xefi->xefi_startblock);
oinfo.oi_owner = xefi->xefi_owner; 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(xefi->xefi_pag, tp, 0, &agbp);
error = xfs_alloc_read_agf(pag, tp, 0, &agbp);
if (!error) if (!error)
error = xfs_free_agfl_block(tp, agno, agbno, agbp, &oinfo); error = xfs_free_agfl_block(tp, xefi->xefi_pag->pag_agno,
xfs_perag_put(pag); agbno, agbp, &oinfo);
/* /*
* Mark the transaction dirty, even on error. This ensures the * Mark the transaction dirty, even on error. This ensures the
...@@ -566,6 +581,7 @@ xfs_agfl_free_finish_item( ...@@ -566,6 +581,7 @@ xfs_agfl_free_finish_item(
extp->ext_len = xefi->xefi_blockcount; extp->ext_len = xefi->xefi_blockcount;
efdp->efd_next_extent++; efdp->efd_next_extent++;
xfs_extent_free_put_group(xefi);
kmem_cache_free(xfs_extfree_item_cache, xefi); kmem_cache_free(xfs_extfree_item_cache, xefi);
return error; return error;
} }
...@@ -636,7 +652,9 @@ xfs_efi_item_recover( ...@@ -636,7 +652,9 @@ xfs_efi_item_recover(
fake.xefi_startblock = extp->ext_start; fake.xefi_startblock = extp->ext_start;
fake.xefi_blockcount = extp->ext_len; fake.xefi_blockcount = extp->ext_len;
xfs_extent_free_get_group(mp, &fake);
error = xfs_trans_free_extent(tp, efdp, &fake); error = xfs_trans_free_extent(tp, efdp, &fake);
xfs_extent_free_put_group(&fake);
if (error == -EFSCORRUPTED) if (error == -EFSCORRUPTED)
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
extp, sizeof(*extp)); extp, sizeof(*extp));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment