diff options
| -rw-r--r-- | fs/xfs/xfs_alloc.h | 16 | ||||
| -rw-r--r-- | fs/xfs/xfs_bmap.c | 18 |
2 files changed, 26 insertions, 8 deletions
diff --git a/fs/xfs/xfs_alloc.h b/fs/xfs/xfs_alloc.h index 0ab56b32c7e..d0b3bc72005 100644 --- a/fs/xfs/xfs_alloc.h +++ b/fs/xfs/xfs_alloc.h | |||
| @@ -75,6 +75,22 @@ typedef unsigned int xfs_alloctype_t; | |||
| 75 | #define XFS_ALLOC_SET_ASIDE(mp) (4 + ((mp)->m_sb.sb_agcount * 4)) | 75 | #define XFS_ALLOC_SET_ASIDE(mp) (4 + ((mp)->m_sb.sb_agcount * 4)) |
| 76 | 76 | ||
| 77 | /* | 77 | /* |
| 78 | * When deciding how much space to allocate out of an AG, we limit the | ||
| 79 | * allocation maximum size to the size the AG. However, we cannot use all the | ||
| 80 | * blocks in the AG - some are permanently used by metadata. These | ||
| 81 | * blocks are generally: | ||
| 82 | * - the AG superblock, AGF, AGI and AGFL | ||
| 83 | * - the AGF (bno and cnt) and AGI btree root blocks | ||
| 84 | * - 4 blocks on the AGFL according to XFS_ALLOC_SET_ASIDE() limits | ||
| 85 | * | ||
| 86 | * The AG headers are sector sized, so the amount of space they take up is | ||
| 87 | * dependent on filesystem geometry. The others are all single blocks. | ||
| 88 | */ | ||
| 89 | #define XFS_ALLOC_AG_MAX_USABLE(mp) \ | ||
| 90 | ((mp)->m_sb.sb_agblocks - XFS_BB_TO_FSB(mp, XFS_FSS_TO_BB(mp, 4)) - 7) | ||
| 91 | |||
| 92 | |||
| 93 | /* | ||
| 78 | * Argument structure for xfs_alloc routines. | 94 | * Argument structure for xfs_alloc routines. |
| 79 | * This is turned into a structure to avoid having 20 arguments passed | 95 | * This is turned into a structure to avoid having 20 arguments passed |
| 80 | * down several levels of the stack. | 96 | * down several levels of the stack. |
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 4111cd3966c..f3a3768189b 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c | |||
| @@ -2430,7 +2430,7 @@ xfs_bmap_btalloc_nullfb( | |||
| 2430 | startag = ag = 0; | 2430 | startag = ag = 0; |
| 2431 | 2431 | ||
| 2432 | pag = xfs_perag_get(mp, ag); | 2432 | pag = xfs_perag_get(mp, ag); |
| 2433 | while (*blen < ap->alen) { | 2433 | while (*blen < args->maxlen) { |
| 2434 | if (!pag->pagf_init) { | 2434 | if (!pag->pagf_init) { |
| 2435 | error = xfs_alloc_pagf_init(mp, args->tp, ag, | 2435 | error = xfs_alloc_pagf_init(mp, args->tp, ag, |
| 2436 | XFS_ALLOC_FLAG_TRYLOCK); | 2436 | XFS_ALLOC_FLAG_TRYLOCK); |
| @@ -2452,7 +2452,7 @@ xfs_bmap_btalloc_nullfb( | |||
| 2452 | notinit = 1; | 2452 | notinit = 1; |
| 2453 | 2453 | ||
| 2454 | if (xfs_inode_is_filestream(ap->ip)) { | 2454 | if (xfs_inode_is_filestream(ap->ip)) { |
| 2455 | if (*blen >= ap->alen) | 2455 | if (*blen >= args->maxlen) |
| 2456 | break; | 2456 | break; |
| 2457 | 2457 | ||
| 2458 | if (ap->userdata) { | 2458 | if (ap->userdata) { |
| @@ -2498,14 +2498,14 @@ xfs_bmap_btalloc_nullfb( | |||
| 2498 | * If the best seen length is less than the request | 2498 | * If the best seen length is less than the request |
| 2499 | * length, use the best as the minimum. | 2499 | * length, use the best as the minimum. |
| 2500 | */ | 2500 | */ |
| 2501 | else if (*blen < ap->alen) | 2501 | else if (*blen < args->maxlen) |
| 2502 | args->minlen = *blen; | 2502 | args->minlen = *blen; |
| 2503 | /* | 2503 | /* |
| 2504 | * Otherwise we've seen an extent as big as alen, | 2504 | * Otherwise we've seen an extent as big as maxlen, |
| 2505 | * use that as the minimum. | 2505 | * use that as the minimum. |
| 2506 | */ | 2506 | */ |
| 2507 | else | 2507 | else |
| 2508 | args->minlen = ap->alen; | 2508 | args->minlen = args->maxlen; |
| 2509 | 2509 | ||
| 2510 | /* | 2510 | /* |
| 2511 | * set the failure fallback case to look in the selected | 2511 | * set the failure fallback case to look in the selected |
| @@ -2573,7 +2573,9 @@ xfs_bmap_btalloc( | |||
| 2573 | args.tp = ap->tp; | 2573 | args.tp = ap->tp; |
| 2574 | args.mp = mp; | 2574 | args.mp = mp; |
| 2575 | args.fsbno = ap->rval; | 2575 | args.fsbno = ap->rval; |
| 2576 | args.maxlen = MIN(ap->alen, mp->m_sb.sb_agblocks); | 2576 | |
| 2577 | /* Trim the allocation back to the maximum an AG can fit. */ | ||
| 2578 | args.maxlen = MIN(ap->alen, XFS_ALLOC_AG_MAX_USABLE(mp)); | ||
| 2577 | args.firstblock = ap->firstblock; | 2579 | args.firstblock = ap->firstblock; |
| 2578 | blen = 0; | 2580 | blen = 0; |
| 2579 | if (nullfb) { | 2581 | if (nullfb) { |
| @@ -2621,7 +2623,7 @@ xfs_bmap_btalloc( | |||
| 2621 | /* | 2623 | /* |
| 2622 | * Adjust for alignment | 2624 | * Adjust for alignment |
| 2623 | */ | 2625 | */ |
| 2624 | if (blen > args.alignment && blen <= ap->alen) | 2626 | if (blen > args.alignment && blen <= args.maxlen) |
| 2625 | args.minlen = blen - args.alignment; | 2627 | args.minlen = blen - args.alignment; |
| 2626 | args.minalignslop = 0; | 2628 | args.minalignslop = 0; |
| 2627 | } else { | 2629 | } else { |
| @@ -2640,7 +2642,7 @@ xfs_bmap_btalloc( | |||
| 2640 | * of minlen+alignment+slop doesn't go up | 2642 | * of minlen+alignment+slop doesn't go up |
| 2641 | * between the calls. | 2643 | * between the calls. |
| 2642 | */ | 2644 | */ |
| 2643 | if (blen > mp->m_dalign && blen <= ap->alen) | 2645 | if (blen > mp->m_dalign && blen <= args.maxlen) |
| 2644 | nextminlen = blen - mp->m_dalign; | 2646 | nextminlen = blen - mp->m_dalign; |
| 2645 | else | 2647 | else |
| 2646 | nextminlen = args.minlen; | 2648 | nextminlen = args.minlen; |
