aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_bmap.c
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2011-01-26 20:16:28 -0500
committerAlex Elder <aelder@sgi.com>2011-01-28 10:05:35 -0500
commit14b064ceaa6f51a7426cc45b4b43685b94380658 (patch)
treeacb620a958da7f3528acc04899c685591663fc24 /fs/xfs/xfs_bmap.c
parentb8fc82630ae289bb4e661567808afc59e3298dce (diff)
xfs: limit extent length for allocation to AG size
Delayed allocation extents can be larger than AGs, so when trying to convert a large range we may scan every AG inside xfs_bmap_alloc_nullfb() trying to find an AG with a size larger than an AG. We should stop when we find the first AG with a maximum possible allocation size. This causes excessive CPU usage when there are lots of AGs. The same problem occurs when doing preallocation of a range larger than an AG. Fix the problem by limiting real allocation lengths to the maximum that an AG can support. This means if we have empty AGs, we'll stop the search at the first of them. If there are no empty AGs, we'll still scan them all, but that is a different problem.... Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Alex Elder <aelder@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_bmap.c')
-rw-r--r--fs/xfs/xfs_bmap.c18
1 files changed, 10 insertions, 8 deletions
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index 4111cd3966c7..f3a3768189bb 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;