aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
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
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')
-rw-r--r--fs/xfs/xfs_alloc.h16
-rw-r--r--fs/xfs/xfs_bmap.c18
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;