diff options
author | Christoph Hellwig <hch@lst.de> | 2014-04-22 17:11:41 -0400 |
---|---|---|
committer | Dave Chinner <david@fromorbit.com> | 2014-04-22 17:11:41 -0400 |
commit | c977eb1065612bf64e18c61437e290c22183add8 (patch) | |
tree | a9e9fea73c5d80cffaf5fe3fd8063a30fe364229 | |
parent | 8b90a33f476436ad6a49b7138d8a00ecbc62f9a6 (diff) |
xfs: split xfs_bmap_btalloc_nullfb
Split xfs_bmap_btalloc_nullfb into one function for filestream allocations
and one for everything else that share a few helpers. This dramatically
simplifies the control flow.
Signed-off-by: Christoph Hellwig <hch@lst.de>
-rw-r--r-- | fs/xfs/xfs_bmap.c | 200 |
1 files changed, 117 insertions, 83 deletions
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 38e88a01b447..b0758656c1c3 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c | |||
@@ -3517,6 +3517,67 @@ xfs_bmap_adjacent( | |||
3517 | #undef ISVALID | 3517 | #undef ISVALID |
3518 | } | 3518 | } |
3519 | 3519 | ||
3520 | static int | ||
3521 | xfs_bmap_longest_free_extent( | ||
3522 | struct xfs_trans *tp, | ||
3523 | xfs_agnumber_t ag, | ||
3524 | xfs_extlen_t *blen, | ||
3525 | int *notinit) | ||
3526 | { | ||
3527 | struct xfs_mount *mp = tp->t_mountp; | ||
3528 | struct xfs_perag *pag; | ||
3529 | xfs_extlen_t longest; | ||
3530 | int error = 0; | ||
3531 | |||
3532 | pag = xfs_perag_get(mp, ag); | ||
3533 | if (!pag->pagf_init) { | ||
3534 | error = xfs_alloc_pagf_init(mp, tp, ag, XFS_ALLOC_FLAG_TRYLOCK); | ||
3535 | if (error) | ||
3536 | goto out; | ||
3537 | |||
3538 | if (!pag->pagf_init) { | ||
3539 | *notinit = 1; | ||
3540 | goto out; | ||
3541 | } | ||
3542 | } | ||
3543 | |||
3544 | longest = xfs_alloc_longest_free_extent(mp, pag); | ||
3545 | if (*blen < longest) | ||
3546 | *blen = longest; | ||
3547 | |||
3548 | out: | ||
3549 | xfs_perag_put(pag); | ||
3550 | return error; | ||
3551 | } | ||
3552 | |||
3553 | static void | ||
3554 | xfs_bmap_select_minlen( | ||
3555 | struct xfs_bmalloca *ap, | ||
3556 | struct xfs_alloc_arg *args, | ||
3557 | xfs_extlen_t *blen, | ||
3558 | int notinit) | ||
3559 | { | ||
3560 | if (notinit || *blen < ap->minlen) { | ||
3561 | /* | ||
3562 | * Since we did a BUF_TRYLOCK above, it is possible that | ||
3563 | * there is space for this request. | ||
3564 | */ | ||
3565 | args->minlen = ap->minlen; | ||
3566 | } else if (*blen < args->maxlen) { | ||
3567 | /* | ||
3568 | * If the best seen length is less than the request length, | ||
3569 | * use the best as the minimum. | ||
3570 | */ | ||
3571 | args->minlen = *blen; | ||
3572 | } else { | ||
3573 | /* | ||
3574 | * Otherwise we've seen an extent as big as maxlen, use that | ||
3575 | * as the minimum. | ||
3576 | */ | ||
3577 | args->minlen = args->maxlen; | ||
3578 | } | ||
3579 | } | ||
3580 | |||
3520 | STATIC int | 3581 | STATIC int |
3521 | xfs_bmap_btalloc_nullfb( | 3582 | xfs_bmap_btalloc_nullfb( |
3522 | struct xfs_bmalloca *ap, | 3583 | struct xfs_bmalloca *ap, |
@@ -3524,109 +3585,74 @@ xfs_bmap_btalloc_nullfb( | |||
3524 | xfs_extlen_t *blen) | 3585 | xfs_extlen_t *blen) |
3525 | { | 3586 | { |
3526 | struct xfs_mount *mp = ap->ip->i_mount; | 3587 | struct xfs_mount *mp = ap->ip->i_mount; |
3527 | struct xfs_perag *pag; | ||
3528 | xfs_agnumber_t ag, startag; | 3588 | xfs_agnumber_t ag, startag; |
3529 | int notinit = 0; | 3589 | int notinit = 0; |
3530 | int error; | 3590 | int error; |
3531 | 3591 | ||
3532 | if (ap->userdata && xfs_inode_is_filestream(ap->ip)) | 3592 | args->type = XFS_ALLOCTYPE_START_BNO; |
3533 | args->type = XFS_ALLOCTYPE_NEAR_BNO; | ||
3534 | else | ||
3535 | args->type = XFS_ALLOCTYPE_START_BNO; | ||
3536 | args->total = ap->total; | 3593 | args->total = ap->total; |
3537 | 3594 | ||
3538 | /* | ||
3539 | * Search for an allocation group with a single extent large enough | ||
3540 | * for the request. If one isn't found, then adjust the minimum | ||
3541 | * allocation size to the largest space found. | ||
3542 | */ | ||
3543 | startag = ag = XFS_FSB_TO_AGNO(mp, args->fsbno); | 3595 | startag = ag = XFS_FSB_TO_AGNO(mp, args->fsbno); |
3544 | if (startag == NULLAGNUMBER) | 3596 | if (startag == NULLAGNUMBER) |
3545 | startag = ag = 0; | 3597 | startag = ag = 0; |
3546 | 3598 | ||
3547 | pag = xfs_perag_get(mp, ag); | ||
3548 | while (*blen < args->maxlen) { | 3599 | while (*blen < args->maxlen) { |
3549 | if (!pag->pagf_init) { | 3600 | error = xfs_bmap_longest_free_extent(args->tp, ag, blen, |
3550 | error = xfs_alloc_pagf_init(mp, args->tp, ag, | 3601 | ¬init); |
3551 | XFS_ALLOC_FLAG_TRYLOCK); | 3602 | if (error) |
3552 | if (error) { | 3603 | return error; |
3553 | xfs_perag_put(pag); | ||
3554 | return error; | ||
3555 | } | ||
3556 | } | ||
3557 | |||
3558 | /* | ||
3559 | * See xfs_alloc_fix_freelist... | ||
3560 | */ | ||
3561 | if (pag->pagf_init) { | ||
3562 | xfs_extlen_t longest; | ||
3563 | longest = xfs_alloc_longest_free_extent(mp, pag); | ||
3564 | if (*blen < longest) | ||
3565 | *blen = longest; | ||
3566 | } else | ||
3567 | notinit = 1; | ||
3568 | |||
3569 | if (xfs_inode_is_filestream(ap->ip) && ap->userdata) { | ||
3570 | if (*blen >= args->maxlen) | ||
3571 | break; | ||
3572 | |||
3573 | /* | ||
3574 | * If startag is an invalid AG, we've | ||
3575 | * come here once before and | ||
3576 | * xfs_filestream_new_ag picked the | ||
3577 | * best currently available. | ||
3578 | * | ||
3579 | * Don't continue looping, since we | ||
3580 | * could loop forever. | ||
3581 | */ | ||
3582 | if (startag == NULLAGNUMBER) | ||
3583 | break; | ||
3584 | |||
3585 | error = xfs_filestream_new_ag(ap, &ag); | ||
3586 | xfs_perag_put(pag); | ||
3587 | if (error) | ||
3588 | return error; | ||
3589 | 3604 | ||
3590 | /* loop again to set 'blen'*/ | ||
3591 | startag = NULLAGNUMBER; | ||
3592 | pag = xfs_perag_get(mp, ag); | ||
3593 | continue; | ||
3594 | } | ||
3595 | if (++ag == mp->m_sb.sb_agcount) | 3605 | if (++ag == mp->m_sb.sb_agcount) |
3596 | ag = 0; | 3606 | ag = 0; |
3597 | if (ag == startag) | 3607 | if (ag == startag) |
3598 | break; | 3608 | break; |
3599 | xfs_perag_put(pag); | ||
3600 | pag = xfs_perag_get(mp, ag); | ||
3601 | } | 3609 | } |
3602 | xfs_perag_put(pag); | ||
3603 | 3610 | ||
3604 | /* | 3611 | xfs_bmap_select_minlen(ap, args, blen, notinit); |
3605 | * Since the above loop did a BUF_TRYLOCK, it is | 3612 | return 0; |
3606 | * possible that there is space for this request. | 3613 | } |
3607 | */ | 3614 | |
3608 | if (notinit || *blen < ap->minlen) | 3615 | STATIC int |
3609 | args->minlen = ap->minlen; | 3616 | xfs_bmap_btalloc_filestreams( |
3610 | /* | 3617 | struct xfs_bmalloca *ap, |
3611 | * If the best seen length is less than the request | 3618 | struct xfs_alloc_arg *args, |
3612 | * length, use the best as the minimum. | 3619 | xfs_extlen_t *blen) |
3613 | */ | 3620 | { |
3614 | else if (*blen < args->maxlen) | 3621 | struct xfs_mount *mp = ap->ip->i_mount; |
3615 | args->minlen = *blen; | 3622 | xfs_agnumber_t ag; |
3616 | /* | 3623 | int notinit = 0; |
3617 | * Otherwise we've seen an extent as big as maxlen, | 3624 | int error; |
3618 | * use that as the minimum. | 3625 | |
3619 | */ | 3626 | args->type = XFS_ALLOCTYPE_NEAR_BNO; |
3620 | else | 3627 | args->total = ap->total; |
3621 | args->minlen = args->maxlen; | 3628 | |
3629 | ag = XFS_FSB_TO_AGNO(mp, args->fsbno); | ||
3630 | if (ag == NULLAGNUMBER) | ||
3631 | ag = 0; | ||
3632 | |||
3633 | error = xfs_bmap_longest_free_extent(args->tp, ag, blen, ¬init); | ||
3634 | if (error) | ||
3635 | return error; | ||
3636 | |||
3637 | if (*blen < args->maxlen) { | ||
3638 | error = xfs_filestream_new_ag(ap, &ag); | ||
3639 | if (error) | ||
3640 | return error; | ||
3641 | |||
3642 | error = xfs_bmap_longest_free_extent(args->tp, ag, blen, | ||
3643 | ¬init); | ||
3644 | if (error) | ||
3645 | return error; | ||
3646 | |||
3647 | } | ||
3648 | |||
3649 | xfs_bmap_select_minlen(ap, args, blen, notinit); | ||
3622 | 3650 | ||
3623 | /* | 3651 | /* |
3624 | * set the failure fallback case to look in the selected | 3652 | * Set the failure fallback case to look in the selected AG as stream |
3625 | * AG as the stream may have moved. | 3653 | * may have moved. |
3626 | */ | 3654 | */ |
3627 | if (xfs_inode_is_filestream(ap->ip)) | 3655 | ap->blkno = args->fsbno = XFS_AGB_TO_FSB(mp, ag, 0); |
3628 | ap->blkno = args->fsbno = XFS_AGB_TO_FSB(mp, ag, 0); | ||
3629 | |||
3630 | return 0; | 3656 | return 0; |
3631 | } | 3657 | } |
3632 | 3658 | ||
@@ -3706,7 +3732,15 @@ xfs_bmap_btalloc( | |||
3706 | args.firstblock = *ap->firstblock; | 3732 | args.firstblock = *ap->firstblock; |
3707 | blen = 0; | 3733 | blen = 0; |
3708 | if (nullfb) { | 3734 | if (nullfb) { |
3709 | error = xfs_bmap_btalloc_nullfb(ap, &args, &blen); | 3735 | /* |
3736 | * Search for an allocation group with a single extent large | ||
3737 | * enough for the request. If one isn't found, then adjust | ||
3738 | * the minimum allocation size to the largest space found. | ||
3739 | */ | ||
3740 | if (ap->userdata && xfs_inode_is_filestream(ap->ip)) | ||
3741 | error = xfs_bmap_btalloc_filestreams(ap, &args, &blen); | ||
3742 | else | ||
3743 | error = xfs_bmap_btalloc_nullfb(ap, &args, &blen); | ||
3710 | if (error) | 3744 | if (error) |
3711 | return error; | 3745 | return error; |
3712 | } else if (ap->flist->xbf_low) { | 3746 | } else if (ap->flist->xbf_low) { |