aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-10-15 16:17:44 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:03:56 -0400
commite19caa5f0e34b571ed0c2617554af5c43cb124d1 (patch)
tree763e227bbce9325411955bb5cea5c5f1772b0a2d /fs
parent6b80053d02be41886344b5007d04e345311ec0b5 (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')
-rw-r--r--fs/btrfs/extent-tree.c38
-rw-r--r--fs/btrfs/extent_map.c6
2 files changed, 25 insertions, 19 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
193new_group: 196new_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
913check_failed: 909check_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 }
1004next: 1003next:
@@ -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
diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c
index 7ef3397a266d..e241699024da 100644
--- a/fs/btrfs/extent_map.c
+++ b/fs/btrfs/extent_map.c
@@ -981,7 +981,7 @@ int find_first_extent_bit(struct extent_map_tree *tree, u64 start,
981 struct extent_state *state; 981 struct extent_state *state;
982 int ret = 1; 982 int ret = 1;
983 983
984 write_lock_irq(&tree->lock); 984 read_lock_irq(&tree->lock);
985 /* 985 /*
986 * this search will find all the extents that end after 986 * this search will find all the extents that end after
987 * our range starts. 987 * our range starts.
@@ -993,7 +993,7 @@ int find_first_extent_bit(struct extent_map_tree *tree, u64 start,
993 993
994 while(1) { 994 while(1) {
995 state = rb_entry(node, struct extent_state, rb_node); 995 state = rb_entry(node, struct extent_state, rb_node);
996 if (state->state & bits) { 996 if (state->end >= start && (state->state & bits)) {
997 *start_ret = state->start; 997 *start_ret = state->start;
998 *end_ret = state->end; 998 *end_ret = state->end;
999 ret = 0; 999 ret = 0;
@@ -1004,7 +1004,7 @@ int find_first_extent_bit(struct extent_map_tree *tree, u64 start,
1004 break; 1004 break;
1005 } 1005 }
1006out: 1006out:
1007 write_unlock_irq(&tree->lock); 1007 read_unlock_irq(&tree->lock);
1008 return ret; 1008 return ret;
1009} 1009}
1010EXPORT_SYMBOL(find_first_extent_bit); 1010EXPORT_SYMBOL(find_first_extent_bit);