diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-10-15 16:17:44 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:03:56 -0400 |
commit | e19caa5f0e34b571ed0c2617554af5c43cb124d1 (patch) | |
tree | 763e227bbce9325411955bb5cea5c5f1772b0a2d /fs/btrfs/extent-tree.c | |
parent | 6b80053d02be41886344b5007d04e345311ec0b5 (diff) |
Btrfs: Fix allocation routines to avoid intermixing data and metadata allocations
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r-- | fs/btrfs/extent-tree.c | 38 |
1 files changed, 22 insertions, 16 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 0b0c947194ae..72e6b274a450 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -165,7 +165,7 @@ static u64 find_search_start(struct btrfs_root *root, | |||
165 | { | 165 | { |
166 | int ret; | 166 | int ret; |
167 | struct btrfs_block_group_cache *cache = *cache_ret; | 167 | struct btrfs_block_group_cache *cache = *cache_ret; |
168 | u64 last = max(search_start, cache->key.objectid); | 168 | u64 last; |
169 | u64 start = 0; | 169 | u64 start = 0; |
170 | u64 end = 0; | 170 | u64 end = 0; |
171 | 171 | ||
@@ -173,11 +173,14 @@ again: | |||
173 | ret = cache_block_group(root, cache); | 173 | ret = cache_block_group(root, cache); |
174 | if (ret) | 174 | if (ret) |
175 | goto out; | 175 | goto out; |
176 | last = max(search_start, cache->key.objectid); | ||
177 | |||
176 | while(1) { | 178 | while(1) { |
177 | ret = find_first_extent_bit(&root->fs_info->free_space_cache, | 179 | ret = find_first_extent_bit(&root->fs_info->free_space_cache, |
178 | last, &start, &end, EXTENT_DIRTY); | 180 | last, &start, &end, EXTENT_DIRTY); |
179 | if (ret) | 181 | if (ret) { |
180 | goto out; | 182 | goto new_group; |
183 | } | ||
181 | 184 | ||
182 | start = max(last, start); | 185 | start = max(last, start); |
183 | last = end + 1; | 186 | last = end + 1; |
@@ -191,15 +194,13 @@ out: | |||
191 | return search_start; | 194 | return search_start; |
192 | 195 | ||
193 | new_group: | 196 | new_group: |
194 | cache = btrfs_lookup_block_group(root->fs_info, | 197 | last = cache->key.objectid + cache->key.offset; |
195 | last + cache->key.offset - 1); | 198 | cache = btrfs_lookup_block_group(root->fs_info, last); |
196 | if (!cache) { | 199 | if (!cache) { |
197 | return search_start; | 200 | return search_start; |
198 | } | 201 | } |
199 | cache = btrfs_find_block_group(root, cache, | 202 | cache = btrfs_find_block_group(root, cache, last, data, 0); |
200 | last + cache->key.offset - 1, data, 0); | ||
201 | *cache_ret = cache; | 203 | *cache_ret = cache; |
202 | last = min(cache->key.objectid, last); | ||
203 | goto again; | 204 | goto again; |
204 | } | 205 | } |
205 | 206 | ||
@@ -257,12 +258,7 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root, | |||
257 | if (used < div_factor(hint->key.offset, factor)) { | 258 | if (used < div_factor(hint->key.offset, factor)) { |
258 | return hint; | 259 | return hint; |
259 | } | 260 | } |
260 | last = hint->key.offset * 3; | 261 | last = hint->key.objectid + hint->key.offset; |
261 | if (hint->key.objectid >= last) | ||
262 | last = max(search_start + hint->key.offset - 1, | ||
263 | hint->key.objectid - last); | ||
264 | else | ||
265 | last = hint->key.objectid + hint->key.offset; | ||
266 | hint_last = last; | 262 | hint_last = last; |
267 | } else { | 263 | } else { |
268 | if (hint) | 264 | if (hint) |
@@ -913,7 +909,6 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
913 | check_failed: | 909 | check_failed: |
914 | search_start = find_search_start(root, &block_group, | 910 | search_start = find_search_start(root, &block_group, |
915 | search_start, total_needed, data); | 911 | search_start, total_needed, data); |
916 | |||
917 | btrfs_init_path(path); | 912 | btrfs_init_path(path); |
918 | ins->objectid = search_start; | 913 | ins->objectid = search_start; |
919 | ins->offset = 0; | 914 | ins->offset = 0; |
@@ -958,6 +953,9 @@ check_failed: | |||
958 | continue; | 953 | continue; |
959 | if (ret < 0) | 954 | if (ret < 0) |
960 | goto error; | 955 | goto error; |
956 | |||
957 | search_start = max(search_start, | ||
958 | block_group->key.objectid); | ||
961 | if (!start_found) { | 959 | if (!start_found) { |
962 | ins->objectid = search_start; | 960 | ins->objectid = search_start; |
963 | ins->offset = search_end - search_start; | 961 | ins->offset = search_end - search_start; |
@@ -967,6 +965,7 @@ check_failed: | |||
967 | ins->objectid = last_byte > search_start ? | 965 | ins->objectid = last_byte > search_start ? |
968 | last_byte : search_start; | 966 | last_byte : search_start; |
969 | ins->offset = search_end - ins->objectid; | 967 | ins->offset = search_end - ins->objectid; |
968 | BUG_ON(ins->objectid >= search_end); | ||
970 | goto check_pending; | 969 | goto check_pending; |
971 | } | 970 | } |
972 | btrfs_item_key_to_cpu(l, &key, slot); | 971 | btrfs_item_key_to_cpu(l, &key, slot); |
@@ -998,7 +997,7 @@ check_failed: | |||
998 | block_group->key.offset) { | 997 | block_group->key.offset) { |
999 | btrfs_release_path(root, path); | 998 | btrfs_release_path(root, path); |
1000 | search_start = block_group->key.objectid + | 999 | search_start = block_group->key.objectid + |
1001 | block_group->key.offset * 2; | 1000 | block_group->key.offset; |
1002 | goto new_group; | 1001 | goto new_group; |
1003 | } | 1002 | } |
1004 | next: | 1003 | next: |
@@ -1015,6 +1014,12 @@ check_pending: | |||
1015 | if (ins->objectid + num_bytes >= search_end) | 1014 | if (ins->objectid + num_bytes >= search_end) |
1016 | goto enospc; | 1015 | goto enospc; |
1017 | 1016 | ||
1017 | if (!full_scan && ins->objectid + num_bytes >= block_group-> | ||
1018 | key.objectid + block_group->key.offset) { | ||
1019 | search_start = block_group->key.objectid + | ||
1020 | block_group->key.offset; | ||
1021 | goto new_group; | ||
1022 | } | ||
1018 | if (test_range_bit(&info->extent_ins, ins->objectid, | 1023 | if (test_range_bit(&info->extent_ins, ins->objectid, |
1019 | ins->objectid + num_bytes -1, EXTENT_LOCKED, 0)) { | 1024 | ins->objectid + num_bytes -1, EXTENT_LOCKED, 0)) { |
1020 | search_start = ins->objectid + num_bytes; | 1025 | search_start = ins->objectid + num_bytes; |
@@ -1114,6 +1119,7 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans, | |||
1114 | set_extent_bits(&root->fs_info->extent_ins, ins->objectid, | 1119 | set_extent_bits(&root->fs_info->extent_ins, ins->objectid, |
1115 | ins->objectid + ins->offset - 1, | 1120 | ins->objectid + ins->offset - 1, |
1116 | EXTENT_LOCKED, GFP_NOFS); | 1121 | EXTENT_LOCKED, GFP_NOFS); |
1122 | WARN_ON(data == 1); | ||
1117 | goto update_block; | 1123 | goto update_block; |
1118 | } | 1124 | } |
1119 | 1125 | ||