aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-11-07 18:17:11 -0500
committerChris Mason <chris.mason@oracle.com>2008-11-07 18:17:11 -0500
commit42e70e7a2f9d96fd843723fa46d5121cb3e551d0 (patch)
tree8e9c6e1c1d0810c53a87b0a36adc37037a1fe266
parentaf09abfece59aa50bfbf16f6f1f85822554e061f (diff)
Btrfs: Fix more false enospc errors and an oops from empty clustering
In comes cases the empty cluster was added twice to the total number of bytes the allocator was trying to find. With empty clustering on, the hint byte was sometimes outside of the block group. Add an extra goto to find the correct block group. Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r--fs/btrfs/extent-tree.c19
1 files changed, 14 insertions, 5 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 0d73a53c6763..b92e92c29e3b 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -2152,11 +2152,13 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
2152 } 2152 }
2153 search_start = max(search_start, first_logical_byte(root, 0)); 2153 search_start = max(search_start, first_logical_byte(root, 0));
2154 search_start = max(search_start, hint_byte); 2154 search_start = max(search_start, hint_byte);
2155 total_needed += empty_size;
2156 2155
2157 if (search_start != last_wanted) 2156 if (last_wanted && search_start != last_wanted) {
2158 last_wanted = 0; 2157 last_wanted = 0;
2158 empty_size += empty_cluster;
2159 }
2159 2160
2161 total_needed += empty_size;
2160 block_group = btrfs_lookup_block_group(root->fs_info, search_start); 2162 block_group = btrfs_lookup_block_group(root->fs_info, search_start);
2161 if (!block_group) 2163 if (!block_group)
2162 block_group = btrfs_lookup_first_block_group(root->fs_info, 2164 block_group = btrfs_lookup_first_block_group(root->fs_info,
@@ -2171,7 +2173,9 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
2171 * group thats not of the proper type, while looping this 2173 * group thats not of the proper type, while looping this
2172 * should never happen 2174 * should never happen
2173 */ 2175 */
2174 WARN_ON(!block_group); 2176 if (!block_group)
2177 goto new_group_no_lock;
2178
2175 mutex_lock(&block_group->alloc_mutex); 2179 mutex_lock(&block_group->alloc_mutex);
2176 if (unlikely(!block_group_bits(block_group, data))) 2180 if (unlikely(!block_group_bits(block_group, data)))
2177 goto new_group; 2181 goto new_group;
@@ -2248,12 +2252,13 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
2248 break; 2252 break;
2249 } 2253 }
2250new_group: 2254new_group:
2255 mutex_unlock(&block_group->alloc_mutex);
2256new_group_no_lock:
2251 last_wanted = 0; 2257 last_wanted = 0;
2252 if (loop > 0) { 2258 if (!allowed_chunk_alloc && loop > 0) {
2253 total_needed -= empty_cluster; 2259 total_needed -= empty_cluster;
2254 empty_cluster = 0; 2260 empty_cluster = 0;
2255 } 2261 }
2256 mutex_unlock(&block_group->alloc_mutex);
2257 /* 2262 /*
2258 * Here's how this works. 2263 * Here's how this works.
2259 * loop == 0: we were searching a block group via a hint 2264 * loop == 0: we were searching a block group via a hint
@@ -2271,6 +2276,10 @@ new_group:
2271 cur = head->next; 2276 cur = head->next;
2272 loop++; 2277 loop++;
2273 } else if (loop == 1 && cur == head) { 2278 } else if (loop == 1 && cur == head) {
2279
2280 total_needed -= empty_cluster;
2281 empty_cluster = 0;
2282
2274 if (allowed_chunk_alloc && !chunk_alloc_done) { 2283 if (allowed_chunk_alloc && !chunk_alloc_done) {
2275 up_read(&space_info->groups_sem); 2284 up_read(&space_info->groups_sem);
2276 ret = do_chunk_alloc(trans, root, num_bytes + 2285 ret = do_chunk_alloc(trans, root, num_bytes +