diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-11-07 21:08:16 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:03:57 -0400 |
commit | 257d0ce36f215937602eb5c1b328b69afaf3bcd8 (patch) | |
tree | 4a08be69cd4807950e973d7ec797ce284eff5640 /fs/btrfs/extent-tree.c | |
parent | 09be207d1ba224531a61de9afdc07a125e45318c (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.c | 36 |
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 | ||
173 | again: | 174 | again: |
@@ -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 | ||
216 | static u64 div_factor(u64 num, int factor) | 230 | static 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; |