aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorMiao Xie <miaox@cn.fujitsu.com>2011-07-15 06:34:36 -0400
committerChris Mason <chris.mason@oracle.com>2011-07-27 12:46:45 -0400
commit199c36eaa95077a47ae1bc55532fc0fbeb80cc95 (patch)
treeef4e9a5ff244c842b9b335cb391223d9a4d5f854 /fs
parentf7aaa06bff6f5fe049ce9723267e1639c2c3d8b5 (diff)
Btrfs: fix BUG_ON() caused by ENOSPC when relocating space
When we balanced the chunks across the devices, BUG_ON() in __finish_chunk_alloc() was triggered. ------------[ cut here ]------------ kernel BUG at fs/btrfs/volumes.c:2568! [SNIP] Call Trace: [<ffffffffa049525e>] btrfs_alloc_chunk+0x8e/0xa0 [btrfs] [<ffffffffa04546b0>] do_chunk_alloc+0x330/0x3a0 [btrfs] [<ffffffffa045c654>] btrfs_reserve_extent+0xb4/0x1f0 [btrfs] [<ffffffffa045c86b>] btrfs_alloc_free_block+0xdb/0x350 [btrfs] [<ffffffffa048a8d8>] ? read_extent_buffer+0xd8/0x1d0 [btrfs] [<ffffffffa04476fd>] __btrfs_cow_block+0x14d/0x5e0 [btrfs] [<ffffffffa044660d>] ? read_block_for_search+0x14d/0x4d0 [btrfs] [<ffffffffa0447c9b>] btrfs_cow_block+0x10b/0x240 [btrfs] [<ffffffffa044dd5e>] btrfs_search_slot+0x49e/0x7a0 [btrfs] [<ffffffffa044f07d>] btrfs_insert_empty_items+0x8d/0xf0 [btrfs] [<ffffffffa045e973>] insert_with_overflow+0x43/0x110 [btrfs] [<ffffffffa045eb0d>] btrfs_insert_dir_item+0xcd/0x1f0 [btrfs] [<ffffffffa0489bd0>] ? map_extent_buffer+0xb0/0xc0 [btrfs] [<ffffffff812276ad>] ? rb_insert_color+0x9d/0x160 [<ffffffffa046cc40>] ? inode_tree_add+0xf0/0x150 [btrfs] [<ffffffffa0474801>] btrfs_add_link+0xc1/0x1c0 [btrfs] [<ffffffff811dacac>] ? security_inode_init_security+0x1c/0x30 [<ffffffffa04a28aa>] ? btrfs_init_acl+0x4a/0x180 [btrfs] [<ffffffffa047492f>] btrfs_add_nondir+0x2f/0x70 [btrfs] [<ffffffffa046af16>] ? btrfs_init_inode_security+0x46/0x60 [btrfs] [<ffffffffa0474ac0>] btrfs_create+0x150/0x1d0 [btrfs] [<ffffffff81159c63>] ? generic_permission+0x23/0xb0 [<ffffffff8115b415>] vfs_create+0xa5/0xc0 [<ffffffff8115ce6e>] do_last+0x5fe/0x880 [<ffffffff8115dc0d>] path_openat+0xcd/0x3d0 [<ffffffff8115e029>] do_filp_open+0x49/0xa0 [<ffffffff8116a965>] ? alloc_fd+0x95/0x160 [<ffffffff8114f0c7>] do_sys_open+0x107/0x1e0 [<ffffffff810bcc3f>] ? audit_syscall_entry+0x1bf/0x1f0 [<ffffffff8114f1e0>] sys_open+0x20/0x30 [<ffffffff81484ec2>] system_call_fastpath+0x16/0x1b [SNIP] RIP [<ffffffffa049444a>] __finish_chunk_alloc+0x20a/0x220 [btrfs] The reason is: Task1 Space balance task do_chunk_alloc() __finish_chunk_alloc() update device info in the chunk tree alloc system metadata block relocate system metadata block group set system metadata block group readonly, This block group is the only one that can allocate space. So there is no free space that can be allocated now. find no space and don't try to alloc new chunk, and then return ENOSPC BUG_ON() in __finish_chunk_alloc() was triggered. Fix this bug by allocating a new system metadata chunk before relocating the old one if we find there is no free space which can be allocated after setting the old block group to be read-only. Reported-by: Tsutomu Itoh <t-itoh@jp.fujitsu.com> Signed-off-by: Miao Xie <miaox@cn.fujitsu.com> Tested-by: Tsutomu Itoh <t-itoh@jp.fujitsu.com> Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/extent-tree.c28
1 files changed, 21 insertions, 7 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index d7031e7dfd76..7021dde74d81 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -6526,15 +6526,28 @@ static u64 update_block_group_flags(struct btrfs_root *root, u64 flags)
6526 return flags; 6526 return flags;
6527} 6527}
6528 6528
6529static int set_block_group_ro(struct btrfs_block_group_cache *cache) 6529static int set_block_group_ro(struct btrfs_block_group_cache *cache, int force)
6530{ 6530{
6531 struct btrfs_space_info *sinfo = cache->space_info; 6531 struct btrfs_space_info *sinfo = cache->space_info;
6532 u64 num_bytes; 6532 u64 num_bytes;
6533 u64 min_allocable_bytes;
6533 int ret = -ENOSPC; 6534 int ret = -ENOSPC;
6534 6535
6535 if (cache->ro) 6536 if (cache->ro)
6536 return 0; 6537 return 0;
6537 6538
6539 /*
6540 * We need some metadata space and system metadata space for
6541 * allocating chunks in some corner cases until we force to set
6542 * it to be readonly.
6543 */
6544 if ((sinfo->flags &
6545 (BTRFS_BLOCK_GROUP_SYSTEM | BTRFS_BLOCK_GROUP_METADATA)) &&
6546 !force)
6547 min_allocable_bytes = 1 * 1024 * 1024;
6548 else
6549 min_allocable_bytes = 0;
6550
6538 spin_lock(&sinfo->lock); 6551 spin_lock(&sinfo->lock);
6539 spin_lock(&cache->lock); 6552 spin_lock(&cache->lock);
6540 num_bytes = cache->key.offset - cache->reserved - cache->pinned - 6553 num_bytes = cache->key.offset - cache->reserved - cache->pinned -
@@ -6542,7 +6555,8 @@ static int set_block_group_ro(struct btrfs_block_group_cache *cache)
6542 6555
6543 if (sinfo->bytes_used + sinfo->bytes_reserved + sinfo->bytes_pinned + 6556 if (sinfo->bytes_used + sinfo->bytes_reserved + sinfo->bytes_pinned +
6544 sinfo->bytes_may_use + sinfo->bytes_readonly + 6557 sinfo->bytes_may_use + sinfo->bytes_readonly +
6545 cache->reserved_pinned + num_bytes <= sinfo->total_bytes) { 6558 cache->reserved_pinned + num_bytes + min_allocable_bytes <=
6559 sinfo->total_bytes) {
6546 sinfo->bytes_readonly += num_bytes; 6560 sinfo->bytes_readonly += num_bytes;
6547 sinfo->bytes_reserved += cache->reserved_pinned; 6561 sinfo->bytes_reserved += cache->reserved_pinned;
6548 cache->reserved_pinned = 0; 6562 cache->reserved_pinned = 0;
@@ -6573,7 +6587,7 @@ int btrfs_set_block_group_ro(struct btrfs_root *root,
6573 do_chunk_alloc(trans, root, 2 * 1024 * 1024, alloc_flags, 6587 do_chunk_alloc(trans, root, 2 * 1024 * 1024, alloc_flags,
6574 CHUNK_ALLOC_FORCE); 6588 CHUNK_ALLOC_FORCE);
6575 6589
6576 ret = set_block_group_ro(cache); 6590 ret = set_block_group_ro(cache, 0);
6577 if (!ret) 6591 if (!ret)
6578 goto out; 6592 goto out;
6579 alloc_flags = get_alloc_profile(root, cache->space_info->flags); 6593 alloc_flags = get_alloc_profile(root, cache->space_info->flags);
@@ -6581,7 +6595,7 @@ int btrfs_set_block_group_ro(struct btrfs_root *root,
6581 CHUNK_ALLOC_FORCE); 6595 CHUNK_ALLOC_FORCE);
6582 if (ret < 0) 6596 if (ret < 0)
6583 goto out; 6597 goto out;
6584 ret = set_block_group_ro(cache); 6598 ret = set_block_group_ro(cache, 0);
6585out: 6599out:
6586 btrfs_end_transaction(trans, root); 6600 btrfs_end_transaction(trans, root);
6587 return ret; 6601 return ret;
@@ -7018,7 +7032,7 @@ int btrfs_read_block_groups(struct btrfs_root *root)
7018 7032
7019 set_avail_alloc_bits(root->fs_info, cache->flags); 7033 set_avail_alloc_bits(root->fs_info, cache->flags);
7020 if (btrfs_chunk_readonly(root, cache->key.objectid)) 7034 if (btrfs_chunk_readonly(root, cache->key.objectid))
7021 set_block_group_ro(cache); 7035 set_block_group_ro(cache, 1);
7022 } 7036 }
7023 7037
7024 list_for_each_entry_rcu(space_info, &root->fs_info->space_info, list) { 7038 list_for_each_entry_rcu(space_info, &root->fs_info->space_info, list) {
@@ -7032,9 +7046,9 @@ int btrfs_read_block_groups(struct btrfs_root *root)
7032 * mirrored block groups. 7046 * mirrored block groups.
7033 */ 7047 */
7034 list_for_each_entry(cache, &space_info->block_groups[3], list) 7048 list_for_each_entry(cache, &space_info->block_groups[3], list)
7035 set_block_group_ro(cache); 7049 set_block_group_ro(cache, 1);
7036 list_for_each_entry(cache, &space_info->block_groups[4], list) 7050 list_for_each_entry(cache, &space_info->block_groups[4], list)
7037 set_block_group_ro(cache); 7051 set_block_group_ro(cache, 1);
7038 } 7052 }
7039 7053
7040 init_global_block_rsv(info); 7054 init_global_block_rsv(info);