diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-05-30 10:22:12 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-05-30 10:22:12 -0400 |
commit | fbdc762b4e1833b5d75cada5aabeadccd8379792 (patch) | |
tree | 776a98aeea04e03737b02c5caedac24fa144acdb /fs/btrfs/extent-tree.c | |
parent | 1e2677e000fbc7f1892b1ea9f952f1667f4443f1 (diff) |
Btrfs: use a separate flag for search_start vs a hint in find_free_extent
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 | 69 |
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 | ||
7 | static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | 7 | static 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); | ||
10 | static int finish_current_insert(struct btrfs_trans_handle *trans, struct | 11 | static int finish_current_insert(struct btrfs_trans_handle *trans, struct |
11 | btrfs_root *extent_root); | 12 | btrfs_root *extent_root); |
12 | static int del_pending_extents(struct btrfs_trans_handle *trans, struct | 13 | static 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 | */ |
907 | static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | 902 | static 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: | |||
1132 | new_group: | 1134 | new_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; |
1135 | printk("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 | ||
1145 | error: | 1153 | error: |
@@ -1156,12 +1164,13 @@ error: | |||
1156 | */ | 1164 | */ |
1157 | int btrfs_alloc_extent(struct btrfs_trans_handle *trans, | 1165 | int 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 | } |