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.c69
1 files changed, 42 insertions, 27 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index b6dc020bdde9..85616b458e18 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -5,8 +5,9 @@
5#include "transaction.h" 5#include "transaction.h"
6 6
7static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root 7static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
8 *orig_root, u64 num_blocks, u64 search_start, u64 8 *orig_root, u64 num_blocks, u64 search_start,
9 search_end, struct btrfs_key *ins, int data); 9 u64 search_end, u64 hint_block,
10 struct btrfs_key *ins, int data);
10static int finish_current_insert(struct btrfs_trans_handle *trans, struct 11static int finish_current_insert(struct btrfs_trans_handle *trans, struct
11 btrfs_root *extent_root); 12 btrfs_root *extent_root);
12static int del_pending_extents(struct btrfs_trans_handle *trans, struct 13static int del_pending_extents(struct btrfs_trans_handle *trans, struct
@@ -157,12 +158,6 @@ static struct btrfs_block_group_cache *lookup_block_group(struct
157 block_group->key.objectid + block_group->key.offset) 158 block_group->key.objectid + block_group->key.offset)
158 return block_group; 159 return block_group;
159 } 160 }
160 WARN_ON(1);
161 printk("lookup_block_group fails for blocknr %Lu\n", blocknr);
162 printk("last ret was %d\n", ret);
163 if (ret) {
164 printk("last block group was %Lu %Lu\n", block_group->key.objectid, block_group->key.offset);
165 }
166 return NULL; 161 return NULL;
167} 162}
168 163
@@ -378,7 +373,7 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
378 struct btrfs_key ins; 373 struct btrfs_key ins;
379 u32 refs; 374 u32 refs;
380 375
381 find_free_extent(trans, root->fs_info->extent_root, 0, 0, (u64)-1, 376 find_free_extent(trans, root->fs_info->extent_root, 0, 0, (u64)-1, 0,
382 &ins, 0); 377 &ins, 0);
383 path = btrfs_alloc_path(); 378 path = btrfs_alloc_path();
384 BUG_ON(!path); 379 BUG_ON(!path);
@@ -495,7 +490,7 @@ static int write_one_cache_group(struct btrfs_trans_handle *trans,
495 struct btrfs_block_group_item *bi; 490 struct btrfs_block_group_item *bi;
496 struct btrfs_key ins; 491 struct btrfs_key ins;
497 492
498 find_free_extent(trans, extent_root, 0, 0, (u64)-1, &ins, 0); 493 find_free_extent(trans, extent_root, 0, 0, (u64)-1, 0, &ins, 0);
499 ret = btrfs_search_slot(trans, extent_root, &cache->key, path, 0, 1); 494 ret = btrfs_search_slot(trans, extent_root, &cache->key, path, 0, 1);
500 BUG_ON(ret); 495 BUG_ON(ret);
501 bi = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0], 496 bi = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0],
@@ -788,7 +783,7 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
788 btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); 783 btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
789 key.offset = num_blocks; 784 key.offset = num_blocks;
790 785
791 find_free_extent(trans, root, 0, 0, (u64)-1, &ins, 0); 786 find_free_extent(trans, root, 0, 0, (u64)-1, 0, &ins, 0);
792 path = btrfs_alloc_path(); 787 path = btrfs_alloc_path();
793 BUG_ON(!path); 788 BUG_ON(!path);
794 btrfs_init_path(path); 789 btrfs_init_path(path);
@@ -906,7 +901,8 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
906 */ 901 */
907static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root 902static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
908 *orig_root, u64 num_blocks, u64 search_start, u64 903 *orig_root, u64 num_blocks, u64 search_start, u64
909 search_end, struct btrfs_key *ins, int data) 904 search_end, u64 hint_block,
905 struct btrfs_key *ins, int data)
910{ 906{
911 struct btrfs_path *path; 907 struct btrfs_path *path;
912 struct btrfs_key key; 908 struct btrfs_key key;
@@ -926,6 +922,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
926 int level; 922 int level;
927 struct btrfs_block_group_cache *block_group; 923 struct btrfs_block_group_cache *block_group;
928 int full_scan = 0; 924 int full_scan = 0;
925 int wrapped = 0;
929 u64 limit; 926 u64 limit;
930 927
931 path = btrfs_alloc_path(); 928 path = btrfs_alloc_path();
@@ -940,10 +937,10 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
940 } 937 }
941 if (search_end == (u64)-1) 938 if (search_end == (u64)-1)
942 search_end = btrfs_super_total_blocks(info->disk_super); 939 search_end = btrfs_super_total_blocks(info->disk_super);
943 if (search_start) { 940 if (hint_block) {
944 block_group = lookup_block_group(info, search_start); 941 block_group = lookup_block_group(info, hint_block);
945 block_group = btrfs_find_block_group(root, block_group, 942 block_group = btrfs_find_block_group(root, block_group,
946 search_start, data, 1); 943 hint_block, data, 1);
947 } else { 944 } else {
948 block_group = btrfs_find_block_group(root, 945 block_group = btrfs_find_block_group(root,
949 trans->block_group, 0, 946 trans->block_group, 0,
@@ -954,7 +951,7 @@ check_failed:
954 if (!block_group->data) 951 if (!block_group->data)
955 search_start = find_search_start(root, &block_group, 952 search_start = find_search_start(root, &block_group,
956 search_start, total_needed); 953 search_start, total_needed);
957 else 954 else if (!full_scan)
958 search_start = max(block_group->last_alloc, search_start); 955 search_start = max(block_group->last_alloc, search_start);
959 956
960 btrfs_init_path(path); 957 btrfs_init_path(path);
@@ -1039,7 +1036,7 @@ check_failed:
1039 1036
1040 start_found = 1; 1037 start_found = 1;
1041 last_block = key.objectid + key.offset; 1038 last_block = key.objectid + key.offset;
1042 if (last_block >= block_group->key.objectid + 1039 if (!full_scan && last_block >= block_group->key.objectid +
1043 block_group->key.offset) { 1040 block_group->key.offset) {
1044 btrfs_release_path(root, path); 1041 btrfs_release_path(root, path);
1045 search_start = block_group->key.objectid + 1042 search_start = block_group->key.objectid +
@@ -1059,10 +1056,15 @@ check_pending:
1059 BUG_ON(ins->objectid < search_start); 1056 BUG_ON(ins->objectid < search_start);
1060 1057
1061 if (ins->objectid + num_blocks >= search_end) { 1058 if (ins->objectid + num_blocks >= search_end) {
1062 if (full_scan) 1059 if (full_scan) {
1063 return -ENOSPC; 1060 ret = -ENOSPC;
1061 goto error;
1062 }
1064 search_start = orig_search_start; 1063 search_start = orig_search_start;
1065 full_scan = 1; 1064 if (wrapped)
1065 full_scan = 1;
1066 else
1067 wrapped = 1;
1066 goto new_group; 1068 goto new_group;
1067 } 1069 }
1068 for (test_block = ins->objectid; 1070 for (test_block = ins->objectid;
@@ -1132,14 +1134,20 @@ check_pending:
1132new_group: 1134new_group:
1133 if (search_start + num_blocks >= search_end) { 1135 if (search_start + num_blocks >= search_end) {
1134 search_start = orig_search_start; 1136 search_start = orig_search_start;
1135printk("doing full scan!\n"); 1137 if (full_scan) {
1136 full_scan = 1; 1138 ret = -ENOSPC;
1139 goto error;
1140 }
1141 if (wrapped)
1142 full_scan = 1;
1143 else
1144 wrapped = 1;
1137 } 1145 }
1138 block_group = lookup_block_group(info, search_start); 1146 block_group = lookup_block_group(info, search_start);
1147 cond_resched();
1139 if (!full_scan) 1148 if (!full_scan)
1140 block_group = btrfs_find_block_group(root, block_group, 1149 block_group = btrfs_find_block_group(root, block_group,
1141 search_start, data, 0); 1150 search_start, data, 0);
1142 cond_resched();
1143 goto check_failed; 1151 goto check_failed;
1144 1152
1145error: 1153error:
@@ -1156,12 +1164,13 @@ error:
1156 */ 1164 */
1157int btrfs_alloc_extent(struct btrfs_trans_handle *trans, 1165int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
1158 struct btrfs_root *root, u64 owner, 1166 struct btrfs_root *root, u64 owner,
1159 u64 num_blocks, u64 search_start, 1167 u64 num_blocks, u64 hint_block,
1160 u64 search_end, struct btrfs_key *ins, int data) 1168 u64 search_end, struct btrfs_key *ins, int data)
1161{ 1169{
1162 int ret; 1170 int ret;
1163 int pending_ret; 1171 int pending_ret;
1164 u64 super_blocks_used; 1172 u64 super_blocks_used;
1173 u64 search_start = 0;
1165 struct btrfs_fs_info *info = root->fs_info; 1174 struct btrfs_fs_info *info = root->fs_info;
1166 struct btrfs_root *extent_root = info->extent_root; 1175 struct btrfs_root *extent_root = info->extent_root;
1167 struct btrfs_extent_item extent_item; 1176 struct btrfs_extent_item extent_item;
@@ -1193,7 +1202,7 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
1193 */ 1202 */
1194 if (data) { 1203 if (data) {
1195 ret = find_free_extent(trans, root, 0, 0, 1204 ret = find_free_extent(trans, root, 0, 0,
1196 search_end, &prealloc_key, 0); 1205 search_end, 0, &prealloc_key, 0);
1197 if (ret) { 1206 if (ret) {
1198 return ret; 1207 return ret;
1199 } 1208 }
@@ -1204,9 +1213,11 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
1204 search_start = info->extent_tree_prealloc[0] + 1; 1213 search_start = info->extent_tree_prealloc[0] + 1;
1205 } 1214 }
1206 } 1215 }
1216 if (hint_block < search_start)
1217 hint_block = search_start;
1207 /* do the real allocation */ 1218 /* do the real allocation */
1208 ret = find_free_extent(trans, root, num_blocks, search_start, 1219 ret = find_free_extent(trans, root, num_blocks, search_start,
1209 search_end, ins, data); 1220 search_end, hint_block, ins, data);
1210 if (ret) { 1221 if (ret) {
1211 return ret; 1222 return ret;
1212 } 1223 }
@@ -1226,8 +1237,12 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
1226 else 1237 else
1227 search_start = ins->objectid + ins->offset; 1238 search_start = ins->objectid + ins->offset;
1228 1239
1240 if (hint_block < search_start)
1241 hint_block = search_start;
1242
1229 ret = find_free_extent(trans, root, 0, search_start, 1243 ret = find_free_extent(trans, root, 0, search_start,
1230 search_end, &prealloc_key, 0); 1244 search_end, hint_block,
1245 &prealloc_key, 0);
1231 if (ret) { 1246 if (ret) {
1232 return ret; 1247 return ret;
1233 } 1248 }