|
@@ -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));
|