Skip to content

Commit 6a2a9d7

Browse files
Dave ChinnerDarrick J. Wong
authored andcommitted
xfs: pass alloc flags through to xfs_extent_busy_flush()
To avoid blocking in xfs_extent_busy_flush() when freeing extents and the only busy extents are held by the current transaction, we need to pass the XFS_ALLOC_FLAG_FREEING flag context all the way into xfs_extent_busy_flush(). Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Darrick J. Wong <djwong@kernel.org> Reviewed-by: Chandan Babu R <chandan.babu@oracle.com>
1 parent b742d7b commit 6a2a9d7

File tree

4 files changed

+56
-47
lines changed

4 files changed

+56
-47
lines changed

fs/xfs/libxfs/xfs_alloc.c

Lines changed: 52 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1536,7 +1536,8 @@ xfs_alloc_ag_vextent_lastblock(
15361536
*/
15371537
STATIC int
15381538
xfs_alloc_ag_vextent_near(
1539-
struct xfs_alloc_arg *args)
1539+
struct xfs_alloc_arg *args,
1540+
uint32_t alloc_flags)
15401541
{
15411542
struct xfs_alloc_cur acur = {};
15421543
int error; /* error code */
@@ -1612,7 +1613,7 @@ xfs_alloc_ag_vextent_near(
16121613
if (acur.busy) {
16131614
trace_xfs_alloc_near_busy(args);
16141615
xfs_extent_busy_flush(args->mp, args->pag,
1615-
acur.busy_gen);
1616+
acur.busy_gen, alloc_flags);
16161617
goto restart;
16171618
}
16181619
trace_xfs_alloc_size_neither(args);
@@ -1635,21 +1636,22 @@ xfs_alloc_ag_vextent_near(
16351636
* and of the form k * prod + mod unless there's nothing that large.
16361637
* Return the starting a.g. block, or NULLAGBLOCK if we can't do it.
16371638
*/
1638-
STATIC int /* error */
1639+
static int
16391640
xfs_alloc_ag_vextent_size(
1640-
xfs_alloc_arg_t *args) /* allocation argument structure */
1641+
struct xfs_alloc_arg *args,
1642+
uint32_t alloc_flags)
16411643
{
1642-
struct xfs_agf *agf = args->agbp->b_addr;
1643-
struct xfs_btree_cur *bno_cur; /* cursor for bno btree */
1644-
struct xfs_btree_cur *cnt_cur; /* cursor for cnt btree */
1645-
int error; /* error result */
1646-
xfs_agblock_t fbno; /* start of found freespace */
1647-
xfs_extlen_t flen; /* length of found freespace */
1648-
int i; /* temp status variable */
1649-
xfs_agblock_t rbno; /* returned block number */
1650-
xfs_extlen_t rlen; /* length of returned extent */
1651-
bool busy;
1652-
unsigned busy_gen;
1644+
struct xfs_agf *agf = args->agbp->b_addr;
1645+
struct xfs_btree_cur *bno_cur;
1646+
struct xfs_btree_cur *cnt_cur;
1647+
xfs_agblock_t fbno; /* start of found freespace */
1648+
xfs_extlen_t flen; /* length of found freespace */
1649+
xfs_agblock_t rbno; /* returned block number */
1650+
xfs_extlen_t rlen; /* length of returned extent */
1651+
bool busy;
1652+
unsigned busy_gen;
1653+
int error;
1654+
int i;
16531655

16541656
restart:
16551657
/*
@@ -1717,8 +1719,8 @@ xfs_alloc_ag_vextent_size(
17171719
xfs_btree_del_cursor(cnt_cur,
17181720
XFS_BTREE_NOERROR);
17191721
trace_xfs_alloc_size_busy(args);
1720-
xfs_extent_busy_flush(args->mp,
1721-
args->pag, busy_gen);
1722+
xfs_extent_busy_flush(args->mp, args->pag,
1723+
busy_gen, alloc_flags);
17221724
goto restart;
17231725
}
17241726
}
@@ -1802,7 +1804,8 @@ xfs_alloc_ag_vextent_size(
18021804
if (busy) {
18031805
xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR);
18041806
trace_xfs_alloc_size_busy(args);
1805-
xfs_extent_busy_flush(args->mp, args->pag, busy_gen);
1807+
xfs_extent_busy_flush(args->mp, args->pag, busy_gen,
1808+
alloc_flags);
18061809
goto restart;
18071810
}
18081811
goto out_nominleft;
@@ -2572,7 +2575,7 @@ xfs_exact_minlen_extent_available(
25722575
int /* error */
25732576
xfs_alloc_fix_freelist(
25742577
struct xfs_alloc_arg *args, /* allocation argument structure */
2575-
int flags) /* XFS_ALLOC_FLAG_... */
2578+
uint32_t alloc_flags)
25762579
{
25772580
struct xfs_mount *mp = args->mp;
25782581
struct xfs_perag *pag = args->pag;
@@ -2588,7 +2591,7 @@ xfs_alloc_fix_freelist(
25882591
ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES);
25892592

25902593
if (!xfs_perag_initialised_agf(pag)) {
2591-
error = xfs_alloc_read_agf(pag, tp, flags, &agbp);
2594+
error = xfs_alloc_read_agf(pag, tp, alloc_flags, &agbp);
25922595
if (error) {
25932596
/* Couldn't lock the AGF so skip this AG. */
25942597
if (error == -EAGAIN)
@@ -2604,13 +2607,13 @@ xfs_alloc_fix_freelist(
26042607
*/
26052608
if (xfs_perag_prefers_metadata(pag) &&
26062609
(args->datatype & XFS_ALLOC_USERDATA) &&
2607-
(flags & XFS_ALLOC_FLAG_TRYLOCK)) {
2608-
ASSERT(!(flags & XFS_ALLOC_FLAG_FREEING));
2610+
(alloc_flags & XFS_ALLOC_FLAG_TRYLOCK)) {
2611+
ASSERT(!(alloc_flags & XFS_ALLOC_FLAG_FREEING));
26092612
goto out_agbp_relse;
26102613
}
26112614

26122615
need = xfs_alloc_min_freelist(mp, pag);
2613-
if (!xfs_alloc_space_available(args, need, flags |
2616+
if (!xfs_alloc_space_available(args, need, alloc_flags |
26142617
XFS_ALLOC_FLAG_CHECK))
26152618
goto out_agbp_relse;
26162619

@@ -2619,7 +2622,7 @@ xfs_alloc_fix_freelist(
26192622
* Can fail if we're not blocking on locks, and it's held.
26202623
*/
26212624
if (!agbp) {
2622-
error = xfs_alloc_read_agf(pag, tp, flags, &agbp);
2625+
error = xfs_alloc_read_agf(pag, tp, alloc_flags, &agbp);
26232626
if (error) {
26242627
/* Couldn't lock the AGF so skip this AG. */
26252628
if (error == -EAGAIN)
@@ -2634,7 +2637,7 @@ xfs_alloc_fix_freelist(
26342637

26352638
/* If there isn't enough total space or single-extent, reject it. */
26362639
need = xfs_alloc_min_freelist(mp, pag);
2637-
if (!xfs_alloc_space_available(args, need, flags))
2640+
if (!xfs_alloc_space_available(args, need, alloc_flags))
26382641
goto out_agbp_relse;
26392642

26402643
#ifdef DEBUG
@@ -2672,11 +2675,12 @@ xfs_alloc_fix_freelist(
26722675
*/
26732676
memset(&targs, 0, sizeof(targs));
26742677
/* struct copy below */
2675-
if (flags & XFS_ALLOC_FLAG_NORMAP)
2678+
if (alloc_flags & XFS_ALLOC_FLAG_NORMAP)
26762679
targs.oinfo = XFS_RMAP_OINFO_SKIP_UPDATE;
26772680
else
26782681
targs.oinfo = XFS_RMAP_OINFO_AG;
2679-
while (!(flags & XFS_ALLOC_FLAG_NOSHRINK) && pag->pagf_flcount > need) {
2682+
while (!(alloc_flags & XFS_ALLOC_FLAG_NOSHRINK) &&
2683+
pag->pagf_flcount > need) {
26802684
error = xfs_alloc_get_freelist(pag, tp, agbp, &bno, 0);
26812685
if (error)
26822686
goto out_agbp_relse;
@@ -2704,7 +2708,7 @@ xfs_alloc_fix_freelist(
27042708
targs.resv = XFS_AG_RESV_AGFL;
27052709

27062710
/* Allocate as many blocks as possible at once. */
2707-
error = xfs_alloc_ag_vextent_size(&targs);
2711+
error = xfs_alloc_ag_vextent_size(&targs, alloc_flags);
27082712
if (error)
27092713
goto out_agflbp_relse;
27102714

@@ -2714,7 +2718,7 @@ xfs_alloc_fix_freelist(
27142718
* on a completely full ag.
27152719
*/
27162720
if (targs.agbno == NULLAGBLOCK) {
2717-
if (flags & XFS_ALLOC_FLAG_FREEING)
2721+
if (alloc_flags & XFS_ALLOC_FLAG_FREEING)
27182722
break;
27192723
goto out_agflbp_relse;
27202724
}
@@ -3230,7 +3234,7 @@ xfs_alloc_vextent_check_args(
32303234
static int
32313235
xfs_alloc_vextent_prepare_ag(
32323236
struct xfs_alloc_arg *args,
3233-
uint32_t flags)
3237+
uint32_t alloc_flags)
32343238
{
32353239
bool need_pag = !args->pag;
32363240
int error;
@@ -3239,7 +3243,7 @@ xfs_alloc_vextent_prepare_ag(
32393243
args->pag = xfs_perag_get(args->mp, args->agno);
32403244

32413245
args->agbp = NULL;
3242-
error = xfs_alloc_fix_freelist(args, flags);
3246+
error = xfs_alloc_fix_freelist(args, alloc_flags);
32433247
if (error) {
32443248
trace_xfs_alloc_vextent_nofix(args);
32453249
if (need_pag)
@@ -3361,6 +3365,7 @@ xfs_alloc_vextent_this_ag(
33613365
{
33623366
struct xfs_mount *mp = args->mp;
33633367
xfs_agnumber_t minimum_agno;
3368+
uint32_t alloc_flags = 0;
33643369
int error;
33653370

33663371
ASSERT(args->pag != NULL);
@@ -3379,9 +3384,9 @@ xfs_alloc_vextent_this_ag(
33793384
return error;
33803385
}
33813386

3382-
error = xfs_alloc_vextent_prepare_ag(args, 0);
3387+
error = xfs_alloc_vextent_prepare_ag(args, alloc_flags);
33833388
if (!error && args->agbp)
3384-
error = xfs_alloc_ag_vextent_size(args);
3389+
error = xfs_alloc_ag_vextent_size(args, alloc_flags);
33853390

33863391
return xfs_alloc_vextent_finish(args, minimum_agno, error, false);
33873392
}
@@ -3410,20 +3415,20 @@ xfs_alloc_vextent_iterate_ags(
34103415
xfs_agnumber_t minimum_agno,
34113416
xfs_agnumber_t start_agno,
34123417
xfs_agblock_t target_agbno,
3413-
uint32_t flags)
3418+
uint32_t alloc_flags)
34143419
{
34153420
struct xfs_mount *mp = args->mp;
34163421
xfs_agnumber_t restart_agno = minimum_agno;
34173422
xfs_agnumber_t agno;
34183423
int error = 0;
34193424

3420-
if (flags & XFS_ALLOC_FLAG_TRYLOCK)
3425+
if (alloc_flags & XFS_ALLOC_FLAG_TRYLOCK)
34213426
restart_agno = 0;
34223427
restart:
34233428
for_each_perag_wrap_range(mp, start_agno, restart_agno,
34243429
mp->m_sb.sb_agcount, agno, args->pag) {
34253430
args->agno = agno;
3426-
error = xfs_alloc_vextent_prepare_ag(args, flags);
3431+
error = xfs_alloc_vextent_prepare_ag(args, alloc_flags);
34273432
if (error)
34283433
break;
34293434
if (!args->agbp) {
@@ -3437,10 +3442,10 @@ xfs_alloc_vextent_iterate_ags(
34373442
*/
34383443
if (args->agno == start_agno && target_agbno) {
34393444
args->agbno = target_agbno;
3440-
error = xfs_alloc_ag_vextent_near(args);
3445+
error = xfs_alloc_ag_vextent_near(args, alloc_flags);
34413446
} else {
34423447
args->agbno = 0;
3443-
error = xfs_alloc_ag_vextent_size(args);
3448+
error = xfs_alloc_ag_vextent_size(args, alloc_flags);
34443449
}
34453450
break;
34463451
}
@@ -3457,8 +3462,8 @@ xfs_alloc_vextent_iterate_ags(
34573462
* constraining flags by the caller, drop them and retry the allocation
34583463
* without any constraints being set.
34593464
*/
3460-
if (flags) {
3461-
flags = 0;
3465+
if (alloc_flags & XFS_ALLOC_FLAG_TRYLOCK) {
3466+
alloc_flags &= ~XFS_ALLOC_FLAG_TRYLOCK;
34623467
restart_agno = minimum_agno;
34633468
goto restart;
34643469
}
@@ -3486,6 +3491,7 @@ xfs_alloc_vextent_start_ag(
34863491
xfs_agnumber_t start_agno;
34873492
xfs_agnumber_t rotorstep = xfs_rotorstep;
34883493
bool bump_rotor = false;
3494+
uint32_t alloc_flags = XFS_ALLOC_FLAG_TRYLOCK;
34893495
int error;
34903496

34913497
ASSERT(args->pag == NULL);
@@ -3512,7 +3518,7 @@ xfs_alloc_vextent_start_ag(
35123518

35133519
start_agno = max(minimum_agno, XFS_FSB_TO_AGNO(mp, target));
35143520
error = xfs_alloc_vextent_iterate_ags(args, minimum_agno, start_agno,
3515-
XFS_FSB_TO_AGBNO(mp, target), XFS_ALLOC_FLAG_TRYLOCK);
3521+
XFS_FSB_TO_AGBNO(mp, target), alloc_flags);
35163522

35173523
if (bump_rotor) {
35183524
if (args->agno == start_agno)
@@ -3539,6 +3545,7 @@ xfs_alloc_vextent_first_ag(
35393545
struct xfs_mount *mp = args->mp;
35403546
xfs_agnumber_t minimum_agno;
35413547
xfs_agnumber_t start_agno;
3548+
uint32_t alloc_flags = XFS_ALLOC_FLAG_TRYLOCK;
35423549
int error;
35433550

35443551
ASSERT(args->pag == NULL);
@@ -3557,7 +3564,7 @@ xfs_alloc_vextent_first_ag(
35573564

35583565
start_agno = max(minimum_agno, XFS_FSB_TO_AGNO(mp, target));
35593566
error = xfs_alloc_vextent_iterate_ags(args, minimum_agno, start_agno,
3560-
XFS_FSB_TO_AGBNO(mp, target), 0);
3567+
XFS_FSB_TO_AGBNO(mp, target), alloc_flags);
35613568
return xfs_alloc_vextent_finish(args, minimum_agno, error, true);
35623569
}
35633570

@@ -3610,6 +3617,7 @@ xfs_alloc_vextent_near_bno(
36103617
struct xfs_mount *mp = args->mp;
36113618
xfs_agnumber_t minimum_agno;
36123619
bool needs_perag = args->pag == NULL;
3620+
uint32_t alloc_flags = 0;
36133621
int error;
36143622

36153623
if (!needs_perag)
@@ -3630,9 +3638,9 @@ xfs_alloc_vextent_near_bno(
36303638
if (needs_perag)
36313639
args->pag = xfs_perag_grab(mp, args->agno);
36323640

3633-
error = xfs_alloc_vextent_prepare_ag(args, 0);
3641+
error = xfs_alloc_vextent_prepare_ag(args, alloc_flags);
36343642
if (!error && args->agbp)
3635-
error = xfs_alloc_ag_vextent_near(args);
3643+
error = xfs_alloc_ag_vextent_near(args, alloc_flags);
36363644

36373645
return xfs_alloc_vextent_finish(args, minimum_agno, error, needs_perag);
36383646
}

fs/xfs/libxfs/xfs_alloc.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ int xfs_alloc_read_agfl(struct xfs_perag *pag, struct xfs_trans *tp,
195195
struct xfs_buf **bpp);
196196
int xfs_free_agfl_block(struct xfs_trans *, xfs_agnumber_t, xfs_agblock_t,
197197
struct xfs_buf *, struct xfs_owner_info *);
198-
int xfs_alloc_fix_freelist(struct xfs_alloc_arg *args, int flags);
198+
int xfs_alloc_fix_freelist(struct xfs_alloc_arg *args, uint32_t alloc_flags);
199199
int xfs_free_extent_fix_freelist(struct xfs_trans *tp, struct xfs_perag *pag,
200200
struct xfs_buf **agbp);
201201

fs/xfs/xfs_extent_busy.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,8 @@ void
571571
xfs_extent_busy_flush(
572572
struct xfs_mount *mp,
573573
struct xfs_perag *pag,
574-
unsigned busy_gen)
574+
unsigned busy_gen,
575+
uint32_t alloc_flags)
575576
{
576577
DEFINE_WAIT (wait);
577578
int error;

fs/xfs/xfs_extent_busy.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ xfs_extent_busy_trim(struct xfs_alloc_arg *args, xfs_agblock_t *bno,
5353

5454
void
5555
xfs_extent_busy_flush(struct xfs_mount *mp, struct xfs_perag *pag,
56-
unsigned busy_gen);
56+
unsigned busy_gen, uint32_t alloc_flags);
5757

5858
void
5959
xfs_extent_busy_wait_all(struct xfs_mount *mp);

0 commit comments

Comments
 (0)