diff options
Diffstat (limited to 'fs/xfs/xfs_alloc.c')
| -rw-r--r-- | fs/xfs/xfs_alloc.c | 24 | 
1 files changed, 18 insertions, 6 deletions
| diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c index 5673bcfda2f..71596e57283 100644 --- a/fs/xfs/xfs_alloc.c +++ b/fs/xfs/xfs_alloc.c @@ -175,6 +175,7 @@ xfs_alloc_compute_diff(  	xfs_agblock_t	wantbno,	/* target starting block */  	xfs_extlen_t	wantlen,	/* target length */  	xfs_extlen_t	alignment,	/* target alignment */ +	char		userdata,	/* are we allocating data? */  	xfs_agblock_t	freebno,	/* freespace's starting block */  	xfs_extlen_t	freelen,	/* freespace's length */  	xfs_agblock_t	*newbnop)	/* result: best start block from free */ @@ -189,7 +190,14 @@ xfs_alloc_compute_diff(  	ASSERT(freelen >= wantlen);  	freeend = freebno + freelen;  	wantend = wantbno + wantlen; -	if (freebno >= wantbno) { +	/* +	 * We want to allocate from the start of a free extent if it is past +	 * the desired block or if we are allocating user data and the free +	 * extent is before desired block. The second case is there to allow +	 * for contiguous allocation from the remaining free space if the file +	 * grows in the short term. +	 */ +	if (freebno >= wantbno || (userdata && freeend < wantend)) {  		if ((newbno1 = roundup(freebno, alignment)) >= freeend)  			newbno1 = NULLAGBLOCK;  	} else if (freeend >= wantend && alignment > 1) { @@ -805,7 +813,8 @@ xfs_alloc_find_best_extent(  			xfs_alloc_fix_len(args);  			sdiff = xfs_alloc_compute_diff(args->agbno, args->len, -						       args->alignment, *sbnoa, +						       args->alignment, +						       args->userdata, *sbnoa,  						       *slena, &new);  			/* @@ -976,7 +985,8 @@ restart:  			if (args->len < blen)  				continue;  			ltdiff = xfs_alloc_compute_diff(args->agbno, args->len, -				args->alignment, ltbnoa, ltlena, <new); +				args->alignment, args->userdata, ltbnoa, +				ltlena, <new);  			if (ltnew != NULLAGBLOCK &&  			    (args->len > blen || ltdiff < bdiff)) {  				bdiff = ltdiff; @@ -1128,7 +1138,8 @@ restart:  			args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen);  			xfs_alloc_fix_len(args);  			ltdiff = xfs_alloc_compute_diff(args->agbno, args->len, -				args->alignment, ltbnoa, ltlena, <new); +				args->alignment, args->userdata, ltbnoa, +				ltlena, <new);  			error = xfs_alloc_find_best_extent(args,  						&bno_cur_lt, &bno_cur_gt, @@ -1144,7 +1155,8 @@ restart:  			args->len = XFS_EXTLEN_MIN(gtlena, args->maxlen);  			xfs_alloc_fix_len(args);  			gtdiff = xfs_alloc_compute_diff(args->agbno, args->len, -				args->alignment, gtbnoa, gtlena, >new); +				args->alignment, args->userdata, gtbnoa, +				gtlena, >new);  			error = xfs_alloc_find_best_extent(args,  						&bno_cur_gt, &bno_cur_lt, @@ -1203,7 +1215,7 @@ restart:  	}  	rlen = args->len;  	(void)xfs_alloc_compute_diff(args->agbno, rlen, args->alignment, -				     ltbnoa, ltlena, <new); +				     args->userdata, ltbnoa, ltlena, <new);  	ASSERT(ltnew >= ltbno);  	ASSERT(ltnew + rlen <= ltbnoa + ltlena);  	ASSERT(ltnew + rlen <= be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length)); | 
