Skip to content

Commit 662254a

Browse files
Darrick J. Wonggregkh
authored andcommitted
xfs: give xfs_extfree_intent its own perag reference
commit f6b384631e1e3482c24e35b53adbd3da50e47e8f upstream. 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: Darrick J. Wong <[email protected]> Reviewed-by: Dave Chinner <[email protected]> Signed-off-by: Leah Rumancik <[email protected]> Acked-by: "Darrick J. Wong" <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 7400fa1 commit 662254a

File tree

3 files changed

+47
-22
lines changed

3 files changed

+47
-22
lines changed

fs/xfs/libxfs/xfs_alloc.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2511,6 +2511,7 @@ xfs_defer_agfl_block(
25112511

25122512
trace_xfs_agfl_free_defer(mp, agno, 0, agbno, 1);
25132513

2514+
xfs_extent_free_get_group(mp, xefi);
25142515
xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_AGFL_FREE, &xefi->xefi_list);
25152516
return 0;
25162517
}
@@ -2529,8 +2530,8 @@ __xfs_free_extent_later(
25292530
bool skip_discard)
25302531
{
25312532
struct xfs_extent_free_item *xefi;
2532-
#ifdef DEBUG
25332533
struct xfs_mount *mp = tp->t_mountp;
2534+
#ifdef DEBUG
25342535
xfs_agnumber_t agno;
25352536
xfs_agblock_t agbno;
25362537

@@ -2569,9 +2570,11 @@ __xfs_free_extent_later(
25692570
} else {
25702571
xefi->xefi_owner = XFS_RMAP_OWN_NULL;
25712572
}
2572-
trace_xfs_bmap_free_defer(tp->t_mountp,
2573+
trace_xfs_bmap_free_defer(mp,
25732574
XFS_FSB_TO_AGNO(tp->t_mountp, bno), 0,
25742575
XFS_FSB_TO_AGBNO(tp->t_mountp, bno), len);
2576+
2577+
xfs_extent_free_get_group(mp, xefi);
25752578
xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_FREE, &xefi->xefi_list);
25762579
return 0;
25772580
}

fs/xfs/libxfs/xfs_alloc.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,10 +226,14 @@ struct xfs_extent_free_item {
226226
uint64_t xefi_owner;
227227
xfs_fsblock_t xefi_startblock;/* starting fs block number */
228228
xfs_extlen_t xefi_blockcount;/* number of blocks in extent */
229+
struct xfs_perag *xefi_pag;
229230
unsigned int xefi_flags;
230231
enum xfs_ag_resv_type xefi_agresv;
231232
};
232233

234+
void xfs_extent_free_get_group(struct xfs_mount *mp,
235+
struct xfs_extent_free_item *xefi);
236+
233237
#define XFS_EFI_SKIP_DISCARD (1U << 0) /* don't issue discard */
234238
#define XFS_EFI_ATTR_FORK (1U << 1) /* freeing attr fork block */
235239
#define XFS_EFI_BMBT_BLOCK (1U << 2) /* freeing bmap btree block */

