aboutsummaryrefslogtreecommitdiff
path: root/fs/btrfs
diff options
context:
space:
mode:
authorChris Mason2008-11-07 18:17:11 -0500
committerChris Mason2008-11-07 18:17:11 -0500
commit42e70e7a2f9d96fd843723fa46d5121cb3e551d0 (patch)
tree8e9c6e1c1d0810c53a87b0a36adc37037a1fe266 /fs/btrfs
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>
Diffstat (limited to 'fs/btrfs')
-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,
}
search_start = max(search_start, first_logical_byte(root, 0));
search_start = max(search_start, hint_byte);
- total_needed += empty_size;
- if (search_start != last_wanted)
+ if (last_wanted && search_start != last_wanted) {
last_wanted = 0;
+ empty_size += empty_cluster;
+ }
+ total_needed += empty_size;
block_group = btrfs_lookup_block_group(root->fs_info, search_start);
if (!block_group)
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,
* group thats not of the proper type, while looping this
* should never happen
*/
- WARN_ON(!block_group);
+ if (!block_group)
+ goto new_group_no_lock;
+
mutex_lock(&block_group->alloc_mutex);
if (unlikely(!block_group_bits(block_group, data)))
goto new_group;
@@ -2248,12 +2252,13 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
break;
}
new_group:
+ mutex_unlock(&block_group->alloc_mutex);
+new_group_no_lock:
last_wanted = 0;
- if (loop > 0) {
+ if (!allowed_chunk_alloc && loop > 0) {
total_needed -= empty_cluster;
empty_cluster = 0;
}
- mutex_unlock(&block_group->alloc_mutex);
/*
* Here's how this works.
* loop == 0: we were searching a block group via a hint
@@ -2271,6 +2276,10 @@ new_group:
cur = head->next;
loop++;
} else if (loop == 1 && cur == head) {
+
+ total_needed -= empty_cluster;
+ empty_cluster = 0;
+
if (allowed_chunk_alloc && !chunk_alloc_done) {
up_read(&space_info->groups_sem);
ret = do_chunk_alloc(trans, root, num_bytes +