aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent-tree.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r--fs/btrfs/extent-tree.c76
1 files changed, 62 insertions, 14 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 1497ff98f0d3..e3c6bfea3751 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -12,6 +12,33 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct
12static int del_pending_extents(struct btrfs_trans_handle *trans, struct 12static int del_pending_extents(struct btrfs_trans_handle *trans, struct
13 btrfs_root *extent_root); 13 btrfs_root *extent_root);
14 14
15static void reada_extent_leaves(struct btrfs_root *root,
16 struct btrfs_path *path, u64 limit)
17{
18 struct btrfs_node *node;
19 int i;
20 int nritems;
21 u64 item_objectid;
22 u64 blocknr;
23 int slot;
24 int ret;
25
26 if (!path->nodes[1])
27 return;
28 node = btrfs_buffer_node(path->nodes[1]);
29 slot = path->slots[1] + 1;
30 nritems = btrfs_header_nritems(&node->header);
31 for (i = slot; i < nritems && i < slot + 8; i++) {
32 item_objectid = btrfs_disk_key_objectid(&node->ptrs[i].key);
33 if (item_objectid > limit)
34 break;
35 blocknr = btrfs_node_blockptr(node, i);
36 ret = readahead_tree_block(root, blocknr);
37 if (ret)
38 break;
39 }
40}
41
15static int cache_block_group(struct btrfs_root *root, 42static int cache_block_group(struct btrfs_root *root,
16 struct btrfs_block_group_cache *block_group) 43 struct btrfs_block_group_cache *block_group)
17{ 44{
@@ -24,6 +51,7 @@ static int cache_block_group(struct btrfs_root *root,
24 u64 i; 51 u64 i;
25 u64 last = 0; 52 u64 last = 0;
26 u64 hole_size; 53 u64 hole_size;
54 u64 limit;
27 int found = 0; 55 int found = 0;
28 56
29 root = root->fs_info->extent_root; 57 root = root->fs_info->extent_root;
@@ -46,14 +74,17 @@ printk("cache block group %Lu\n", block_group->key.objectid);
46 return ret; 74 return ret;
47 if (ret && path->slots[0] > 0) 75 if (ret && path->slots[0] > 0)
48 path->slots[0]--; 76 path->slots[0]--;
77 limit = block_group->key.objectid + block_group->key.offset;
78 reada_extent_leaves(root, path, limit);
49 while(1) { 79 while(1) {
50 leaf = btrfs_buffer_leaf(path->nodes[0]); 80 leaf = btrfs_buffer_leaf(path->nodes[0]);
51 slot = path->slots[0]; 81 slot = path->slots[0];
52 if (slot >= btrfs_header_nritems(&leaf->header)) { 82 if (slot >= btrfs_header_nritems(&leaf->header)) {
83 reada_extent_leaves(root, path, limit);
53 ret = btrfs_next_leaf(root, path); 84 ret = btrfs_next_leaf(root, path);
54 if (ret == 0) 85 if (ret == 0) {
55 continue; 86 continue;
56 else { 87 } else {
57 if (found) { 88 if (found) {
58 hole_size = block_group->key.objectid + 89 hole_size = block_group->key.objectid +
59 block_group->key.offset - last; 90 block_group->key.offset - last;
@@ -187,7 +218,7 @@ new_group:
187 return max((*cache_ret)->last_alloc, search_start); 218 return max((*cache_ret)->last_alloc, search_start);
188 } 219 }
189 cache = btrfs_find_block_group(root, cache, 220 cache = btrfs_find_block_group(root, cache,
190 last + cache->key.offset - 1, 0); 221 last + cache->key.offset - 1, 0, 0);
191 *cache_ret = cache; 222 *cache_ret = cache;
192 goto again; 223 goto again;
193} 224}
@@ -195,7 +226,7 @@ new_group:
195struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root, 226struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
196 struct btrfs_block_group_cache 227 struct btrfs_block_group_cache
197 *hint, u64 search_start, 228 *hint, u64 search_start,
198 int data) 229 int data, int owner)
199{ 230{
200 struct btrfs_block_group_cache *cache[8]; 231 struct btrfs_block_group_cache *cache[8];
201 struct btrfs_block_group_cache *found_group = NULL; 232 struct btrfs_block_group_cache *found_group = NULL;
@@ -207,6 +238,10 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
207 int i; 238 int i;
208 int ret; 239 int ret;
209 int full_search = 0; 240 int full_search = 0;
241 int factor = 8;
242
243 if (!owner)
244 factor = 5;
210 245
211 if (data) 246 if (data)
212 radix = &info->block_group_data_radix; 247 radix = &info->block_group_data_radix;
@@ -219,14 +254,14 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
219 if (shint->data == data) { 254 if (shint->data == data) {
220 used = btrfs_block_group_used(&shint->item); 255 used = btrfs_block_group_used(&shint->item);
221 if (used + shint->pinned < 256 if (used + shint->pinned <
222 (shint->key.offset * 8) / 10) { 257 (shint->key.offset * factor) / 10) {
223 return shint; 258 return shint;
224 } 259 }
225 } 260 }
226 } 261 }
227 if (hint && hint->data == data) { 262 if (hint && hint->data == data) {
228 used = btrfs_block_group_used(&hint->item); 263 used = btrfs_block_group_used(&hint->item);
229 if (used + hint->pinned < (hint->key.offset * 8) / 10) { 264 if (used + hint->pinned < (hint->key.offset * factor) / 10) {
230 return hint; 265 return hint;
231 } 266 }
232 if (used >= (hint->key.offset * 8) / 10) { 267 if (used >= (hint->key.offset * 8) / 10) {
@@ -261,7 +296,7 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
261 cache[i]->key.offset; 296 cache[i]->key.offset;
262 used = btrfs_block_group_used(&cache[i]->item); 297 used = btrfs_block_group_used(&cache[i]->item);
263 if (used + cache[i]->pinned < 298 if (used + cache[i]->pinned <
264 (cache[i]->key.offset * 8) / 10) { 299 (cache[i]->key.offset * factor) / 10) {
265 found_group = cache[i]; 300 found_group = cache[i];
266 goto found; 301 goto found;
267 } 302 }
@@ -272,6 +307,7 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
272 BTRFS_BLOCK_GROUP_AVAIL); 307 BTRFS_BLOCK_GROUP_AVAIL);
273 } 308 }
274 } 309 }
310 cond_resched();
275 } 311 }
276 last = hint_last; 312 last = hint_last;
277again: 313again:
@@ -295,13 +331,16 @@ again:
295 BTRFS_BLOCK_GROUP_AVAIL); 331 BTRFS_BLOCK_GROUP_AVAIL);
296 } 332 }
297 } 333 }
334 cond_resched();
298 } 335 }
299 if (!full_search) { 336 if (!full_search) {
337printk("find block group doing full search data %d start %Lu\n", data, search_start);
300 last = search_start; 338 last = search_start;
301 full_search = 1; 339 full_search = 1;
302 goto again; 340 goto again;
303 } 341 }
304 if (!found_group) { 342 if (!found_group) {
343printk("find block group bailing to zero data %d\n", data);
305 ret = radix_tree_gang_lookup(radix, 344 ret = radix_tree_gang_lookup(radix,
306 (void **)&found_group, 0, 1); 345 (void **)&found_group, 0, 1);
307 BUG_ON(ret != 1); 346 BUG_ON(ret != 1);
@@ -554,8 +593,8 @@ static int update_block_group(struct btrfs_trans_handle *trans,
554 blocknr + i); 593 blocknr + i);
555 } 594 }
556 } 595 }
557 if (old_val < (cache->key.offset * 6) / 10 && 596 if (old_val < (cache->key.offset * 5) / 10 &&
558 old_val + num >= (cache->key.offset * 6) / 10) { 597 old_val + num >= (cache->key.offset * 5) / 10) {
559printk("group %Lu now available\n", cache->key.objectid); 598printk("group %Lu now available\n", cache->key.objectid);
560 radix_tree_tag_set(cache->radix, 599 radix_tree_tag_set(cache->radix,
561 cache->key.objectid + 600 cache->key.objectid +
@@ -842,6 +881,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
842 int level; 881 int level;
843 struct btrfs_block_group_cache *block_group; 882 struct btrfs_block_group_cache *block_group;
844 int full_scan = 0; 883 int full_scan = 0;
884 u64 limit;
845 885
846 path = btrfs_alloc_path(); 886 path = btrfs_alloc_path();
847 ins->flags = 0; 887 ins->flags = 0;
@@ -858,11 +898,11 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
858 if (search_start) { 898 if (search_start) {
859 block_group = lookup_block_group(info, search_start); 899 block_group = lookup_block_group(info, search_start);
860 block_group = btrfs_find_block_group(root, block_group, 900 block_group = btrfs_find_block_group(root, block_group,
861 search_start, data); 901 search_start, data, 1);
862 } else { 902 } else {
863 block_group = btrfs_find_block_group(root, 903 block_group = btrfs_find_block_group(root,
864 trans->block_group, 0, 904 trans->block_group, 0,
865 data); 905 data, 1);
866 } 906 }
867 907
868check_failed: 908check_failed:
@@ -916,6 +956,12 @@ check_failed:
916 info->extent_tree_prealloc_nr = 0; 956 info->extent_tree_prealloc_nr = 0;
917 total_found = 0; 957 total_found = 0;
918 } 958 }
959 if (start_found)
960 limit = last_block +
961 block_group->key.offset / 2;
962 else
963 limit = search_start +
964 block_group->key.offset / 2;
919 ret = btrfs_next_leaf(root, path); 965 ret = btrfs_next_leaf(root, path);
920 if (ret == 0) 966 if (ret == 0)
921 continue; 967 continue;
@@ -960,6 +1006,7 @@ check_failed:
960 } 1006 }
961next: 1007next:
962 path->slots[0]++; 1008 path->slots[0]++;
1009 cond_resched();
963 } 1010 }
964 // FIXME -ENOSPC 1011 // FIXME -ENOSPC
965check_pending: 1012check_pending:
@@ -1049,7 +1096,8 @@ printk("doing full scan!\n");
1049 block_group = lookup_block_group(info, search_start); 1096 block_group = lookup_block_group(info, search_start);
1050 if (!full_scan) 1097 if (!full_scan)
1051 block_group = btrfs_find_block_group(root, block_group, 1098 block_group = btrfs_find_block_group(root, block_group,
1052 search_start, data); 1099 search_start, data, 0);
1100 cond_resched();
1053 goto check_failed; 1101 goto check_failed;
1054 1102
1055error: 1103error:
@@ -1102,7 +1150,7 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
1102 * in the correct block group. 1150 * in the correct block group.
1103 */ 1151 */
1104 if (data) { 1152 if (data) {
1105 ret = find_free_extent(trans, root, 0, search_start, 1153 ret = find_free_extent(trans, root, 0, 0,
1106 search_end, &prealloc_key, 0); 1154 search_end, &prealloc_key, 0);
1107 if (ret) { 1155 if (ret) {
1108 return ret; 1156 return ret;
@@ -1173,7 +1221,7 @@ struct buffer_head *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
1173 struct buffer_head *buf; 1221 struct buffer_head *buf;
1174 1222
1175 ret = btrfs_alloc_extent(trans, root, root->root_key.objectid, 1223 ret = btrfs_alloc_extent(trans, root, root->root_key.objectid,
1176 1, 0, (unsigned long)-1, &ins, 0); 1224 1, hint, (unsigned long)-1, &ins, 0);
1177 if (ret) { 1225 if (ret) {
1178 BUG(); 1226 BUG();
1179 return NULL; 1227 return NULL;