Skip to content

Commit f6b3846

Browse files
author
Darrick J. Wong
committed
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: Darrick J. Wong <djwong@kernel.org> Reviewed-by: Dave Chinner <dchinner@redhat.com>
1 parent b2ccab3 commit f6b3846

3 files changed

Lines changed: 47 additions & 22 deletions

File tree

fs/xfs/libxfs/xfs_alloc.c

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

24062406
trace_xfs_agfl_free_defer(mp, agno, 0, agbno, 1);
24072407

2408+
xfs_extent_free_get_group(mp, xefi);
24082409
xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_AGFL_FREE, &xefi->xefi_list);
24092410
}
24102411

@@ -2421,8 +2422,8 @@ __xfs_free_extent_later(
24212422
bool skip_discard)
24222423
{
24232424
struct xfs_extent_free_item *xefi;
2424-
#ifdef DEBUG
24252425
struct xfs_mount *mp = tp->t_mountp;
2426+
#ifdef DEBUG
24262427
xfs_agnumber_t agno;
24272428
xfs_agblock_t agbno;
24282429

@@ -2456,9 +2457,11 @@ __xfs_free_extent_later(
24562457
} else {
24572458
xefi->xefi_owner = XFS_RMAP_OWN_NULL;
24582459
}
2459-
trace_xfs_bmap_free_defer(tp->t_mountp,
2460+
trace_xfs_bmap_free_defer(mp,
24602461
XFS_FSB_TO_AGNO(tp->t_mountp, bno), 0,
24612462
XFS_FSB_TO_AGBNO(tp->t_mountp, bno), len);
2463+
2464+
xfs_extent_free_get_group(mp, xefi);
24622465
xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_FREE, &xefi->xefi_list);
24632466
}
24642467

fs/xfs/libxfs/xfs_alloc.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,9 +237,13 @@ struct xfs_extent_free_item {
237237
uint64_t xefi_owner;
238238
xfs_fsblock_t xefi_startblock;/* starting fs block number */
239239
xfs_extlen_t xefi_blockcount;/* number of blocks in extent */
240+
struct xfs_perag *xefi_pag;
240241
unsigned int xefi_flags;
241242
};
242243

244+
void xfs_extent_free_get_group(struct xfs_mount *mp,
245+
struct xfs_extent_free_item *xefi);
246+
243247
#define XFS_EFI_SKIP_DISCARD (1U << 0) /* don't issue discard */
244248
#define XFS_EFI_ATTR_FORK (1U << 1) /* freeing attr fork block */
245249
#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, XFS_AG_RESV_NONE,
367+
error = __xfs_free_extent(tp, xefi->xefi_pag, agbno,
368+
xefi->xefi_blockcount, &oinfo, XFS_AG_RESV_NONE,
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
}
@@ -636,7 +652,9 @@ xfs_efi_item_recover(
636652
fake.xefi_startblock = extp->ext_start;
637653
fake.xefi_blockcount = extp->ext_len;
638654

655+
xfs_extent_free_get_group(mp, &fake);
639656
error = xfs_trans_free_extent(tp, efdp, &fake);
657+
xfs_extent_free_put_group(&fake);
640658
if (error == -EFSCORRUPTED)
641659
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
642660
extp, sizeof(*extp));

0 commit comments

Comments
 (0)