diff options
-rw-r--r-- | fs/btrfs/ctree.h | 7 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 3 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 230 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 2 | ||||
-rw-r--r-- | fs/btrfs/transaction.h | 2 |
5 files changed, 49 insertions, 195 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 8b7d01597f4f..59e09e37ab93 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -299,12 +299,7 @@ struct btrfs_fs_info { | |||
299 | struct radix_tree_root block_group_radix; | 299 | struct radix_tree_root block_group_radix; |
300 | struct radix_tree_root block_group_data_radix; | 300 | struct radix_tree_root block_group_data_radix; |
301 | struct radix_tree_root extent_map_radix; | 301 | struct radix_tree_root extent_map_radix; |
302 | 302 | struct radix_tree_root extent_ins_radix; | |
303 | u64 extent_tree_insert[BTRFS_MAX_LEVEL * 6]; | ||
304 | int extent_tree_insert_nr; | ||
305 | u64 extent_tree_prealloc[BTRFS_MAX_LEVEL * 6]; | ||
306 | int extent_tree_prealloc_nr; | ||
307 | |||
308 | u64 generation; | 303 | u64 generation; |
309 | struct btrfs_transaction *running_transaction; | 304 | struct btrfs_transaction *running_transaction; |
310 | struct btrfs_super_block *disk_super; | 305 | struct btrfs_super_block *disk_super; |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index c948416fea3a..192211274ce5 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -427,6 +427,7 @@ struct btrfs_root *open_ctree(struct super_block *sb) | |||
427 | init_bit_radix(&fs_info->pinned_radix); | 427 | init_bit_radix(&fs_info->pinned_radix); |
428 | init_bit_radix(&fs_info->pending_del_radix); | 428 | init_bit_radix(&fs_info->pending_del_radix); |
429 | init_bit_radix(&fs_info->extent_map_radix); | 429 | init_bit_radix(&fs_info->extent_map_radix); |
430 | init_bit_radix(&fs_info->extent_ins_radix); | ||
430 | INIT_RADIX_TREE(&fs_info->fs_roots_radix, GFP_NOFS); | 431 | INIT_RADIX_TREE(&fs_info->fs_roots_radix, GFP_NOFS); |
431 | INIT_RADIX_TREE(&fs_info->block_group_radix, GFP_KERNEL); | 432 | INIT_RADIX_TREE(&fs_info->block_group_radix, GFP_KERNEL); |
432 | INIT_RADIX_TREE(&fs_info->block_group_data_radix, GFP_KERNEL); | 433 | INIT_RADIX_TREE(&fs_info->block_group_data_radix, GFP_KERNEL); |
@@ -443,8 +444,6 @@ struct btrfs_root *open_ctree(struct super_block *sb) | |||
443 | fs_info->btree_inode->i_size = sb->s_bdev->bd_inode->i_size; | 444 | fs_info->btree_inode->i_size = sb->s_bdev->bd_inode->i_size; |
444 | fs_info->btree_inode->i_mapping->a_ops = &btree_aops; | 445 | fs_info->btree_inode->i_mapping->a_ops = &btree_aops; |
445 | fs_info->do_barriers = 1; | 446 | fs_info->do_barriers = 1; |
446 | fs_info->extent_tree_insert_nr = 0; | ||
447 | fs_info->extent_tree_prealloc_nr = 0; | ||
448 | fs_info->closing = 0; | 447 | fs_info->closing = 0; |
449 | 448 | ||
450 | INIT_DELAYED_WORK(&fs_info->trans_work, btrfs_transaction_cleaner); | 449 | INIT_DELAYED_WORK(&fs_info->trans_work, btrfs_transaction_cleaner); |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index f7d76d34fc37..ba50bd7b9a78 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -22,12 +22,6 @@ | |||
22 | #include "print-tree.h" | 22 | #include "print-tree.h" |
23 | #include "transaction.h" | 23 | #include "transaction.h" |
24 | 24 | ||
25 | static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | ||
26 | *orig_root, u64 num_blocks, u64 empty_size, | ||
27 | u64 search_start, | ||
28 | u64 search_end, u64 hint_block, | ||
29 | struct btrfs_key *ins, u64 exclude_start, | ||
30 | u64 exclude_nr, int data); | ||
31 | static int finish_current_insert(struct btrfs_trans_handle *trans, struct | 25 | static int finish_current_insert(struct btrfs_trans_handle *trans, struct |
32 | btrfs_root *extent_root); | 26 | btrfs_root *extent_root); |
33 | static int del_pending_extents(struct btrfs_trans_handle *trans, struct | 27 | static int del_pending_extents(struct btrfs_trans_handle *trans, struct |
@@ -174,9 +168,6 @@ static u64 find_search_start(struct btrfs_root *root, | |||
174 | 168 | ||
175 | if (cache->data) | 169 | if (cache->data) |
176 | goto out; | 170 | goto out; |
177 | if (num > 1) { | ||
178 | last = max(last, cache->last_prealloc); | ||
179 | } | ||
180 | again: | 171 | again: |
181 | ret = cache_block_group(root, cache); | 172 | ret = cache_block_group(root, cache); |
182 | if (ret) | 173 | if (ret) |
@@ -374,18 +365,12 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, | |||
374 | struct btrfs_key key; | 365 | struct btrfs_key key; |
375 | struct btrfs_leaf *l; | 366 | struct btrfs_leaf *l; |
376 | struct btrfs_extent_item *item; | 367 | struct btrfs_extent_item *item; |
377 | struct btrfs_key ins; | ||
378 | u32 refs; | 368 | u32 refs; |
379 | 369 | ||
380 | path = btrfs_alloc_path(); | 370 | path = btrfs_alloc_path(); |
381 | if (!path) | 371 | if (!path) |
382 | return -ENOMEM; | 372 | return -ENOMEM; |
383 | ret = find_free_extent(trans, root->fs_info->extent_root, 0, 0, 0, | 373 | |
384 | (u64)-1, 0, &ins, 0, 0, 0); | ||
385 | if (ret) { | ||
386 | btrfs_free_path(path); | ||
387 | return ret; | ||
388 | } | ||
389 | key.objectid = blocknr; | 374 | key.objectid = blocknr; |
390 | key.flags = 0; | 375 | key.flags = 0; |
391 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); | 376 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); |
@@ -532,13 +517,7 @@ static int write_one_cache_group(struct btrfs_trans_handle *trans, | |||
532 | int pending_ret; | 517 | int pending_ret; |
533 | struct btrfs_root *extent_root = root->fs_info->extent_root; | 518 | struct btrfs_root *extent_root = root->fs_info->extent_root; |
534 | struct btrfs_block_group_item *bi; | 519 | struct btrfs_block_group_item *bi; |
535 | struct btrfs_key ins; | ||
536 | 520 | ||
537 | ret = find_free_extent(trans, extent_root, 0, 0, 0, (u64)-1, 0, &ins, | ||
538 | 0, 0, 0); | ||
539 | /* FIXME, set bit to recalc cache groups on next mount */ | ||
540 | if (ret) | ||
541 | return ret; | ||
542 | ret = btrfs_search_slot(trans, extent_root, &cache->key, path, 0, 1); | 521 | ret = btrfs_search_slot(trans, extent_root, &cache->key, path, 0, 1); |
543 | if (ret < 0) | 522 | if (ret < 0) |
544 | goto fail; | 523 | goto fail; |
@@ -706,14 +685,6 @@ static int update_block_group(struct btrfs_trans_handle *trans, | |||
706 | return 0; | 685 | return 0; |
707 | } | 686 | } |
708 | 687 | ||
709 | static int try_remove_page(struct address_space *mapping, unsigned long index) | ||
710 | { | ||
711 | int ret; | ||
712 | return 0; | ||
713 | ret = invalidate_mapping_pages(mapping, index, index); | ||
714 | return ret; | ||
715 | } | ||
716 | |||
717 | int btrfs_copy_pinned(struct btrfs_root *root, struct radix_tree_root *copy) | 688 | int btrfs_copy_pinned(struct btrfs_root *root, struct radix_tree_root *copy) |
718 | { | 689 | { |
719 | unsigned long gang[8]; | 690 | unsigned long gang[8]; |
@@ -732,6 +703,9 @@ int btrfs_copy_pinned(struct btrfs_root *root, struct radix_tree_root *copy) | |||
732 | last = gang[i] + 1; | 703 | last = gang[i] + 1; |
733 | } | 704 | } |
734 | } | 705 | } |
706 | ret = find_first_radix_bit(&root->fs_info->extent_ins_radix, gang, 0, | ||
707 | ARRAY_SIZE(gang)); | ||
708 | WARN_ON(ret); | ||
735 | return 0; | 709 | return 0; |
736 | } | 710 | } |
737 | 711 | ||
@@ -740,7 +714,6 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, | |||
740 | struct radix_tree_root *unpin_radix) | 714 | struct radix_tree_root *unpin_radix) |
741 | { | 715 | { |
742 | unsigned long gang[8]; | 716 | unsigned long gang[8]; |
743 | struct inode *btree_inode = root->fs_info->btree_inode; | ||
744 | struct btrfs_block_group_cache *block_group; | 717 | struct btrfs_block_group_cache *block_group; |
745 | u64 first = 0; | 718 | u64 first = 0; |
746 | int ret; | 719 | int ret; |
@@ -765,14 +738,9 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, | |||
765 | block_group->pinned--; | 738 | block_group->pinned--; |
766 | if (gang[i] < block_group->last_alloc) | 739 | if (gang[i] < block_group->last_alloc) |
767 | block_group->last_alloc = gang[i]; | 740 | block_group->last_alloc = gang[i]; |
768 | if (gang[i] < block_group->last_prealloc) | ||
769 | block_group->last_prealloc = gang[i]; | ||
770 | if (!block_group->data) | 741 | if (!block_group->data) |
771 | set_radix_bit(extent_radix, gang[i]); | 742 | set_radix_bit(extent_radix, gang[i]); |
772 | } | 743 | } |
773 | try_remove_page(btree_inode->i_mapping, | ||
774 | gang[i] << (PAGE_CACHE_SHIFT - | ||
775 | btree_inode->i_blkbits)); | ||
776 | } | 744 | } |
777 | } | 745 | } |
778 | return 0; | 746 | return 0; |
@@ -785,7 +753,8 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct | |||
785 | struct btrfs_extent_item extent_item; | 753 | struct btrfs_extent_item extent_item; |
786 | int i; | 754 | int i; |
787 | int ret; | 755 | int ret; |
788 | u64 super_blocks_used; | 756 | int err; |
757 | unsigned long gang[8]; | ||
789 | struct btrfs_fs_info *info = extent_root->fs_info; | 758 | struct btrfs_fs_info *info = extent_root->fs_info; |
790 | 759 | ||
791 | btrfs_set_extent_refs(&extent_item, 1); | 760 | btrfs_set_extent_refs(&extent_item, 1); |
@@ -794,16 +763,21 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct | |||
794 | btrfs_set_key_type(&ins, BTRFS_EXTENT_ITEM_KEY); | 763 | btrfs_set_key_type(&ins, BTRFS_EXTENT_ITEM_KEY); |
795 | btrfs_set_extent_owner(&extent_item, extent_root->root_key.objectid); | 764 | btrfs_set_extent_owner(&extent_item, extent_root->root_key.objectid); |
796 | 765 | ||
797 | for (i = 0; i < extent_root->fs_info->extent_tree_insert_nr; i++) { | 766 | while(1) { |
798 | ins.objectid = extent_root->fs_info->extent_tree_insert[i]; | 767 | ret = find_first_radix_bit(&info->extent_ins_radix, gang, 0, |
799 | super_blocks_used = btrfs_super_blocks_used(&info->super_copy); | 768 | ARRAY_SIZE(gang)); |
800 | btrfs_set_super_blocks_used(&info->super_copy, | 769 | if (!ret) |
801 | super_blocks_used + 1); | 770 | break; |
802 | ret = btrfs_insert_item(trans, extent_root, &ins, &extent_item, | 771 | |
803 | sizeof(extent_item)); | 772 | for (i = 0; i < ret; i++) { |
804 | BUG_ON(ret); | 773 | ins.objectid = gang[i]; |
774 | err = btrfs_insert_item(trans, extent_root, &ins, | ||
775 | &extent_item, | ||
776 | sizeof(extent_item)); | ||
777 | clear_radix_bit(&info->extent_ins_radix, gang[i]); | ||
778 | WARN_ON(err); | ||
779 | } | ||
805 | } | 780 | } |
806 | extent_root->fs_info->extent_tree_insert_nr = 0; | ||
807 | return 0; | 781 | return 0; |
808 | } | 782 | } |
809 | 783 | ||
@@ -856,7 +830,6 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
856 | struct btrfs_root *extent_root = info->extent_root; | 830 | struct btrfs_root *extent_root = info->extent_root; |
857 | int ret; | 831 | int ret; |
858 | struct btrfs_extent_item *ei; | 832 | struct btrfs_extent_item *ei; |
859 | struct btrfs_key ins; | ||
860 | u32 refs; | 833 | u32 refs; |
861 | 834 | ||
862 | key.objectid = blocknr; | 835 | key.objectid = blocknr; |
@@ -868,12 +841,6 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
868 | if (!path) | 841 | if (!path) |
869 | return -ENOMEM; | 842 | return -ENOMEM; |
870 | 843 | ||
871 | ret = find_free_extent(trans, root, 0, 0, 0, (u64)-1, 0, &ins, 0, 0, 0); | ||
872 | if (ret) { | ||
873 | btrfs_free_path(path); | ||
874 | return ret; | ||
875 | } | ||
876 | |||
877 | ret = btrfs_search_slot(trans, extent_root, &key, path, -1, 1); | 844 | ret = btrfs_search_slot(trans, extent_root, &key, path, -1, 1); |
878 | if (ret < 0) | 845 | if (ret < 0) |
879 | return ret; | 846 | return ret; |
@@ -1003,35 +970,17 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1003 | struct btrfs_root * root = orig_root->fs_info->extent_root; | 970 | struct btrfs_root * root = orig_root->fs_info->extent_root; |
1004 | struct btrfs_fs_info *info = root->fs_info; | 971 | struct btrfs_fs_info *info = root->fs_info; |
1005 | int total_needed = num_blocks; | 972 | int total_needed = num_blocks; |
1006 | int total_found = 0; | ||
1007 | int fill_prealloc = 0; | ||
1008 | int level; | 973 | int level; |
1009 | struct btrfs_block_group_cache *block_group; | 974 | struct btrfs_block_group_cache *block_group; |
1010 | int full_scan = 0; | 975 | int full_scan = 0; |
1011 | int wrapped = 0; | 976 | int wrapped = 0; |
1012 | u64 limit; | 977 | u64 limit; |
1013 | 978 | ||
979 | WARN_ON(num_blocks < 1); | ||
1014 | ins->flags = 0; | 980 | ins->flags = 0; |
1015 | btrfs_set_key_type(ins, BTRFS_EXTENT_ITEM_KEY); | 981 | btrfs_set_key_type(ins, BTRFS_EXTENT_ITEM_KEY); |
1016 | 982 | ||
1017 | level = btrfs_header_level(btrfs_buffer_header(root->node)); | 983 | level = btrfs_header_level(btrfs_buffer_header(root->node)); |
1018 | if (num_blocks == 0) { | ||
1019 | fill_prealloc = 1; | ||
1020 | num_blocks = 1; | ||
1021 | total_needed = (min(level + 1, BTRFS_MAX_LEVEL)) * 6; | ||
1022 | } | ||
1023 | if (fill_prealloc) { | ||
1024 | u64 first; | ||
1025 | int nr = info->extent_tree_prealloc_nr; | ||
1026 | first = info->extent_tree_prealloc[nr - 1]; | ||
1027 | if (info->extent_tree_prealloc_nr >= total_needed && | ||
1028 | first >= search_start) { | ||
1029 | ins->objectid = info->extent_tree_prealloc[0]; | ||
1030 | ins->offset = 1; | ||
1031 | return 0; | ||
1032 | } | ||
1033 | info->extent_tree_prealloc_nr = 0; | ||
1034 | } | ||
1035 | if (search_end == (u64)-1) | 984 | if (search_end == (u64)-1) |
1036 | search_end = btrfs_super_total_blocks(&info->super_copy); | 985 | search_end = btrfs_super_total_blocks(&info->super_copy); |
1037 | if (hint_block) { | 986 | if (hint_block) { |
@@ -1091,10 +1040,6 @@ check_failed: | |||
1091 | l = btrfs_buffer_leaf(path->nodes[0]); | 1040 | l = btrfs_buffer_leaf(path->nodes[0]); |
1092 | slot = path->slots[0]; | 1041 | slot = path->slots[0]; |
1093 | if (slot >= btrfs_header_nritems(&l->header)) { | 1042 | if (slot >= btrfs_header_nritems(&l->header)) { |
1094 | if (fill_prealloc) { | ||
1095 | info->extent_tree_prealloc_nr = 0; | ||
1096 | total_found = 0; | ||
1097 | } | ||
1098 | if (start_found) | 1043 | if (start_found) |
1099 | limit = last_block + | 1044 | limit = last_block + |
1100 | (block_group->key.offset >> 1); | 1045 | (block_group->key.offset >> 1); |
@@ -1170,67 +1115,21 @@ check_pending: | |||
1170 | } | 1115 | } |
1171 | for (test_block = ins->objectid; | 1116 | for (test_block = ins->objectid; |
1172 | test_block < ins->objectid + num_blocks; test_block++) { | 1117 | test_block < ins->objectid + num_blocks; test_block++) { |
1173 | if (test_radix_bit(&info->pinned_radix, test_block)) { | 1118 | if (test_radix_bit(&info->pinned_radix, test_block) || |
1119 | test_radix_bit(&info->extent_ins_radix, test_block)) { | ||
1174 | search_start = test_block + 1; | 1120 | search_start = test_block + 1; |
1175 | goto new_group; | 1121 | goto new_group; |
1176 | } | 1122 | } |
1177 | } | 1123 | } |
1178 | if (!fill_prealloc && info->extent_tree_insert_nr) { | ||
1179 | u64 last = | ||
1180 | info->extent_tree_insert[info->extent_tree_insert_nr - 1]; | ||
1181 | if (ins->objectid + num_blocks > | ||
1182 | info->extent_tree_insert[0] && | ||
1183 | ins->objectid <= last) { | ||
1184 | search_start = last + 1; | ||
1185 | WARN_ON(!full_scan); | ||
1186 | goto new_group; | ||
1187 | } | ||
1188 | } | ||
1189 | if (!fill_prealloc && info->extent_tree_prealloc_nr) { | ||
1190 | u64 first = | ||
1191 | info->extent_tree_prealloc[info->extent_tree_prealloc_nr - 1]; | ||
1192 | if (ins->objectid + num_blocks > first && | ||
1193 | ins->objectid <= info->extent_tree_prealloc[0]) { | ||
1194 | search_start = info->extent_tree_prealloc[0] + 1; | ||
1195 | goto new_group; | ||
1196 | } | ||
1197 | } | ||
1198 | if (exclude_nr > 0 && (ins->objectid + num_blocks > exclude_start && | 1124 | if (exclude_nr > 0 && (ins->objectid + num_blocks > exclude_start && |
1199 | ins->objectid < exclude_start + exclude_nr)) { | 1125 | ins->objectid < exclude_start + exclude_nr)) { |
1200 | search_start = exclude_start + exclude_nr; | 1126 | search_start = exclude_start + exclude_nr; |
1201 | goto new_group; | 1127 | goto new_group; |
1202 | } | 1128 | } |
1203 | if (fill_prealloc) { | ||
1204 | int nr; | ||
1205 | test_block = ins->objectid; | ||
1206 | if (test_block - info->extent_tree_prealloc[total_needed - 1] >= | ||
1207 | leaf_range(root)) { | ||
1208 | total_found = 0; | ||
1209 | info->extent_tree_prealloc_nr = total_found; | ||
1210 | } | ||
1211 | while(test_block < ins->objectid + ins->offset && | ||
1212 | total_found < total_needed) { | ||
1213 | nr = total_needed - total_found - 1; | ||
1214 | BUG_ON(nr < 0); | ||
1215 | info->extent_tree_prealloc[nr] = test_block; | ||
1216 | total_found++; | ||
1217 | test_block++; | ||
1218 | } | ||
1219 | if (total_found < total_needed) { | ||
1220 | search_start = test_block; | ||
1221 | goto new_group; | ||
1222 | } | ||
1223 | info->extent_tree_prealloc_nr = total_found; | ||
1224 | } | ||
1225 | if (!data) { | 1129 | if (!data) { |
1226 | block_group = btrfs_lookup_block_group(info, ins->objectid); | 1130 | block_group = btrfs_lookup_block_group(info, ins->objectid); |
1227 | if (block_group) { | 1131 | if (block_group) |
1228 | if (fill_prealloc) | 1132 | trans->block_group = block_group; |
1229 | block_group->last_prealloc = | ||
1230 | info->extent_tree_prealloc[total_needed-1]; | ||
1231 | else | ||
1232 | trans->block_group = block_group; | ||
1233 | } | ||
1234 | } | 1133 | } |
1235 | ins->offset = num_blocks; | 1134 | ins->offset = num_blocks; |
1236 | btrfs_free_path(path); | 1135 | btrfs_free_path(path); |
@@ -1278,85 +1177,41 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans, | |||
1278 | int pending_ret; | 1177 | int pending_ret; |
1279 | u64 super_blocks_used; | 1178 | u64 super_blocks_used; |
1280 | u64 search_start = 0; | 1179 | u64 search_start = 0; |
1281 | u64 exclude_start = 0; | ||
1282 | u64 exclude_nr = 0; | ||
1283 | struct btrfs_fs_info *info = root->fs_info; | 1180 | struct btrfs_fs_info *info = root->fs_info; |
1284 | struct btrfs_root *extent_root = info->extent_root; | 1181 | struct btrfs_root *extent_root = info->extent_root; |
1285 | struct btrfs_extent_item extent_item; | 1182 | struct btrfs_extent_item extent_item; |
1286 | struct btrfs_key prealloc_key; | ||
1287 | 1183 | ||
1288 | btrfs_set_extent_refs(&extent_item, 1); | 1184 | btrfs_set_extent_refs(&extent_item, 1); |
1289 | btrfs_set_extent_owner(&extent_item, owner); | 1185 | btrfs_set_extent_owner(&extent_item, owner); |
1290 | 1186 | ||
1291 | if (root == extent_root) { | 1187 | WARN_ON(num_blocks < 1); |
1292 | int nr; | ||
1293 | BUG_ON(info->extent_tree_prealloc_nr == 0); | ||
1294 | BUG_ON(num_blocks != 1); | ||
1295 | ins->offset = 1; | ||
1296 | info->extent_tree_prealloc_nr--; | ||
1297 | nr = info->extent_tree_prealloc_nr; | ||
1298 | ins->objectid = info->extent_tree_prealloc[nr]; | ||
1299 | info->extent_tree_insert[info->extent_tree_insert_nr++] = | ||
1300 | ins->objectid; | ||
1301 | ret = update_block_group(trans, root, | ||
1302 | ins->objectid, ins->offset, 1, 0, 0); | ||
1303 | WARN_ON(info->extent_tree_insert_nr > | ||
1304 | ARRAY_SIZE(info->extent_tree_insert)); | ||
1305 | BUG_ON(ret); | ||
1306 | return 0; | ||
1307 | } | ||
1308 | |||
1309 | /* | ||
1310 | * if we're doing a data allocation, preallocate room in the | ||
1311 | * extent tree first. This way the extent tree blocks end up | ||
1312 | * in the correct block group. | ||
1313 | */ | ||
1314 | if (data) { | ||
1315 | ret = find_free_extent(trans, root, 0, 0, 0, | ||
1316 | search_end, 0, &prealloc_key, 0, 0, 0); | ||
1317 | BUG_ON(ret); | ||
1318 | if (ret) | ||
1319 | return ret; | ||
1320 | exclude_nr = info->extent_tree_prealloc_nr; | ||
1321 | exclude_start = info->extent_tree_prealloc[exclude_nr - 1]; | ||
1322 | } | ||
1323 | |||
1324 | /* do the real allocation */ | ||
1325 | ret = find_free_extent(trans, root, num_blocks, empty_size, | 1188 | ret = find_free_extent(trans, root, num_blocks, empty_size, |
1326 | search_start, search_end, hint_block, ins, | 1189 | search_start, search_end, hint_block, ins, |
1327 | exclude_start, exclude_nr, data); | 1190 | trans->alloc_exclude_start, |
1191 | trans->alloc_exclude_nr, data); | ||
1328 | BUG_ON(ret); | 1192 | BUG_ON(ret); |
1329 | if (ret) | 1193 | if (ret) |
1330 | return ret; | 1194 | return ret; |
1331 | 1195 | ||
1332 | /* | ||
1333 | * if we're doing a metadata allocation, preallocate space in the | ||
1334 | * extent tree second. This way, we don't create a tiny hole | ||
1335 | * in the allocation map between any unused preallocation blocks | ||
1336 | * and the metadata block we're actually allocating. On disk, | ||
1337 | * it'll go: | ||
1338 | * [block we've allocated], [used prealloc 1], [ unused prealloc ] | ||
1339 | * The unused prealloc will get reused the next time around. | ||
1340 | */ | ||
1341 | if (!data) { | ||
1342 | exclude_start = ins->objectid; | ||
1343 | exclude_nr = ins->offset; | ||
1344 | hint_block = exclude_start + exclude_nr; | ||
1345 | ret = find_free_extent(trans, root, 0, 0, search_start, | ||
1346 | search_end, hint_block, | ||
1347 | &prealloc_key, exclude_start, | ||
1348 | exclude_nr, 0); | ||
1349 | BUG_ON(ret); | ||
1350 | if (ret) | ||
1351 | return ret; | ||
1352 | } | ||
1353 | |||
1354 | super_blocks_used = btrfs_super_blocks_used(&info->super_copy); | 1196 | super_blocks_used = btrfs_super_blocks_used(&info->super_copy); |
1355 | btrfs_set_super_blocks_used(&info->super_copy, super_blocks_used + | 1197 | btrfs_set_super_blocks_used(&info->super_copy, super_blocks_used + |
1356 | num_blocks); | 1198 | num_blocks); |
1199 | |||
1200 | if (root == extent_root) { | ||
1201 | BUG_ON(num_blocks != 1); | ||
1202 | set_radix_bit(&root->fs_info->extent_ins_radix, ins->objectid); | ||
1203 | goto update_block; | ||
1204 | } | ||
1205 | |||
1206 | WARN_ON(trans->alloc_exclude_nr); | ||
1207 | trans->alloc_exclude_start = ins->objectid; | ||
1208 | trans->alloc_exclude_nr = ins->offset; | ||
1357 | ret = btrfs_insert_item(trans, extent_root, ins, &extent_item, | 1209 | ret = btrfs_insert_item(trans, extent_root, ins, &extent_item, |
1358 | sizeof(extent_item)); | 1210 | sizeof(extent_item)); |
1359 | 1211 | ||
1212 | trans->alloc_exclude_start = 0; | ||
1213 | trans->alloc_exclude_nr = 0; | ||
1214 | |||
1360 | BUG_ON(ret); | 1215 | BUG_ON(ret); |
1361 | finish_current_insert(trans, extent_root); | 1216 | finish_current_insert(trans, extent_root); |
1362 | pending_ret = del_pending_extents(trans, extent_root); | 1217 | pending_ret = del_pending_extents(trans, extent_root); |
@@ -1366,6 +1221,8 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans, | |||
1366 | if (pending_ret) { | 1221 | if (pending_ret) { |
1367 | return pending_ret; | 1222 | return pending_ret; |
1368 | } | 1223 | } |
1224 | |||
1225 | update_block: | ||
1369 | ret = update_block_group(trans, root, ins->objectid, ins->offset, 1, 0, | 1226 | ret = update_block_group(trans, root, ins->objectid, ins->offset, 1, 0, |
1370 | data); | 1227 | data); |
1371 | BUG_ON(ret); | 1228 | BUG_ON(ret); |
@@ -1750,7 +1607,6 @@ int btrfs_read_block_groups(struct btrfs_root *root) | |||
1750 | memcpy(&cache->key, &found_key, sizeof(found_key)); | 1607 | memcpy(&cache->key, &found_key, sizeof(found_key)); |
1751 | cache->last_alloc = cache->key.objectid; | 1608 | cache->last_alloc = cache->key.objectid; |
1752 | cache->first_free = cache->key.objectid; | 1609 | cache->first_free = cache->key.objectid; |
1753 | cache->last_prealloc = cache->key.objectid; | ||
1754 | cache->pinned = 0; | 1610 | cache->pinned = 0; |
1755 | cache->cached = 0; | 1611 | cache->cached = 0; |
1756 | 1612 | ||
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 88b0752550b6..e64ecec3f52e 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -109,6 +109,8 @@ struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root, | |||
109 | h->blocks_reserved = num_blocks; | 109 | h->blocks_reserved = num_blocks; |
110 | h->blocks_used = 0; | 110 | h->blocks_used = 0; |
111 | h->block_group = NULL; | 111 | h->block_group = NULL; |
112 | h->alloc_exclude_nr = 0; | ||
113 | h->alloc_exclude_start = 0; | ||
112 | root->fs_info->running_transaction->use_count++; | 114 | root->fs_info->running_transaction->use_count++; |
113 | mutex_unlock(&root->fs_info->trans_mutex); | 115 | mutex_unlock(&root->fs_info->trans_mutex); |
114 | return h; | 116 | return h; |
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h index 8b2714e65562..65a395eeca91 100644 --- a/fs/btrfs/transaction.h +++ b/fs/btrfs/transaction.h | |||
@@ -39,6 +39,8 @@ struct btrfs_trans_handle { | |||
39 | unsigned long blocks_used; | 39 | unsigned long blocks_used; |
40 | struct btrfs_transaction *transaction; | 40 | struct btrfs_transaction *transaction; |
41 | struct btrfs_block_group_cache *block_group; | 41 | struct btrfs_block_group_cache *block_group; |
42 | u64 alloc_exclude_start; | ||
43 | u64 alloc_exclude_nr; | ||
42 | }; | 44 | }; |
43 | 45 | ||
44 | 46 | ||