aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent-tree.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-11-07 21:08:16 -0500
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:03:57 -0400
commit257d0ce36f215937602eb5c1b328b69afaf3bcd8 (patch)
tree4a08be69cd4807950e973d7ec797ce284eff5640 /fs/btrfs/extent-tree.c
parent09be207d1ba224531a61de9afdc07a125e45318c (diff)
Btrfs: Allow large data extents in a single file to span into metadata block groups
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r--fs/btrfs/extent-tree.c36
1 files changed, 30 insertions, 6 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index d54ab8ef06d5..7405bd5301af 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -168,6 +168,7 @@ static u64 find_search_start(struct btrfs_root *root,
168 u64 last; 168 u64 last;
169 u64 start = 0; 169 u64 start = 0;
170 u64 end = 0; 170 u64 end = 0;
171 u64 cache_miss = 0;
171 int wrapped = 0; 172 int wrapped = 0;
172 173
173again: 174again:
@@ -181,14 +182,20 @@ again:
181 ret = find_first_extent_bit(&root->fs_info->free_space_cache, 182 ret = find_first_extent_bit(&root->fs_info->free_space_cache,
182 last, &start, &end, EXTENT_DIRTY); 183 last, &start, &end, EXTENT_DIRTY);
183 if (ret) { 184 if (ret) {
185 if (!cache_miss)
186 cache_miss = last;
184 goto new_group; 187 goto new_group;
185 } 188 }
186 189
187 start = max(last, start); 190 start = max(last, start);
188 last = end + 1; 191 last = end + 1;
189 if (end + 1 - start < num) 192 if (last - start < num) {
193 if (last == cache->key.objectid + cache->key.offset)
194 cache_miss = start;
190 continue; 195 continue;
191 if (start + num >= cache->key.objectid + cache->key.offset) 196 }
197 if (data != BTRFS_BLOCK_GROUP_MIXED &&
198 start + num >= cache->key.objectid + cache->key.offset)
192 goto new_group; 199 goto new_group;
193 return start; 200 return start;
194 } 201 }
@@ -208,13 +215,22 @@ wrapped:
208 } 215 }
209 return search_start; 216 return search_start;
210 } 217 }
218 if (cache_miss && !cache->cached) {
219 cache_block_group(root, cache);
220 last = cache_miss;
221
222 cache = btrfs_lookup_block_group(root->fs_info, last);
223 }
211 cache = btrfs_find_block_group(root, cache, last, data, 0); 224 cache = btrfs_find_block_group(root, cache, last, data, 0);
212 *cache_ret = cache; 225 *cache_ret = cache;
226 cache_miss = 0;
213 goto again; 227 goto again;
214} 228}
215 229
216static u64 div_factor(u64 num, int factor) 230static u64 div_factor(u64 num, int factor)
217{ 231{
232 if (factor == 10)
233 return num;
218 num *= factor; 234 num *= factor;
219 do_div(num, 10); 235 do_div(num, 10);
220 return num; 236 return num;
@@ -247,9 +263,10 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
247 if (!owner) 263 if (!owner)
248 factor = 8; 264 factor = 8;
249 265
250 if (data == BTRFS_BLOCK_GROUP_MIXED) 266 if (data == BTRFS_BLOCK_GROUP_MIXED) {
251 bit = BLOCK_GROUP_DATA | BLOCK_GROUP_METADATA; 267 bit = BLOCK_GROUP_DATA | BLOCK_GROUP_METADATA;
252 else if (data) 268 factor = 10;
269 } else if (data)
253 bit = BLOCK_GROUP_DATA; 270 bit = BLOCK_GROUP_DATA;
254 else 271 else
255 bit = BLOCK_GROUP_METADATA; 272 bit = BLOCK_GROUP_METADATA;
@@ -918,6 +935,10 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
918 935
919 level = btrfs_header_level(root->node); 936 level = btrfs_header_level(root->node);
920 937
938 if (num_bytes >= 96 * 1024 * 1024 && hint_byte) {
939 data = BTRFS_BLOCK_GROUP_MIXED;
940 }
941
921 if (search_end == (u64)-1) 942 if (search_end == (u64)-1)
922 search_end = btrfs_super_total_bytes(&info->super_copy); 943 search_end = btrfs_super_total_bytes(&info->super_copy);
923 if (hint_byte) { 944 if (hint_byte) {
@@ -937,6 +958,7 @@ check_failed:
937 search_start = find_search_start(root, &block_group, 958 search_start = find_search_start(root, &block_group,
938 search_start, total_needed, data); 959 search_start, total_needed, data);
939 cached_start = search_start; 960 cached_start = search_start;
961
940 btrfs_init_path(path); 962 btrfs_init_path(path);
941 ins->objectid = search_start; 963 ins->objectid = search_start;
942 ins->offset = 0; 964 ins->offset = 0;
@@ -1021,7 +1043,8 @@ check_failed:
1021 start_found = 1; 1043 start_found = 1;
1022 last_byte = key.objectid + key.offset; 1044 last_byte = key.objectid + key.offset;
1023 1045
1024 if (!full_scan && last_byte >= block_group->key.objectid + 1046 if (!full_scan && data != BTRFS_BLOCK_GROUP_MIXED &&
1047 last_byte >= block_group->key.objectid +
1025 block_group->key.offset) { 1048 block_group->key.offset) {
1026 btrfs_release_path(root, path); 1049 btrfs_release_path(root, path);
1027 search_start = block_group->key.objectid + 1050 search_start = block_group->key.objectid +
@@ -1042,7 +1065,8 @@ check_pending:
1042 if (ins->objectid + num_bytes >= search_end) 1065 if (ins->objectid + num_bytes >= search_end)
1043 goto enospc; 1066 goto enospc;
1044 1067
1045 if (!full_scan && ins->objectid + num_bytes >= block_group-> 1068 if (!full_scan && data != BTRFS_BLOCK_GROUP_MIXED &&
1069 ins->objectid + num_bytes >= block_group->
1046 key.objectid + block_group->key.offset) { 1070 key.objectid + block_group->key.offset) {
1047 search_start = block_group->key.objectid + 1071 search_start = block_group->key.objectid +
1048 block_group->key.offset; 1072 block_group->key.offset;