diff options
Diffstat (limited to 'fs/xfs/libxfs/xfs_alloc.c')
-rw-r--r-- | fs/xfs/libxfs/xfs_alloc.c | 115 |
1 files changed, 28 insertions, 87 deletions
diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 5050056a0b06..9f06a211e157 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c | |||
@@ -95,10 +95,7 @@ unsigned int | |||
95 | xfs_alloc_set_aside( | 95 | xfs_alloc_set_aside( |
96 | struct xfs_mount *mp) | 96 | struct xfs_mount *mp) |
97 | { | 97 | { |
98 | unsigned int blocks; | 98 | return mp->m_sb.sb_agcount * (XFS_ALLOC_AGFL_RESERVE + 4); |
99 | |||
100 | blocks = 4 + (mp->m_sb.sb_agcount * XFS_ALLOC_AGFL_RESERVE); | ||
101 | return blocks; | ||
102 | } | 99 | } |
103 | 100 | ||
104 | /* | 101 | /* |
@@ -365,36 +362,12 @@ xfs_alloc_fix_len( | |||
365 | return; | 362 | return; |
366 | ASSERT(rlen >= args->minlen && rlen <= args->maxlen); | 363 | ASSERT(rlen >= args->minlen && rlen <= args->maxlen); |
367 | ASSERT(rlen % args->prod == args->mod); | 364 | ASSERT(rlen % args->prod == args->mod); |
365 | ASSERT(args->pag->pagf_freeblks + args->pag->pagf_flcount >= | ||
366 | rlen + args->minleft); | ||
368 | args->len = rlen; | 367 | args->len = rlen; |
369 | } | 368 | } |
370 | 369 | ||
371 | /* | 370 | /* |
372 | * Fix up length if there is too little space left in the a.g. | ||
373 | * Return 1 if ok, 0 if too little, should give up. | ||
374 | */ | ||
375 | STATIC int | ||
376 | xfs_alloc_fix_minleft( | ||
377 | xfs_alloc_arg_t *args) /* allocation argument structure */ | ||
378 | { | ||
379 | xfs_agf_t *agf; /* a.g. freelist header */ | ||
380 | int diff; /* free space difference */ | ||
381 | |||
382 | if (args->minleft == 0) | ||
383 | return 1; | ||
384 | agf = XFS_BUF_TO_AGF(args->agbp); | ||
385 | diff = be32_to_cpu(agf->agf_freeblks) | ||
386 | - args->len - args->minleft; | ||
387 | if (diff >= 0) | ||
388 | return 1; | ||
389 | args->len += diff; /* shrink the allocated space */ | ||
390 | /* casts to (int) catch length underflows */ | ||
391 | if ((int)args->len >= (int)args->minlen) | ||
392 | return 1; | ||
393 | args->agbno = NULLAGBLOCK; | ||
394 | return 0; | ||
395 | } | ||
396 | |||
397 | /* | ||
398 | * Update the two btrees, logically removing from freespace the extent | 371 | * Update the two btrees, logically removing from freespace the extent |
399 | * starting at rbno, rlen blocks. The extent is contained within the | 372 | * starting at rbno, rlen blocks. The extent is contained within the |
400 | * actual (current) free extent fbno for flen blocks. | 373 | * actual (current) free extent fbno for flen blocks. |
@@ -689,8 +662,6 @@ xfs_alloc_ag_vextent( | |||
689 | xfs_alloc_arg_t *args) /* argument structure for allocation */ | 662 | xfs_alloc_arg_t *args) /* argument structure for allocation */ |
690 | { | 663 | { |
691 | int error=0; | 664 | int error=0; |
692 | xfs_extlen_t reservation; | ||
693 | xfs_extlen_t oldmax; | ||
694 | 665 | ||
695 | ASSERT(args->minlen > 0); | 666 | ASSERT(args->minlen > 0); |
696 | ASSERT(args->maxlen > 0); | 667 | ASSERT(args->maxlen > 0); |
@@ -699,20 +670,6 @@ xfs_alloc_ag_vextent( | |||
699 | ASSERT(args->alignment > 0); | 670 | ASSERT(args->alignment > 0); |
700 | 671 | ||
701 | /* | 672 | /* |
702 | * Clamp maxlen to the amount of free space minus any reservations | ||
703 | * that have been made. | ||
704 | */ | ||
705 | oldmax = args->maxlen; | ||
706 | reservation = xfs_ag_resv_needed(args->pag, args->resv); | ||
707 | if (args->maxlen > args->pag->pagf_freeblks - reservation) | ||
708 | args->maxlen = args->pag->pagf_freeblks - reservation; | ||
709 | if (args->maxlen == 0) { | ||
710 | args->agbno = NULLAGBLOCK; | ||
711 | args->maxlen = oldmax; | ||
712 | return 0; | ||
713 | } | ||
714 | |||
715 | /* | ||
716 | * Branch to correct routine based on the type. | 673 | * Branch to correct routine based on the type. |
717 | */ | 674 | */ |
718 | args->wasfromfl = 0; | 675 | args->wasfromfl = 0; |
@@ -731,8 +688,6 @@ xfs_alloc_ag_vextent( | |||
731 | /* NOTREACHED */ | 688 | /* NOTREACHED */ |
732 | } | 689 | } |
733 | 690 | ||
734 | args->maxlen = oldmax; | ||
735 | |||
736 | if (error || args->agbno == NULLAGBLOCK) | 691 | if (error || args->agbno == NULLAGBLOCK) |
737 | return error; | 692 | return error; |
738 | 693 | ||
@@ -841,9 +796,6 @@ xfs_alloc_ag_vextent_exact( | |||
841 | args->len = XFS_AGBLOCK_MIN(tend, args->agbno + args->maxlen) | 796 | args->len = XFS_AGBLOCK_MIN(tend, args->agbno + args->maxlen) |
842 | - args->agbno; | 797 | - args->agbno; |
843 | xfs_alloc_fix_len(args); | 798 | xfs_alloc_fix_len(args); |
844 | if (!xfs_alloc_fix_minleft(args)) | ||
845 | goto not_found; | ||
846 | |||
847 | ASSERT(args->agbno + args->len <= tend); | 799 | ASSERT(args->agbno + args->len <= tend); |
848 | 800 | ||
849 | /* | 801 | /* |
@@ -1149,12 +1101,7 @@ restart: | |||
1149 | XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); | 1101 | XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); |
1150 | ASSERT(ltbno + ltlen <= be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length)); | 1102 | ASSERT(ltbno + ltlen <= be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length)); |
1151 | args->len = blen; | 1103 | args->len = blen; |
1152 | if (!xfs_alloc_fix_minleft(args)) { | 1104 | |
1153 | xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); | ||
1154 | trace_xfs_alloc_near_nominleft(args); | ||
1155 | return 0; | ||
1156 | } | ||
1157 | blen = args->len; | ||
1158 | /* | 1105 | /* |
1159 | * We are allocating starting at bnew for blen blocks. | 1106 | * We are allocating starting at bnew for blen blocks. |
1160 | */ | 1107 | */ |
@@ -1346,12 +1293,6 @@ restart: | |||
1346 | */ | 1293 | */ |
1347 | args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen); | 1294 | args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen); |
1348 | xfs_alloc_fix_len(args); | 1295 | xfs_alloc_fix_len(args); |
1349 | if (!xfs_alloc_fix_minleft(args)) { | ||
1350 | trace_xfs_alloc_near_nominleft(args); | ||
1351 | xfs_btree_del_cursor(bno_cur_lt, XFS_BTREE_NOERROR); | ||
1352 | xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); | ||
1353 | return 0; | ||
1354 | } | ||
1355 | rlen = args->len; | 1296 | rlen = args->len; |
1356 | (void)xfs_alloc_compute_diff(args->agbno, rlen, args->alignment, | 1297 | (void)xfs_alloc_compute_diff(args->agbno, rlen, args->alignment, |
1357 | args->datatype, ltbnoa, ltlena, <new); | 1298 | args->datatype, ltbnoa, ltlena, <new); |
@@ -1553,8 +1494,6 @@ restart: | |||
1553 | } | 1494 | } |
1554 | xfs_alloc_fix_len(args); | 1495 | xfs_alloc_fix_len(args); |
1555 | 1496 | ||
1556 | if (!xfs_alloc_fix_minleft(args)) | ||
1557 | goto out_nominleft; | ||
1558 | rlen = args->len; | 1497 | rlen = args->len; |
1559 | XFS_WANT_CORRUPTED_GOTO(args->mp, rlen <= flen, error0); | 1498 | XFS_WANT_CORRUPTED_GOTO(args->mp, rlen <= flen, error0); |
1560 | /* | 1499 | /* |
@@ -2056,7 +1995,7 @@ xfs_alloc_space_available( | |||
2056 | int flags) | 1995 | int flags) |
2057 | { | 1996 | { |
2058 | struct xfs_perag *pag = args->pag; | 1997 | struct xfs_perag *pag = args->pag; |
2059 | xfs_extlen_t longest; | 1998 | xfs_extlen_t alloc_len, longest; |
2060 | xfs_extlen_t reservation; /* blocks that are still reserved */ | 1999 | xfs_extlen_t reservation; /* blocks that are still reserved */ |
2061 | int available; | 2000 | int available; |
2062 | 2001 | ||
@@ -2066,17 +2005,28 @@ xfs_alloc_space_available( | |||
2066 | reservation = xfs_ag_resv_needed(pag, args->resv); | 2005 | reservation = xfs_ag_resv_needed(pag, args->resv); |
2067 | 2006 | ||
2068 | /* do we have enough contiguous free space for the allocation? */ | 2007 | /* do we have enough contiguous free space for the allocation? */ |
2008 | alloc_len = args->minlen + (args->alignment - 1) + args->minalignslop; | ||
2069 | longest = xfs_alloc_longest_free_extent(args->mp, pag, min_free, | 2009 | longest = xfs_alloc_longest_free_extent(args->mp, pag, min_free, |
2070 | reservation); | 2010 | reservation); |
2071 | if ((args->minlen + args->alignment + args->minalignslop - 1) > longest) | 2011 | if (longest < alloc_len) |
2072 | return false; | 2012 | return false; |
2073 | 2013 | ||
2074 | /* do we have enough free space remaining for the allocation? */ | 2014 | /* do we have enough free space remaining for the allocation? */ |
2075 | available = (int)(pag->pagf_freeblks + pag->pagf_flcount - | 2015 | available = (int)(pag->pagf_freeblks + pag->pagf_flcount - |
2076 | reservation - min_free - args->total); | 2016 | reservation - min_free - args->minleft); |
2077 | if (available < (int)args->minleft || available <= 0) | 2017 | if (available < (int)max(args->total, alloc_len)) |
2078 | return false; | 2018 | return false; |
2079 | 2019 | ||
2020 | /* | ||
2021 | * Clamp maxlen to the amount of free space available for the actual | ||
2022 | * extent allocation. | ||
2023 | */ | ||
2024 | if (available < (int)args->maxlen && !(flags & XFS_ALLOC_FLAG_CHECK)) { | ||
2025 | args->maxlen = available; | ||
2026 | ASSERT(args->maxlen > 0); | ||
2027 | ASSERT(args->maxlen >= args->minlen); | ||
2028 | } | ||
2029 | |||
2080 | return true; | 2030 | return true; |
2081 | } | 2031 | } |
2082 | 2032 | ||
@@ -2122,7 +2072,8 @@ xfs_alloc_fix_freelist( | |||
2122 | } | 2072 | } |
2123 | 2073 | ||
2124 | need = xfs_alloc_min_freelist(mp, pag); | 2074 | need = xfs_alloc_min_freelist(mp, pag); |
2125 | if (!xfs_alloc_space_available(args, need, flags)) | 2075 | if (!xfs_alloc_space_available(args, need, flags | |
2076 | XFS_ALLOC_FLAG_CHECK)) | ||
2126 | goto out_agbp_relse; | 2077 | goto out_agbp_relse; |
2127 | 2078 | ||
2128 | /* | 2079 | /* |
@@ -2638,12 +2589,10 @@ xfs_alloc_vextent( | |||
2638 | xfs_agblock_t agsize; /* allocation group size */ | 2589 | xfs_agblock_t agsize; /* allocation group size */ |
2639 | int error; | 2590 | int error; |
2640 | int flags; /* XFS_ALLOC_FLAG_... locking flags */ | 2591 | int flags; /* XFS_ALLOC_FLAG_... locking flags */ |
2641 | xfs_extlen_t minleft;/* minimum left value, temp copy */ | ||
2642 | xfs_mount_t *mp; /* mount structure pointer */ | 2592 | xfs_mount_t *mp; /* mount structure pointer */ |
2643 | xfs_agnumber_t sagno; /* starting allocation group number */ | 2593 | xfs_agnumber_t sagno; /* starting allocation group number */ |
2644 | xfs_alloctype_t type; /* input allocation type */ | 2594 | xfs_alloctype_t type; /* input allocation type */ |
2645 | int bump_rotor = 0; | 2595 | int bump_rotor = 0; |
2646 | int no_min = 0; | ||
2647 | xfs_agnumber_t rotorstep = xfs_rotorstep; /* inode32 agf stepper */ | 2596 | xfs_agnumber_t rotorstep = xfs_rotorstep; /* inode32 agf stepper */ |
2648 | 2597 | ||
2649 | mp = args->mp; | 2598 | mp = args->mp; |
@@ -2672,7 +2621,6 @@ xfs_alloc_vextent( | |||
2672 | trace_xfs_alloc_vextent_badargs(args); | 2621 | trace_xfs_alloc_vextent_badargs(args); |
2673 | return 0; | 2622 | return 0; |
2674 | } | 2623 | } |
2675 | minleft = args->minleft; | ||
2676 | 2624 | ||
2677 | switch (type) { | 2625 | switch (type) { |
2678 | case XFS_ALLOCTYPE_THIS_AG: | 2626 | case XFS_ALLOCTYPE_THIS_AG: |
@@ -2683,9 +2631,7 @@ xfs_alloc_vextent( | |||
2683 | */ | 2631 | */ |
2684 | args->agno = XFS_FSB_TO_AGNO(mp, args->fsbno); | 2632 | args->agno = XFS_FSB_TO_AGNO(mp, args->fsbno); |
2685 | args->pag = xfs_perag_get(mp, args->agno); | 2633 | args->pag = xfs_perag_get(mp, args->agno); |
2686 | args->minleft = 0; | ||
2687 | error = xfs_alloc_fix_freelist(args, 0); | 2634 | error = xfs_alloc_fix_freelist(args, 0); |
2688 | args->minleft = minleft; | ||
2689 | if (error) { | 2635 | if (error) { |
2690 | trace_xfs_alloc_vextent_nofix(args); | 2636 | trace_xfs_alloc_vextent_nofix(args); |
2691 | goto error0; | 2637 | goto error0; |
@@ -2750,9 +2696,7 @@ xfs_alloc_vextent( | |||
2750 | */ | 2696 | */ |
2751 | for (;;) { | 2697 | for (;;) { |
2752 | args->pag = xfs_perag_get(mp, args->agno); | 2698 | args->pag = xfs_perag_get(mp, args->agno); |
2753 | if (no_min) args->minleft = 0; | ||
2754 | error = xfs_alloc_fix_freelist(args, flags); | 2699 | error = xfs_alloc_fix_freelist(args, flags); |
2755 | args->minleft = minleft; | ||
2756 | if (error) { | 2700 | if (error) { |
2757 | trace_xfs_alloc_vextent_nofix(args); | 2701 | trace_xfs_alloc_vextent_nofix(args); |
2758 | goto error0; | 2702 | goto error0; |
@@ -2792,20 +2736,17 @@ xfs_alloc_vextent( | |||
2792 | * or switch to non-trylock mode. | 2736 | * or switch to non-trylock mode. |
2793 | */ | 2737 | */ |
2794 | if (args->agno == sagno) { | 2738 | if (args->agno == sagno) { |
2795 | if (no_min == 1) { | 2739 | if (flags == 0) { |
2796 | args->agbno = NULLAGBLOCK; | 2740 | args->agbno = NULLAGBLOCK; |
2797 | trace_xfs_alloc_vextent_allfailed(args); | 2741 | trace_xfs_alloc_vextent_allfailed(args); |
2798 | break; | 2742 | break; |
2799 | } | 2743 | } |
2800 | if (flags == 0) { | 2744 | |
2801 | no_min = 1; | 2745 | flags = 0; |
2802 | } else { | 2746 | if (type == XFS_ALLOCTYPE_START_BNO) { |
2803 | flags = 0; | 2747 | args->agbno = XFS_FSB_TO_AGBNO(mp, |
2804 | if (type == XFS_ALLOCTYPE_START_BNO) { | 2748 | args->fsbno); |
2805 | args->agbno = XFS_FSB_TO_AGBNO(mp, | 2749 | args->type = XFS_ALLOCTYPE_NEAR_BNO; |
2806 | args->fsbno); | ||
2807 | args->type = XFS_ALLOCTYPE_NEAR_BNO; | ||
2808 | } | ||
2809 | } | 2750 | } |
2810 | } | 2751 | } |
2811 | xfs_perag_put(args->pag); | 2752 | xfs_perag_put(args->pag); |