fs/xfs/xfs_extfree_item.c

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -350,10 +350,7 @@ xfs_trans_free_extent(
350350
struct xfs_owner_info oinfo = { };
351351
struct xfs_mount *mp = tp->t_mountp;
352352
struct xfs_extent *extp;
353-
struct xfs_perag *pag;
354353
uint next_extent;
355-
xfs_agnumber_t agno = XFS_FSB_TO_AGNO(mp,
356-
xefi->xefi_startblock);
357354
xfs_agblock_t agbno = XFS_FSB_TO_AGBNO(mp,
358355
xefi->xefi_startblock);
359356
int error;
@@ -364,14 +361,12 @@ xfs_trans_free_extent(
364361
if (xefi->xefi_flags & XFS_EFI_BMBT_BLOCK)
365362
oinfo.oi_flags |= XFS_OWNER_INFO_BMBT_BLOCK;
366363

367-
trace_xfs_bmap_free_deferred(tp->t_mountp, agno, 0, agbno,
368-
xefi->xefi_blockcount);
364+
trace_xfs_bmap_free_deferred(tp->t_mountp, xefi->xefi_pag->pag_agno, 0,
365+
agbno, xefi->xefi_blockcount);
369366

370-
pag = xfs_perag_get(mp, agno);
371-
error = __xfs_free_extent(tp, pag, agbno, xefi->xefi_blockcount,
372-
&oinfo, xefi->xefi_agresv,
367+
error = __xfs_free_extent(tp, xefi->xefi_pag, agbno,
368+
xefi->xefi_blockcount, &oinfo, xefi->xefi_agresv,
373369
xefi->xefi_flags & XFS_EFI_SKIP_DISCARD);
374-
xfs_perag_put(pag);
375370

376371
/*
377372
* Mark the transaction dirty, even on error. This ensures the
@@ -400,14 +395,13 @@ xfs_extent_free_diff_items(
400395
const struct list_head *a,
401396
const struct list_head *b)
402397
{
403-
struct xfs_mount *mp = priv;
404398
struct xfs_extent_free_item *ra;
405399
struct xfs_extent_free_item *rb;
406400

407401
ra = container_of(a, struct xfs_extent_free_item, xefi_list);
408402
rb = container_of(b, struct xfs_extent_free_item, xefi_list);
409-
return XFS_FSB_TO_AGNO(mp, ra->xefi_startblock) -
410-
XFS_FSB_TO_AGNO(mp, rb->xefi_startblock);
403+
404+
return ra->xefi_pag->pag_agno - rb->xefi_pag->pag_agno;
411405
}
412406

413407
/* Log a free extent to the intent item. */
@@ -466,6 +460,26 @@ xfs_extent_free_create_done(
466460
return &xfs_trans_get_efd(tp, EFI_ITEM(intent), count)->efd_item;
467461
}
468462

463+
/* Take a passive ref to the AG containing the space we're freeing. */
464+
void
465+
xfs_extent_free_get_group(
466+
struct xfs_mount *mp,
467+
struct xfs_extent_free_item *xefi)
468+
{
469+
xfs_agnumber_t agno;
470+
471+
agno = XFS_FSB_TO_AGNO(mp, xefi->xefi_startblock);
472+
xefi->xefi_pag = xfs_perag_get(mp, agno);
473+
}
474+
475+
/* Release a passive AG ref after some freeing work. */
476+
static inline void
477+
xfs_extent_free_put_group(
478+
struct xfs_extent_free_item *xefi)
479+
{
480+
xfs_perag_put(xefi->xefi_pag);
481+
}
482+
469483
/* Process a free extent. */
470484
STATIC int
471485
xfs_extent_free_finish_item(
@@ -480,6 +494,8 @@ xfs_extent_free_finish_item(
480494
xefi = container_of(item, struct xfs_extent_free_item, xefi_list);
481495

482496
error = xfs_trans_free_extent(tp, EFD_ITEM(done), xefi);
497+
498+
xfs_extent_free_put_group(xefi);
483499
kmem_cache_free(xfs_extfree_item_cache, xefi);
484500
return error;
485501
}
@@ -500,6 +516,8 @@ xfs_extent_free_cancel_item(
500516
struct xfs_extent_free_item *xefi;
501517

502518
xefi = container_of(item, struct xfs_extent_free_item, xefi_list);
519+
520+
xfs_extent_free_put_group(xefi);
503521
kmem_cache_free(xfs_extfree_item_cache, xefi);
504522
}
505523

@@ -530,24 +548,21 @@ xfs_agfl_free_finish_item(
530548
struct xfs_extent *extp;
531549
struct xfs_buf *agbp;
532550
int error;
533-
xfs_agnumber_t agno;
534551
xfs_agblock_t agbno;
535552
uint next_extent;
536-
struct xfs_perag *pag;
537553

538554
xefi = container_of(item, struct xfs_extent_free_item, xefi_list);
539555
ASSERT(xefi->xefi_blockcount == 1);
540-
agno = XFS_FSB_TO_AGNO(mp, xefi->xefi_startblock);
541556
agbno = XFS_FSB_TO_AGBNO(mp, xefi->xefi_startblock);
542557
oinfo.oi_owner = xefi->xefi_owner;
543558

544-
trace_xfs_agfl_free_deferred(mp, agno, 0, agbno, xefi->xefi_blockcount);
559+
trace_xfs_agfl_free_deferred(mp, xefi->xefi_pag->pag_agno, 0, agbno,
560+
xefi->xefi_blockcount);
545561

546-
pag = xfs_perag_get(mp, agno);
547-
error = xfs_alloc_read_agf(pag, tp, 0, &agbp);
562+
error = xfs_alloc_read_agf(xefi->xefi_pag, tp, 0, &agbp);
548563
if (!error)
549-
error = xfs_free_agfl_block(tp, agno, agbno, agbp, &oinfo);
550-
xfs_perag_put(pag);
564+
error = xfs_free_agfl_block(tp, xefi->xefi_pag->pag_agno,
565+
agbno, agbp, &oinfo);
551566

552567
/*
553568
* Mark the transaction dirty, even on error. This ensures the
@@ -566,6 +581,7 @@ xfs_agfl_free_finish_item(
566581
extp->ext_len = xefi->xefi_blockcount;
567582
efdp->efd_next_extent++;
568583

584+
xfs_extent_free_put_group(xefi);
569585
kmem_cache_free(xfs_extfree_item_cache, xefi);
570586
return error;
571587
}
@@ -639,7 +655,9 @@ xfs_efi_item_recover(
639655
fake.xefi_startblock = extp->ext_start;
640656
fake.xefi_blockcount = extp->ext_len;
641657

658+
xfs_extent_free_get_group(mp, &fake);
642659
error = xfs_trans_free_extent(tp, efdp, &fake);
660+
xfs_extent_free_put_group(&fake);
643661
if (error == -EFSCORRUPTED)
644662
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
645663
extp, sizeof(*extp));

0 commit comments

Comments
 (0)