aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2014-04-22 17:11:41 -0400
committerDave Chinner <david@fromorbit.com>2014-04-22 17:11:41 -0400
commitc977eb1065612bf64e18c61437e290c22183add8 (patch)
treea9e9fea73c5d80cffaf5fe3fd8063a30fe364229
parent8b90a33f476436ad6a49b7138d8a00ecbc62f9a6 (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.c200
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
3520static int
3521xfs_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
3548out:
3549 xfs_perag_put(pag);
3550 return error;
3551}
3552
3553static void
3554xfs_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
3520STATIC int 3581STATIC int
3521xfs_bmap_btalloc_nullfb( 3582xfs_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 &notinit);
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) 3615STATIC int
3609 args->minlen = ap->minlen; 3616xfs_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, &notinit);
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 &notinit);
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) {