提交 42e70e7a 编写于 作者: C Chris Mason

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: NChris Mason <chris.mason@oracle.com>
上级 af09abfe
...@@ -2152,11 +2152,13 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans, ...@@ -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, first_logical_byte(root, 0));
search_start = max(search_start, hint_byte); 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; last_wanted = 0;
empty_size += empty_cluster;
}
total_needed += empty_size;
block_group = btrfs_lookup_block_group(root->fs_info, search_start); block_group = btrfs_lookup_block_group(root->fs_info, search_start);
if (!block_group) if (!block_group)
block_group = btrfs_lookup_first_block_group(root->fs_info, 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,7 +2173,9 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
* group thats not of the proper type, while looping this * group thats not of the proper type, while looping this
* should never happen * should never happen
*/ */
WARN_ON(!block_group); if (!block_group)
goto new_group_no_lock;
mutex_lock(&block_group->alloc_mutex); mutex_lock(&block_group->alloc_mutex);
if (unlikely(!block_group_bits(block_group, data))) if (unlikely(!block_group_bits(block_group, data)))
goto new_group; goto new_group;
...@@ -2248,12 +2252,13 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans, ...@@ -2248,12 +2252,13 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
break; break;
} }
new_group: new_group:
mutex_unlock(&block_group->alloc_mutex);
new_group_no_lock:
last_wanted = 0; last_wanted = 0;
if (loop > 0) { if (!allowed_chunk_alloc && loop > 0) {
total_needed -= empty_cluster; total_needed -= empty_cluster;
empty_cluster = 0; empty_cluster = 0;
} }
mutex_unlock(&block_group->alloc_mutex);
/* /*
* Here's how this works. * Here's how this works.
* loop == 0: we were searching a block group via a hint * loop == 0: we were searching a block group via a hint
...@@ -2271,6 +2276,10 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans, ...@@ -2271,6 +2276,10 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
cur = head->next; cur = head->next;
loop++; loop++;
} else if (loop == 1 && cur == head) { } else if (loop == 1 && cur == head) {
total_needed -= empty_cluster;
empty_cluster = 0;
if (allowed_chunk_alloc && !chunk_alloc_done) { if (allowed_chunk_alloc && !chunk_alloc_done) {
up_read(&space_info->groups_sem); up_read(&space_info->groups_sem);
ret = do_chunk_alloc(trans, root, num_bytes + ret = do_chunk_alloc(trans, root, num_bytes +
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册