diff options
-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 5673bcfda2f0..71596e57283a 100644 --- a/fs/xfs/xfs_alloc.c +++ b/fs/xfs/xfs_alloc.c | |||
@@ -175,6 +175,7 @@ xfs_alloc_compute_diff( | |||
175 | xfs_agblock_t wantbno, /* target starting block */ | 175 | xfs_agblock_t wantbno, /* target starting block */ |
176 | xfs_extlen_t wantlen, /* target length */ | 176 | xfs_extlen_t wantlen, /* target length */ |
177 | xfs_extlen_t alignment, /* target alignment */ | 177 | xfs_extlen_t alignment, /* target alignment */ |
178 | char userdata, /* are we allocating data? */ | ||
178 | xfs_agblock_t freebno, /* freespace's starting block */ | 179 | xfs_agblock_t freebno, /* freespace's starting block */ |
179 | xfs_extlen_t freelen, /* freespace's length */ | 180 | xfs_extlen_t freelen, /* freespace's length */ |
180 | xfs_agblock_t *newbnop) /* result: best start block from free */ | 181 | xfs_agblock_t *newbnop) /* result: best start block from free */ |
@@ -189,7 +190,14 @@ xfs_alloc_compute_diff( | |||
189 | ASSERT(freelen >= wantlen); | 190 | ASSERT(freelen >= wantlen); |
190 | freeend = freebno + freelen; | 191 | freeend = freebno + freelen; |
191 | wantend = wantbno + wantlen; | 192 | wantend = wantbno + wantlen; |
192 | if (freebno >= wantbno) { | 193 | /* |
194 | * We want to allocate from the start of a free extent if it is past | ||
195 | * the desired block or if we are allocating user data and the free | ||
196 | * extent is before desired block. The second case is there to allow | ||
197 | * for contiguous allocation from the remaining free space if the file | ||
198 | * grows in the short term. | ||
199 | */ | ||
200 | if (freebno >= wantbno || (userdata && freeend < wantend)) { | ||
193 | if ((newbno1 = roundup(freebno, alignment)) >= freeend) | 201 | if ((newbno1 = roundup(freebno, alignment)) >= freeend) |
194 | newbno1 = NULLAGBLOCK; | 202 | newbno1 = NULLAGBLOCK; |
195 | } else if (freeend >= wantend && alignment > 1) { | 203 | } else if (freeend >= wantend && alignment > 1) { |
@@ -805,7 +813,8 @@ xfs_alloc_find_best_extent( | |||
805 | xfs_alloc_fix_len(args); | 813 | xfs_alloc_fix_len(args); |
806 | 814 | ||
807 | sdiff = xfs_alloc_compute_diff(args->agbno, args->len, | 815 | sdiff = xfs_alloc_compute_diff(args->agbno, args->len, |
808 | args->alignment, *sbnoa, | 816 | args->alignment, |
817 | args->userdata, *sbnoa, | ||
809 | *slena, &new); | 818 | *slena, &new); |
810 | 819 | ||
811 | /* | 820 | /* |
@@ -976,7 +985,8 @@ restart: | |||
976 | if (args->len < blen) | 985 | if (args->len < blen) |
977 | continue; | 986 | continue; |
978 | ltdiff = xfs_alloc_compute_diff(args->agbno, args->len, | 987 | ltdiff = xfs_alloc_compute_diff(args->agbno, args->len, |
979 | args->alignment, ltbnoa, ltlena, <new); | 988 | args->alignment, args->userdata, ltbnoa, |
989 | ltlena, <new); | ||
980 | if (ltnew != NULLAGBLOCK && | 990 | if (ltnew != NULLAGBLOCK && |
981 | (args->len > blen || ltdiff < bdiff)) { | 991 | (args->len > blen || ltdiff < bdiff)) { |
982 | bdiff = ltdiff; | 992 | bdiff = ltdiff; |
@@ -1128,7 +1138,8 @@ restart: | |||
1128 | args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen); | 1138 | args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen); |
1129 | xfs_alloc_fix_len(args); | 1139 | xfs_alloc_fix_len(args); |
1130 | ltdiff = xfs_alloc_compute_diff(args->agbno, args->len, | 1140 | ltdiff = xfs_alloc_compute_diff(args->agbno, args->len, |
1131 | args->alignment, ltbnoa, ltlena, <new); | 1141 | args->alignment, args->userdata, ltbnoa, |
1142 | ltlena, <new); | ||
1132 | 1143 | ||
1133 | error = xfs_alloc_find_best_extent(args, | 1144 | error = xfs_alloc_find_best_extent(args, |
1134 | &bno_cur_lt, &bno_cur_gt, | 1145 | &bno_cur_lt, &bno_cur_gt, |
@@ -1144,7 +1155,8 @@ restart: | |||
1144 | args->len = XFS_EXTLEN_MIN(gtlena, args->maxlen); | 1155 | args->len = XFS_EXTLEN_MIN(gtlena, args->maxlen); |
1145 | xfs_alloc_fix_len(args); | 1156 | xfs_alloc_fix_len(args); |
1146 | gtdiff = xfs_alloc_compute_diff(args->agbno, args->len, | 1157 | gtdiff = xfs_alloc_compute_diff(args->agbno, args->len, |
1147 | args->alignment, gtbnoa, gtlena, >new); | 1158 | args->alignment, args->userdata, gtbnoa, |
1159 | gtlena, >new); | ||
1148 | 1160 | ||
1149 | error = xfs_alloc_find_best_extent(args, | 1161 | error = xfs_alloc_find_best_extent(args, |
1150 | &bno_cur_gt, &bno_cur_lt, | 1162 | &bno_cur_gt, &bno_cur_lt, |
@@ -1203,7 +1215,7 @@ restart: | |||
1203 | } | 1215 | } |
1204 | rlen = args->len; | 1216 | rlen = args->len; |
1205 | (void)xfs_alloc_compute_diff(args->agbno, rlen, args->alignment, | 1217 | (void)xfs_alloc_compute_diff(args->agbno, rlen, args->alignment, |
1206 | ltbnoa, ltlena, <new); | 1218 | args->userdata, ltbnoa, ltlena, <new); |
1207 | ASSERT(ltnew >= ltbno); | 1219 | ASSERT(ltnew >= ltbno); |
1208 | ASSERT(ltnew + rlen <= ltbnoa + ltlena); | 1220 | ASSERT(ltnew + rlen <= ltbnoa + ltlena); |
1209 | ASSERT(ltnew + rlen <= be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length)); | 1221 | ASSERT(ltnew + rlen <= be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length)); |