diff options
author | Miao Xie <miaox@cn.fujitsu.com> | 2011-09-09 05:34:35 -0400 |
---|---|---|
committer | David Sterba <dsterba@suse.cz> | 2011-10-20 12:10:49 -0400 |
commit | 60d2adbb1e7fee1cb4bc67f70bd0bd8ace7b6c3c (patch) | |
tree | 9a3e5f57204cf41bbf998a1873e870110c2ff5f8 /fs/btrfs/extent-tree.c | |
parent | cfbffc39ac89dbd5197cbeec2599a1128eb928f8 (diff) |
Btrfs: fix race between multi-task space allocation and caching space
The task may fail to get free space though it is enough when multi-task
space allocation and caching space happen at the same time.
Task1 Caching Thread Task2
------------------------------------------------------------------------
find_free_extent
The space has not
be cached, and start
caching thread. And
wait for it.
cache space, if
the space is > 2MB
wake up Task1
find_free_extent
get all the space that
is cached.
try to allocate space,
but there is no space
now.
trigger BUG_ON()
The message is following:
btrfs allocation failed flags 1, wanted 4096
space_info has 1040187392 free, is not full
space_info total=1082130432, used=4096, pinned=41938944, reserved=0, may_use=40828928, readonly=0
block group 12582912 has 8388608 bytes, 0 used 8388608 pinned 0 reserved
block group has cluster?: no
0 blocks of free space at or bigger than bytes is
block group 1103101952 has 1073741824 bytes, 4096 used 33550336 pinned 0 reserved
block group has cluster?: no
0 blocks of free space at or bigger than bytes is
------------[ cut here ]------------
kernel BUG at fs/btrfs/inode.c:835!
[<ffffffffa031261b>] __extent_writepage+0x1bf/0x5ce [btrfs]
[<ffffffff810cbcb8>] ? __set_page_dirty_nobuffers+0xfe/0x108
[<ffffffffa02f8ada>] ? wait_current_trans+0x23/0xec [btrfs]
[<ffffffff810c3fbf>] ? find_get_pages_tag+0x73/0xe2
[<ffffffffa0312d12>] extent_write_cache_pages.clone.0+0x176/0x29a [btrfs]
[<ffffffffa0312e74>] extent_writepages+0x3e/0x53 [btrfs]
[<ffffffff8110ad2c>] ? do_sync_write+0xc6/0x103
[<ffffffffa0302d6e>] ? btrfs_submit_direct+0x414/0x414 [btrfs]
[<ffffffff811380fa>] ? fsnotify+0x236/0x266
[<ffffffffa02fc930>] btrfs_writepages+0x22/0x24 [btrfs]
[<ffffffff810cc215>] do_writepages+0x1c/0x25
[<ffffffff810c4958>] __filemap_fdatawrite_range+0x4e/0x50
[<ffffffff810c4982>] filemap_write_and_wait_range+0x28/0x51
[<ffffffffa0306b2e>] btrfs_sync_file+0x7d/0x198 [btrfs]
[<ffffffff8110aa26>] ? fsnotify_modify+0x5d/0x65
[<ffffffff8112d150>] vfs_fsync_range+0x18/0x21
[<ffffffff8112d170>] vfs_fsync+0x17/0x19
[<ffffffff8112d316>] do_fsync+0x29/0x3e
[<ffffffff8112d348>] sys_fsync+0xb/0xf
[<ffffffff81468352>] system_call_fastpath+0x16/0x1b
[SNIP]
RIP [<ffffffffa02fe08c>] cow_file_range+0x1c4/0x32b [btrfs]
We fix this bug by trying to allocate the space again if there are block groups
in caching.
Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r-- | fs/btrfs/extent-tree.c | 7 |
1 files changed, 7 insertions, 0 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 6cfcc9060c83..cef355f1328a 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -4954,6 +4954,7 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans, | |||
4954 | bool failed_cluster_refill = false; | 4954 | bool failed_cluster_refill = false; |
4955 | bool failed_alloc = false; | 4955 | bool failed_alloc = false; |
4956 | bool use_cluster = true; | 4956 | bool use_cluster = true; |
4957 | bool have_caching_bg = false; | ||
4957 | u64 ideal_cache_percent = 0; | 4958 | u64 ideal_cache_percent = 0; |
4958 | u64 ideal_cache_offset = 0; | 4959 | u64 ideal_cache_offset = 0; |
4959 | 4960 | ||
@@ -5036,6 +5037,7 @@ ideal_cache: | |||
5036 | } | 5037 | } |
5037 | } | 5038 | } |
5038 | search: | 5039 | search: |
5040 | have_caching_bg = false; | ||
5039 | down_read(&space_info->groups_sem); | 5041 | down_read(&space_info->groups_sem); |
5040 | list_for_each_entry(block_group, &space_info->block_groups[index], | 5042 | list_for_each_entry(block_group, &space_info->block_groups[index], |
5041 | list) { | 5043 | list) { |
@@ -5244,6 +5246,8 @@ refill_cluster: | |||
5244 | failed_alloc = true; | 5246 | failed_alloc = true; |
5245 | goto have_block_group; | 5247 | goto have_block_group; |
5246 | } else if (!offset) { | 5248 | } else if (!offset) { |
5249 | if (!cached) | ||
5250 | have_caching_bg = true; | ||
5247 | goto loop; | 5251 | goto loop; |
5248 | } | 5252 | } |
5249 | checks: | 5253 | checks: |
@@ -5294,6 +5298,9 @@ loop: | |||
5294 | } | 5298 | } |
5295 | up_read(&space_info->groups_sem); | 5299 | up_read(&space_info->groups_sem); |
5296 | 5300 | ||
5301 | if (!ins->objectid && loop >= LOOP_CACHING_WAIT && have_caching_bg) | ||
5302 | goto search; | ||
5303 | |||
5297 | if (!ins->objectid && ++index < BTRFS_NR_RAID_TYPES) | 5304 | if (!ins->objectid && ++index < BTRFS_NR_RAID_TYPES) |
5298 | goto search; | 5305 | goto search; |
5299 | 5306 | ||