diff options
author | Chris Mason <chris.mason@oracle.com> | 2008-06-25 16:01:30 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:04:03 -0400 |
commit | 925baeddc5b0764a53f2214a1253251bab0e0324 (patch) | |
tree | 0e069bf9cc1c4ecd17c812fd1fb81bf807909ee6 /fs/btrfs/extent-tree.c | |
parent | 1cc127b5d1b71453091859301de4a7dd6ee96fa8 (diff) |
Btrfs: Start btree concurrency work.
The allocation trees and the chunk trees are serialized via their own
dedicated mutexes. This means allocation location is still not very
fine grained.
The main FS btree is protected by locks on each block in the btree. Locks
are taken top / down, and as processing finishes on a given level of the
tree, the lock is released after locking the lower level.
The end result of a search is now a path where only the lowest level
is locked. Releasing or freeing the path drops any locks held.
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 | 252 |
1 files changed, 164 insertions, 88 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 41a63462d3eb..7e40c516fe62 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include "print-tree.h" | 25 | #include "print-tree.h" |
26 | #include "transaction.h" | 26 | #include "transaction.h" |
27 | #include "volumes.h" | 27 | #include "volumes.h" |
28 | #include "locking.h" | ||
28 | 29 | ||
29 | #define BLOCK_GROUP_DATA EXTENT_WRITEBACK | 30 | #define BLOCK_GROUP_DATA EXTENT_WRITEBACK |
30 | #define BLOCK_GROUP_METADATA EXTENT_UPTODATE | 31 | #define BLOCK_GROUP_METADATA EXTENT_UPTODATE |
@@ -36,7 +37,28 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct | |||
36 | btrfs_root *extent_root); | 37 | btrfs_root *extent_root); |
37 | static int del_pending_extents(struct btrfs_trans_handle *trans, struct | 38 | static int del_pending_extents(struct btrfs_trans_handle *trans, struct |
38 | btrfs_root *extent_root); | 39 | btrfs_root *extent_root); |
40 | static struct btrfs_block_group_cache * | ||
41 | __btrfs_find_block_group(struct btrfs_root *root, | ||
42 | struct btrfs_block_group_cache *hint, | ||
43 | u64 search_start, int data, int owner); | ||
39 | 44 | ||
45 | void maybe_lock_mutex(struct btrfs_root *root) | ||
46 | { | ||
47 | if (root != root->fs_info->extent_root && | ||
48 | root != root->fs_info->chunk_root && | ||
49 | root != root->fs_info->dev_root) { | ||
50 | mutex_lock(&root->fs_info->alloc_mutex); | ||
51 | } | ||
52 | } | ||
53 | |||
54 | void maybe_unlock_mutex(struct btrfs_root *root) | ||
55 | { | ||
56 | if (root != root->fs_info->extent_root && | ||
57 | root != root->fs_info->chunk_root && | ||
58 | root != root->fs_info->dev_root) { | ||
59 | mutex_unlock(&root->fs_info->alloc_mutex); | ||
60 | } | ||
61 | } | ||
40 | 62 | ||
41 | static int cache_block_group(struct btrfs_root *root, | 63 | static int cache_block_group(struct btrfs_root *root, |
42 | struct btrfs_block_group_cache *block_group) | 64 | struct btrfs_block_group_cache *block_group) |
@@ -66,6 +88,7 @@ static int cache_block_group(struct btrfs_root *root, | |||
66 | return -ENOMEM; | 88 | return -ENOMEM; |
67 | 89 | ||
68 | path->reada = 2; | 90 | path->reada = 2; |
91 | path->skip_locking = 1; | ||
69 | first_free = block_group->key.objectid; | 92 | first_free = block_group->key.objectid; |
70 | key.objectid = block_group->key.objectid; | 93 | key.objectid = block_group->key.objectid; |
71 | key.offset = 0; | 94 | key.offset = 0; |
@@ -290,7 +313,7 @@ no_cache: | |||
290 | cache = btrfs_lookup_first_block_group(root->fs_info, last); | 313 | cache = btrfs_lookup_first_block_group(root->fs_info, last); |
291 | } | 314 | } |
292 | cache_miss = 0; | 315 | cache_miss = 0; |
293 | cache = btrfs_find_block_group(root, cache, last, data, 0); | 316 | cache = __btrfs_find_block_group(root, cache, last, data, 0); |
294 | if (!cache) | 317 | if (!cache) |
295 | goto no_cache; | 318 | goto no_cache; |
296 | *cache_ret = cache; | 319 | *cache_ret = cache; |
@@ -318,10 +341,10 @@ static int block_group_state_bits(u64 flags) | |||
318 | return bits; | 341 | return bits; |
319 | } | 342 | } |
320 | 343 | ||
321 | struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root, | 344 | static struct btrfs_block_group_cache * |
322 | struct btrfs_block_group_cache | 345 | __btrfs_find_block_group(struct btrfs_root *root, |
323 | *hint, u64 search_start, | 346 | struct btrfs_block_group_cache *hint, |
324 | int data, int owner) | 347 | u64 search_start, int data, int owner) |
325 | { | 348 | { |
326 | struct btrfs_block_group_cache *cache; | 349 | struct btrfs_block_group_cache *cache; |
327 | struct extent_io_tree *block_group_cache; | 350 | struct extent_io_tree *block_group_cache; |
@@ -411,6 +434,18 @@ found: | |||
411 | return found_group; | 434 | return found_group; |
412 | } | 435 | } |
413 | 436 | ||
437 | struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root, | ||
438 | struct btrfs_block_group_cache | ||
439 | *hint, u64 search_start, | ||
440 | int data, int owner) | ||
441 | { | ||
442 | |||
443 | struct btrfs_block_group_cache *ret; | ||
444 | mutex_lock(&root->fs_info->alloc_mutex); | ||
445 | ret = __btrfs_find_block_group(root, hint, search_start, data, owner); | ||
446 | mutex_unlock(&root->fs_info->alloc_mutex); | ||
447 | return ret; | ||
448 | } | ||
414 | static u64 hash_extent_ref(u64 root_objectid, u64 ref_generation, | 449 | static u64 hash_extent_ref(u64 root_objectid, u64 ref_generation, |
415 | u64 owner, u64 owner_offset) | 450 | u64 owner, u64 owner_offset) |
416 | { | 451 | { |
@@ -646,7 +681,7 @@ out: | |||
646 | return ret; | 681 | return ret; |
647 | } | 682 | } |
648 | 683 | ||
649 | int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, | 684 | static int __btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, |
650 | struct btrfs_root *root, | 685 | struct btrfs_root *root, |
651 | u64 bytenr, u64 num_bytes, | 686 | u64 bytenr, u64 num_bytes, |
652 | u64 root_objectid, u64 ref_generation, | 687 | u64 root_objectid, u64 ref_generation, |
@@ -696,6 +731,22 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, | |||
696 | return 0; | 731 | return 0; |
697 | } | 732 | } |
698 | 733 | ||
734 | int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, | ||
735 | struct btrfs_root *root, | ||
736 | u64 bytenr, u64 num_bytes, | ||
737 | u64 root_objectid, u64 ref_generation, | ||
738 | u64 owner, u64 owner_offset) | ||
739 | { | ||
740 | int ret; | ||
741 | |||
742 | mutex_lock(&root->fs_info->alloc_mutex); | ||
743 | ret = __btrfs_inc_extent_ref(trans, root, bytenr, num_bytes, | ||
744 | root_objectid, ref_generation, | ||
745 | owner, owner_offset); | ||
746 | mutex_unlock(&root->fs_info->alloc_mutex); | ||
747 | return ret; | ||
748 | } | ||
749 | |||
699 | int btrfs_extent_post_op(struct btrfs_trans_handle *trans, | 750 | int btrfs_extent_post_op(struct btrfs_trans_handle *trans, |
700 | struct btrfs_root *root) | 751 | struct btrfs_root *root) |
701 | { | 752 | { |
@@ -760,6 +811,10 @@ u32 btrfs_count_snapshots_in_path(struct btrfs_root *root, | |||
760 | struct btrfs_extent_ref *ref_item; | 811 | struct btrfs_extent_ref *ref_item; |
761 | int level = -1; | 812 | int level = -1; |
762 | 813 | ||
814 | /* FIXME, needs locking */ | ||
815 | BUG(); | ||
816 | |||
817 | mutex_lock(&root->fs_info->alloc_mutex); | ||
763 | path = btrfs_alloc_path(); | 818 | path = btrfs_alloc_path(); |
764 | again: | 819 | again: |
765 | if (level == -1) | 820 | if (level == -1) |
@@ -854,33 +909,9 @@ again: | |||
854 | 909 | ||
855 | out: | 910 | out: |
856 | btrfs_free_path(path); | 911 | btrfs_free_path(path); |
912 | mutex_unlock(&root->fs_info->alloc_mutex); | ||
857 | return total_count; | 913 | return total_count; |
858 | } | 914 | } |
859 | int btrfs_inc_root_ref(struct btrfs_trans_handle *trans, | ||
860 | struct btrfs_root *root, u64 owner_objectid) | ||
861 | { | ||
862 | u64 generation; | ||
863 | u64 key_objectid; | ||
864 | u64 level; | ||
865 | u32 nritems; | ||
866 | struct btrfs_disk_key disk_key; | ||
867 | |||
868 | level = btrfs_header_level(root->node); | ||
869 | generation = trans->transid; | ||
870 | nritems = btrfs_header_nritems(root->node); | ||
871 | if (nritems > 0) { | ||
872 | if (level == 0) | ||
873 | btrfs_item_key(root->node, &disk_key, 0); | ||
874 | else | ||
875 | btrfs_node_key(root->node, &disk_key, 0); | ||
876 | key_objectid = btrfs_disk_key_objectid(&disk_key); | ||
877 | } else { | ||
878 | key_objectid = 0; | ||
879 | } | ||
880 | return btrfs_inc_extent_ref(trans, root, root->node->start, | ||
881 | root->node->len, owner_objectid, | ||
882 | generation, level, key_objectid); | ||
883 | } | ||
884 | 915 | ||
885 | int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 916 | int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
886 | struct extent_buffer *buf) | 917 | struct extent_buffer *buf) |
@@ -897,6 +928,7 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
897 | if (!root->ref_cows) | 928 | if (!root->ref_cows) |
898 | return 0; | 929 | return 0; |
899 | 930 | ||
931 | mutex_lock(&root->fs_info->alloc_mutex); | ||
900 | level = btrfs_header_level(buf); | 932 | level = btrfs_header_level(buf); |
901 | nritems = btrfs_header_nritems(buf); | 933 | nritems = btrfs_header_nritems(buf); |
902 | for (i = 0; i < nritems; i++) { | 934 | for (i = 0; i < nritems; i++) { |
@@ -913,7 +945,7 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
913 | disk_bytenr = btrfs_file_extent_disk_bytenr(buf, fi); | 945 | disk_bytenr = btrfs_file_extent_disk_bytenr(buf, fi); |
914 | if (disk_bytenr == 0) | 946 | if (disk_bytenr == 0) |
915 | continue; | 947 | continue; |
916 | ret = btrfs_inc_extent_ref(trans, root, disk_bytenr, | 948 | ret = __btrfs_inc_extent_ref(trans, root, disk_bytenr, |
917 | btrfs_file_extent_disk_num_bytes(buf, fi), | 949 | btrfs_file_extent_disk_num_bytes(buf, fi), |
918 | root->root_key.objectid, trans->transid, | 950 | root->root_key.objectid, trans->transid, |
919 | key.objectid, key.offset); | 951 | key.objectid, key.offset); |
@@ -924,7 +956,7 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
924 | } else { | 956 | } else { |
925 | bytenr = btrfs_node_blockptr(buf, i); | 957 | bytenr = btrfs_node_blockptr(buf, i); |
926 | btrfs_node_key_to_cpu(buf, &key, i); | 958 | btrfs_node_key_to_cpu(buf, &key, i); |
927 | ret = btrfs_inc_extent_ref(trans, root, bytenr, | 959 | ret = __btrfs_inc_extent_ref(trans, root, bytenr, |
928 | btrfs_level_size(root, level - 1), | 960 | btrfs_level_size(root, level - 1), |
929 | root->root_key.objectid, | 961 | root->root_key.objectid, |
930 | trans->transid, | 962 | trans->transid, |
@@ -935,6 +967,7 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
935 | } | 967 | } |
936 | } | 968 | } |
937 | } | 969 | } |
970 | mutex_unlock(&root->fs_info->alloc_mutex); | ||
938 | return 0; | 971 | return 0; |
939 | fail: | 972 | fail: |
940 | WARN_ON(1); | 973 | WARN_ON(1); |
@@ -965,6 +998,7 @@ fail: | |||
965 | } | 998 | } |
966 | } | 999 | } |
967 | #endif | 1000 | #endif |
1001 | mutex_unlock(&root->fs_info->alloc_mutex); | ||
968 | return ret; | 1002 | return ret; |
969 | } | 1003 | } |
970 | 1004 | ||
@@ -1019,6 +1053,7 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans, | |||
1019 | if (!path) | 1053 | if (!path) |
1020 | return -ENOMEM; | 1054 | return -ENOMEM; |
1021 | 1055 | ||
1056 | mutex_lock(&root->fs_info->alloc_mutex); | ||
1022 | while(1) { | 1057 | while(1) { |
1023 | ret = find_first_extent_bit(block_group_cache, last, | 1058 | ret = find_first_extent_bit(block_group_cache, last, |
1024 | &start, &end, BLOCK_GROUP_DIRTY); | 1059 | &start, &end, BLOCK_GROUP_DIRTY); |
@@ -1045,6 +1080,7 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans, | |||
1045 | BLOCK_GROUP_DIRTY, GFP_NOFS); | 1080 | BLOCK_GROUP_DIRTY, GFP_NOFS); |
1046 | } | 1081 | } |
1047 | btrfs_free_path(path); | 1082 | btrfs_free_path(path); |
1083 | mutex_unlock(&root->fs_info->alloc_mutex); | ||
1048 | return werr; | 1084 | return werr; |
1049 | } | 1085 | } |
1050 | 1086 | ||
@@ -1162,26 +1198,28 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans, | |||
1162 | space_info->force_alloc = 0; | 1198 | space_info->force_alloc = 0; |
1163 | } | 1199 | } |
1164 | if (space_info->full) | 1200 | if (space_info->full) |
1165 | return 0; | 1201 | goto out; |
1166 | 1202 | ||
1167 | thresh = div_factor(space_info->total_bytes, 6); | 1203 | thresh = div_factor(space_info->total_bytes, 6); |
1168 | if (!force && | 1204 | if (!force && |
1169 | (space_info->bytes_used + space_info->bytes_pinned + alloc_bytes) < | 1205 | (space_info->bytes_used + space_info->bytes_pinned + alloc_bytes) < |
1170 | thresh) | 1206 | thresh) |
1171 | return 0; | 1207 | goto out; |
1172 | 1208 | ||
1209 | mutex_lock(&extent_root->fs_info->chunk_mutex); | ||
1173 | ret = btrfs_alloc_chunk(trans, extent_root, &start, &num_bytes, flags); | 1210 | ret = btrfs_alloc_chunk(trans, extent_root, &start, &num_bytes, flags); |
1174 | if (ret == -ENOSPC) { | 1211 | if (ret == -ENOSPC) { |
1175 | printk("space info full %Lu\n", flags); | 1212 | printk("space info full %Lu\n", flags); |
1176 | space_info->full = 1; | 1213 | space_info->full = 1; |
1177 | return 0; | 1214 | goto out; |
1178 | } | 1215 | } |
1179 | BUG_ON(ret); | 1216 | BUG_ON(ret); |
1180 | 1217 | ||
1181 | ret = btrfs_make_block_group(trans, extent_root, 0, flags, | 1218 | ret = btrfs_make_block_group(trans, extent_root, 0, flags, |
1182 | BTRFS_FIRST_CHUNK_TREE_OBJECTID, start, num_bytes); | 1219 | BTRFS_FIRST_CHUNK_TREE_OBJECTID, start, num_bytes); |
1183 | BUG_ON(ret); | 1220 | BUG_ON(ret); |
1184 | 1221 | mutex_unlock(&extent_root->fs_info->chunk_mutex); | |
1222 | out: | ||
1185 | return 0; | 1223 | return 0; |
1186 | } | 1224 | } |
1187 | 1225 | ||
@@ -1318,6 +1356,7 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, | |||
1318 | struct extent_io_tree *free_space_cache; | 1356 | struct extent_io_tree *free_space_cache; |
1319 | free_space_cache = &root->fs_info->free_space_cache; | 1357 | free_space_cache = &root->fs_info->free_space_cache; |
1320 | 1358 | ||
1359 | mutex_lock(&root->fs_info->alloc_mutex); | ||
1321 | while(1) { | 1360 | while(1) { |
1322 | ret = find_first_extent_bit(unpin, 0, &start, &end, | 1361 | ret = find_first_extent_bit(unpin, 0, &start, &end, |
1323 | EXTENT_DIRTY); | 1362 | EXTENT_DIRTY); |
@@ -1327,6 +1366,7 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, | |||
1327 | clear_extent_dirty(unpin, start, end, GFP_NOFS); | 1366 | clear_extent_dirty(unpin, start, end, GFP_NOFS); |
1328 | set_extent_dirty(free_space_cache, start, end, GFP_NOFS); | 1367 | set_extent_dirty(free_space_cache, start, end, GFP_NOFS); |
1329 | } | 1368 | } |
1369 | mutex_unlock(&root->fs_info->alloc_mutex); | ||
1330 | return 0; | 1370 | return 0; |
1331 | } | 1371 | } |
1332 | 1372 | ||
@@ -1363,18 +1403,24 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, | |||
1363 | GFP_NOFS); | 1403 | GFP_NOFS); |
1364 | eb = read_tree_block(extent_root, ins.objectid, ins.offset, | 1404 | eb = read_tree_block(extent_root, ins.objectid, ins.offset, |
1365 | trans->transid); | 1405 | trans->transid); |
1406 | btrfs_tree_lock(eb); | ||
1366 | level = btrfs_header_level(eb); | 1407 | level = btrfs_header_level(eb); |
1367 | if (level == 0) { | 1408 | if (level == 0) { |
1368 | btrfs_item_key(eb, &first, 0); | 1409 | btrfs_item_key(eb, &first, 0); |
1369 | } else { | 1410 | } else { |
1370 | btrfs_node_key(eb, &first, 0); | 1411 | btrfs_node_key(eb, &first, 0); |
1371 | } | 1412 | } |
1413 | btrfs_tree_unlock(eb); | ||
1414 | free_extent_buffer(eb); | ||
1415 | /* | ||
1416 | * the first key is just a hint, so the race we've created | ||
1417 | * against reading it is fine | ||
1418 | */ | ||
1372 | err = btrfs_insert_extent_backref(trans, extent_root, path, | 1419 | err = btrfs_insert_extent_backref(trans, extent_root, path, |
1373 | start, extent_root->root_key.objectid, | 1420 | start, extent_root->root_key.objectid, |
1374 | 0, level, | 1421 | 0, level, |
1375 | btrfs_disk_key_objectid(&first)); | 1422 | btrfs_disk_key_objectid(&first)); |
1376 | BUG_ON(err); | 1423 | BUG_ON(err); |
1377 | free_extent_buffer(eb); | ||
1378 | } | 1424 | } |
1379 | btrfs_free_path(path); | 1425 | btrfs_free_path(path); |
1380 | return 0; | 1426 | return 0; |
@@ -1384,12 +1430,14 @@ static int pin_down_bytes(struct btrfs_root *root, u64 bytenr, u32 num_bytes, | |||
1384 | int pending) | 1430 | int pending) |
1385 | { | 1431 | { |
1386 | int err = 0; | 1432 | int err = 0; |
1387 | struct extent_buffer *buf; | ||
1388 | 1433 | ||
1389 | if (!pending) { | 1434 | if (!pending) { |
1435 | #if 0 | ||
1436 | struct extent_buffer *buf; | ||
1390 | buf = btrfs_find_tree_block(root, bytenr, num_bytes); | 1437 | buf = btrfs_find_tree_block(root, bytenr, num_bytes); |
1391 | if (buf) { | 1438 | if (buf) { |
1392 | if (btrfs_buffer_uptodate(buf, 0)) { | 1439 | if (!btrfs_try_tree_lock(buf) && |
1440 | btrfs_buffer_uptodate(buf, 0)) { | ||
1393 | u64 transid = | 1441 | u64 transid = |
1394 | root->fs_info->running_transaction->transid; | 1442 | root->fs_info->running_transaction->transid; |
1395 | u64 header_transid = | 1443 | u64 header_transid = |
@@ -1398,12 +1446,15 @@ static int pin_down_bytes(struct btrfs_root *root, u64 bytenr, u32 num_bytes, | |||
1398 | !btrfs_header_flag(buf, | 1446 | !btrfs_header_flag(buf, |
1399 | BTRFS_HEADER_FLAG_WRITTEN)) { | 1447 | BTRFS_HEADER_FLAG_WRITTEN)) { |
1400 | clean_tree_block(NULL, root, buf); | 1448 | clean_tree_block(NULL, root, buf); |
1449 | btrfs_tree_unlock(buf); | ||
1401 | free_extent_buffer(buf); | 1450 | free_extent_buffer(buf); |
1402 | return 1; | 1451 | return 1; |
1403 | } | 1452 | } |
1453 | btrfs_tree_unlock(buf); | ||
1404 | } | 1454 | } |
1405 | free_extent_buffer(buf); | 1455 | free_extent_buffer(buf); |
1406 | } | 1456 | } |
1457 | #endif | ||
1407 | update_pinned_extents(root, bytenr, num_bytes, 1); | 1458 | update_pinned_extents(root, bytenr, num_bytes, 1); |
1408 | } else { | 1459 | } else { |
1409 | set_extent_bits(&root->fs_info->pending_del, | 1460 | set_extent_bits(&root->fs_info->pending_del, |
@@ -1586,10 +1637,11 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct | |||
1586 | /* | 1637 | /* |
1587 | * remove an extent from the root, returns 0 on success | 1638 | * remove an extent from the root, returns 0 on success |
1588 | */ | 1639 | */ |
1589 | int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | 1640 | static int __btrfs_free_extent(struct btrfs_trans_handle *trans, |
1590 | *root, u64 bytenr, u64 num_bytes, | 1641 | struct btrfs_root *root, u64 bytenr, |
1591 | u64 root_objectid, u64 ref_generation, | 1642 | u64 num_bytes, u64 root_objectid, |
1592 | u64 owner_objectid, u64 owner_offset, int pin) | 1643 | u64 ref_generation, u64 owner_objectid, |
1644 | u64 owner_offset, int pin) | ||
1593 | { | 1645 | { |
1594 | struct btrfs_root *extent_root = root->fs_info->extent_root; | 1646 | struct btrfs_root *extent_root = root->fs_info->extent_root; |
1595 | int pending_ret; | 1647 | int pending_ret; |
@@ -1610,6 +1662,22 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1610 | return ret ? ret : pending_ret; | 1662 | return ret ? ret : pending_ret; |
1611 | } | 1663 | } |
1612 | 1664 | ||
1665 | int btrfs_free_extent(struct btrfs_trans_handle *trans, | ||
1666 | struct btrfs_root *root, u64 bytenr, | ||
1667 | u64 num_bytes, u64 root_objectid, | ||
1668 | u64 ref_generation, u64 owner_objectid, | ||
1669 | u64 owner_offset, int pin) | ||
1670 | { | ||
1671 | int ret; | ||
1672 | |||
1673 | maybe_lock_mutex(root); | ||
1674 | ret = __btrfs_free_extent(trans, root, bytenr, num_bytes, | ||
1675 | root_objectid, ref_generation, | ||
1676 | owner_objectid, owner_offset, pin); | ||
1677 | maybe_unlock_mutex(root); | ||
1678 | return ret; | ||
1679 | } | ||
1680 | |||
1613 | static u64 stripe_align(struct btrfs_root *root, u64 val) | 1681 | static u64 stripe_align(struct btrfs_root *root, u64 val) |
1614 | { | 1682 | { |
1615 | u64 mask = ((u64)root->stripesize - 1); | 1683 | u64 mask = ((u64)root->stripesize - 1); |
@@ -1679,12 +1747,12 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans, | |||
1679 | block_group = btrfs_lookup_first_block_group(info, hint_byte); | 1747 | block_group = btrfs_lookup_first_block_group(info, hint_byte); |
1680 | if (!block_group) | 1748 | if (!block_group) |
1681 | hint_byte = search_start; | 1749 | hint_byte = search_start; |
1682 | block_group = btrfs_find_block_group(root, block_group, | 1750 | block_group = __btrfs_find_block_group(root, block_group, |
1683 | hint_byte, data, 1); | 1751 | hint_byte, data, 1); |
1684 | if (last_ptr && *last_ptr == 0 && block_group) | 1752 | if (last_ptr && *last_ptr == 0 && block_group) |
1685 | hint_byte = block_group->key.objectid; | 1753 | hint_byte = block_group->key.objectid; |
1686 | } else { | 1754 | } else { |
1687 | block_group = btrfs_find_block_group(root, | 1755 | block_group = __btrfs_find_block_group(root, |
1688 | trans->block_group, | 1756 | trans->block_group, |
1689 | search_start, data, 1); | 1757 | search_start, data, 1); |
1690 | } | 1758 | } |
@@ -1806,7 +1874,7 @@ enospc: | |||
1806 | } | 1874 | } |
1807 | block_group = btrfs_lookup_first_block_group(info, search_start); | 1875 | block_group = btrfs_lookup_first_block_group(info, search_start); |
1808 | cond_resched(); | 1876 | cond_resched(); |
1809 | block_group = btrfs_find_block_group(root, block_group, | 1877 | block_group = __btrfs_find_block_group(root, block_group, |
1810 | search_start, data, 0); | 1878 | search_start, data, 0); |
1811 | goto check_failed; | 1879 | goto check_failed; |
1812 | 1880 | ||
@@ -1843,6 +1911,8 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans, | |||
1843 | struct btrfs_path *path; | 1911 | struct btrfs_path *path; |
1844 | struct btrfs_key keys[2]; | 1912 | struct btrfs_key keys[2]; |
1845 | 1913 | ||
1914 | maybe_lock_mutex(root); | ||
1915 | |||
1846 | if (data) { | 1916 | if (data) { |
1847 | alloc_profile = info->avail_data_alloc_bits & | 1917 | alloc_profile = info->avail_data_alloc_bits & |
1848 | info->data_alloc_profile; | 1918 | info->data_alloc_profile; |
@@ -1892,9 +1962,10 @@ again: | |||
1892 | if (ret) { | 1962 | if (ret) { |
1893 | printk("allocation failed flags %Lu\n", data); | 1963 | printk("allocation failed flags %Lu\n", data); |
1894 | } | 1964 | } |
1895 | BUG_ON(ret); | 1965 | if (ret) { |
1896 | if (ret) | 1966 | BUG(); |
1897 | return ret; | 1967 | goto out; |
1968 | } | ||
1898 | 1969 | ||
1899 | /* block accounting for super block */ | 1970 | /* block accounting for super block */ |
1900 | super_used = btrfs_super_bytes_used(&info->super_copy); | 1971 | super_used = btrfs_super_bytes_used(&info->super_copy); |
@@ -1953,11 +2024,11 @@ again: | |||
1953 | finish_current_insert(trans, extent_root); | 2024 | finish_current_insert(trans, extent_root); |
1954 | pending_ret = del_pending_extents(trans, extent_root); | 2025 | pending_ret = del_pending_extents(trans, extent_root); |
1955 | 2026 | ||
1956 | if (ret) { | 2027 | if (ret) |
1957 | return ret; | 2028 | goto out; |
1958 | } | ||
1959 | if (pending_ret) { | 2029 | if (pending_ret) { |
1960 | return pending_ret; | 2030 | ret = pending_ret; |
2031 | goto out; | ||
1961 | } | 2032 | } |
1962 | 2033 | ||
1963 | update_block: | 2034 | update_block: |
@@ -1967,9 +2038,10 @@ update_block: | |||
1967 | ins->objectid, ins->offset); | 2038 | ins->objectid, ins->offset); |
1968 | BUG(); | 2039 | BUG(); |
1969 | } | 2040 | } |
1970 | return 0; | 2041 | out: |
2042 | maybe_unlock_mutex(root); | ||
2043 | return ret; | ||
1971 | } | 2044 | } |
1972 | |||
1973 | /* | 2045 | /* |
1974 | * helper function to allocate a block for a given tree | 2046 | * helper function to allocate a block for a given tree |
1975 | * returns the tree buffer or NULL. | 2047 | * returns the tree buffer or NULL. |
@@ -1977,28 +2049,6 @@ update_block: | |||
1977 | struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, | 2049 | struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, |
1978 | struct btrfs_root *root, | 2050 | struct btrfs_root *root, |
1979 | u32 blocksize, | 2051 | u32 blocksize, |
1980 | u64 root_objectid, u64 hint, | ||
1981 | u64 empty_size) | ||
1982 | { | ||
1983 | u64 ref_generation; | ||
1984 | |||
1985 | if (root->ref_cows) | ||
1986 | ref_generation = trans->transid; | ||
1987 | else | ||
1988 | ref_generation = 0; | ||
1989 | |||
1990 | |||
1991 | return __btrfs_alloc_free_block(trans, root, blocksize, root_objectid, | ||
1992 | ref_generation, 0, 0, hint, empty_size); | ||
1993 | } | ||
1994 | |||
1995 | /* | ||
1996 | * helper function to allocate a block for a given tree | ||
1997 | * returns the tree buffer or NULL. | ||
1998 | */ | ||
1999 | struct extent_buffer *__btrfs_alloc_free_block(struct btrfs_trans_handle *trans, | ||
2000 | struct btrfs_root *root, | ||
2001 | u32 blocksize, | ||
2002 | u64 root_objectid, | 2052 | u64 root_objectid, |
2003 | u64 ref_generation, | 2053 | u64 ref_generation, |
2004 | u64 first_objectid, | 2054 | u64 first_objectid, |
@@ -2026,6 +2076,7 @@ struct extent_buffer *__btrfs_alloc_free_block(struct btrfs_trans_handle *trans, | |||
2026 | return ERR_PTR(-ENOMEM); | 2076 | return ERR_PTR(-ENOMEM); |
2027 | } | 2077 | } |
2028 | btrfs_set_header_generation(buf, trans->transid); | 2078 | btrfs_set_header_generation(buf, trans->transid); |
2079 | btrfs_tree_lock(buf); | ||
2029 | clean_tree_block(trans, root, buf); | 2080 | clean_tree_block(trans, root, buf); |
2030 | btrfs_set_buffer_uptodate(buf); | 2081 | btrfs_set_buffer_uptodate(buf); |
2031 | 2082 | ||
@@ -2076,7 +2127,7 @@ static int noinline drop_leaf_ref(struct btrfs_trans_handle *trans, | |||
2076 | disk_bytenr = btrfs_file_extent_disk_bytenr(leaf, fi); | 2127 | disk_bytenr = btrfs_file_extent_disk_bytenr(leaf, fi); |
2077 | if (disk_bytenr == 0) | 2128 | if (disk_bytenr == 0) |
2078 | continue; | 2129 | continue; |
2079 | ret = btrfs_free_extent(trans, root, disk_bytenr, | 2130 | ret = __btrfs_free_extent(trans, root, disk_bytenr, |
2080 | btrfs_file_extent_disk_num_bytes(leaf, fi), | 2131 | btrfs_file_extent_disk_num_bytes(leaf, fi), |
2081 | leaf_owner, leaf_generation, | 2132 | leaf_owner, leaf_generation, |
2082 | key.objectid, key.offset, 0); | 2133 | key.objectid, key.offset, 0); |
@@ -2151,6 +2202,8 @@ static int noinline walk_down_tree(struct btrfs_trans_handle *trans, | |||
2151 | int ret; | 2202 | int ret; |
2152 | u32 refs; | 2203 | u32 refs; |
2153 | 2204 | ||
2205 | mutex_lock(&root->fs_info->alloc_mutex); | ||
2206 | |||
2154 | WARN_ON(*level < 0); | 2207 | WARN_ON(*level < 0); |
2155 | WARN_ON(*level >= BTRFS_MAX_LEVEL); | 2208 | WARN_ON(*level >= BTRFS_MAX_LEVEL); |
2156 | ret = lookup_extent_ref(trans, root, | 2209 | ret = lookup_extent_ref(trans, root, |
@@ -2182,6 +2235,7 @@ static int noinline walk_down_tree(struct btrfs_trans_handle *trans, | |||
2182 | bytenr = btrfs_node_blockptr(cur, path->slots[*level]); | 2235 | bytenr = btrfs_node_blockptr(cur, path->slots[*level]); |
2183 | ptr_gen = btrfs_node_ptr_generation(cur, path->slots[*level]); | 2236 | ptr_gen = btrfs_node_ptr_generation(cur, path->slots[*level]); |
2184 | blocksize = btrfs_level_size(root, *level - 1); | 2237 | blocksize = btrfs_level_size(root, *level - 1); |
2238 | |||
2185 | ret = lookup_extent_ref(trans, root, bytenr, blocksize, &refs); | 2239 | ret = lookup_extent_ref(trans, root, bytenr, blocksize, &refs); |
2186 | BUG_ON(ret); | 2240 | BUG_ON(ret); |
2187 | if (refs != 1) { | 2241 | if (refs != 1) { |
@@ -2189,7 +2243,7 @@ static int noinline walk_down_tree(struct btrfs_trans_handle *trans, | |||
2189 | root_owner = btrfs_header_owner(parent); | 2243 | root_owner = btrfs_header_owner(parent); |
2190 | root_gen = btrfs_header_generation(parent); | 2244 | root_gen = btrfs_header_generation(parent); |
2191 | path->slots[*level]++; | 2245 | path->slots[*level]++; |
2192 | ret = btrfs_free_extent(trans, root, bytenr, | 2246 | ret = __btrfs_free_extent(trans, root, bytenr, |
2193 | blocksize, root_owner, | 2247 | blocksize, root_owner, |
2194 | root_gen, 0, 0, 1); | 2248 | root_gen, 0, 0, 1); |
2195 | BUG_ON(ret); | 2249 | BUG_ON(ret); |
@@ -2201,9 +2255,11 @@ static int noinline walk_down_tree(struct btrfs_trans_handle *trans, | |||
2201 | reada_walk_down(root, cur, path->slots[*level]); | 2255 | reada_walk_down(root, cur, path->slots[*level]); |
2202 | 2256 | ||
2203 | mutex_unlock(&root->fs_info->fs_mutex); | 2257 | mutex_unlock(&root->fs_info->fs_mutex); |
2258 | mutex_unlock(&root->fs_info->alloc_mutex); | ||
2204 | next = read_tree_block(root, bytenr, blocksize, | 2259 | next = read_tree_block(root, bytenr, blocksize, |
2205 | ptr_gen); | 2260 | ptr_gen); |
2206 | mutex_lock(&root->fs_info->fs_mutex); | 2261 | mutex_lock(&root->fs_info->fs_mutex); |
2262 | mutex_lock(&root->fs_info->alloc_mutex); | ||
2207 | 2263 | ||
2208 | /* we've dropped the lock, double check */ | 2264 | /* we've dropped the lock, double check */ |
2209 | ret = lookup_extent_ref(trans, root, bytenr, | 2265 | ret = lookup_extent_ref(trans, root, bytenr, |
@@ -2216,7 +2272,7 @@ static int noinline walk_down_tree(struct btrfs_trans_handle *trans, | |||
2216 | 2272 | ||
2217 | path->slots[*level]++; | 2273 | path->slots[*level]++; |
2218 | free_extent_buffer(next); | 2274 | free_extent_buffer(next); |
2219 | ret = btrfs_free_extent(trans, root, bytenr, | 2275 | ret = __btrfs_free_extent(trans, root, bytenr, |
2220 | blocksize, | 2276 | blocksize, |
2221 | root_owner, | 2277 | root_owner, |
2222 | root_gen, 0, 0, 1); | 2278 | root_gen, 0, 0, 1); |
@@ -2244,13 +2300,14 @@ out: | |||
2244 | } | 2300 | } |
2245 | 2301 | ||
2246 | root_gen = btrfs_header_generation(parent); | 2302 | root_gen = btrfs_header_generation(parent); |
2247 | ret = btrfs_free_extent(trans, root, path->nodes[*level]->start, | 2303 | ret = __btrfs_free_extent(trans, root, path->nodes[*level]->start, |
2248 | path->nodes[*level]->len, | 2304 | path->nodes[*level]->len, |
2249 | root_owner, root_gen, 0, 0, 1); | 2305 | root_owner, root_gen, 0, 0, 1); |
2250 | free_extent_buffer(path->nodes[*level]); | 2306 | free_extent_buffer(path->nodes[*level]); |
2251 | path->nodes[*level] = NULL; | 2307 | path->nodes[*level] = NULL; |
2252 | *level += 1; | 2308 | *level += 1; |
2253 | BUG_ON(ret); | 2309 | BUG_ON(ret); |
2310 | mutex_unlock(&root->fs_info->alloc_mutex); | ||
2254 | return 0; | 2311 | return 0; |
2255 | } | 2312 | } |
2256 | 2313 | ||
@@ -2350,6 +2407,12 @@ int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root | |||
2350 | btrfs_node_key(node, &found_key, path->slots[level]); | 2407 | btrfs_node_key(node, &found_key, path->slots[level]); |
2351 | WARN_ON(memcmp(&found_key, &root_item->drop_progress, | 2408 | WARN_ON(memcmp(&found_key, &root_item->drop_progress, |
2352 | sizeof(found_key))); | 2409 | sizeof(found_key))); |
2410 | for (i = 0; i < BTRFS_MAX_LEVEL; i++) { | ||
2411 | if (path->nodes[i] && path->locks[i]) { | ||
2412 | path->locks[i] = 0; | ||
2413 | btrfs_tree_unlock(path->nodes[i]); | ||
2414 | } | ||
2415 | } | ||
2353 | } | 2416 | } |
2354 | while(1) { | 2417 | while(1) { |
2355 | wret = walk_down_tree(trans, root, path, &level); | 2418 | wret = walk_down_tree(trans, root, path, &level); |
@@ -2383,6 +2446,8 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info) | |||
2383 | u64 end; | 2446 | u64 end; |
2384 | u64 ptr; | 2447 | u64 ptr; |
2385 | int ret; | 2448 | int ret; |
2449 | |||
2450 | mutex_lock(&info->alloc_mutex); | ||
2386 | while(1) { | 2451 | while(1) { |
2387 | ret = find_first_extent_bit(&info->block_group_cache, 0, | 2452 | ret = find_first_extent_bit(&info->block_group_cache, 0, |
2388 | &start, &end, (unsigned int)-1); | 2453 | &start, &end, (unsigned int)-1); |
@@ -2402,6 +2467,7 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info) | |||
2402 | clear_extent_dirty(&info->free_space_cache, start, | 2467 | clear_extent_dirty(&info->free_space_cache, start, |
2403 | end, GFP_NOFS); | 2468 | end, GFP_NOFS); |
2404 | } | 2469 | } |
2470 | mutex_unlock(&info->alloc_mutex); | ||
2405 | return 0; | 2471 | return 0; |
2406 | } | 2472 | } |
2407 | 2473 | ||
@@ -2678,6 +2744,7 @@ static int noinline relocate_one_reference(struct btrfs_root *extent_root, | |||
2678 | 2744 | ||
2679 | eb = read_tree_block(found_root, extent_key->objectid, | 2745 | eb = read_tree_block(found_root, extent_key->objectid, |
2680 | extent_key->offset, 0); | 2746 | extent_key->offset, 0); |
2747 | btrfs_tree_lock(eb); | ||
2681 | level = btrfs_header_level(eb); | 2748 | level = btrfs_header_level(eb); |
2682 | 2749 | ||
2683 | if (level == 0) | 2750 | if (level == 0) |
@@ -2685,6 +2752,7 @@ static int noinline relocate_one_reference(struct btrfs_root *extent_root, | |||
2685 | else | 2752 | else |
2686 | btrfs_node_key_to_cpu(eb, &found_key, 0); | 2753 | btrfs_node_key_to_cpu(eb, &found_key, 0); |
2687 | 2754 | ||
2755 | btrfs_tree_unlock(eb); | ||
2688 | free_extent_buffer(eb); | 2756 | free_extent_buffer(eb); |
2689 | 2757 | ||
2690 | ret = find_root_for_ref(extent_root, path, &found_key, | 2758 | ret = find_root_for_ref(extent_root, path, &found_key, |
@@ -2888,6 +2956,7 @@ int btrfs_shrink_extent_tree(struct btrfs_root *root, u64 shrink_start) | |||
2888 | int ret; | 2956 | int ret; |
2889 | int progress; | 2957 | int progress; |
2890 | 2958 | ||
2959 | mutex_lock(&root->fs_info->alloc_mutex); | ||
2891 | shrink_block_group = btrfs_lookup_block_group(root->fs_info, | 2960 | shrink_block_group = btrfs_lookup_block_group(root->fs_info, |
2892 | shrink_start); | 2961 | shrink_start); |
2893 | BUG_ON(!shrink_block_group); | 2962 | BUG_ON(!shrink_block_group); |
@@ -3044,20 +3113,22 @@ next: | |||
3044 | (unsigned int)-1, GFP_NOFS); | 3113 | (unsigned int)-1, GFP_NOFS); |
3045 | out: | 3114 | out: |
3046 | btrfs_free_path(path); | 3115 | btrfs_free_path(path); |
3116 | mutex_unlock(&root->fs_info->alloc_mutex); | ||
3047 | return ret; | 3117 | return ret; |
3048 | } | 3118 | } |
3049 | 3119 | ||
3050 | int find_first_block_group(struct btrfs_root *root, struct btrfs_path *path, | 3120 | int find_first_block_group(struct btrfs_root *root, struct btrfs_path *path, |
3051 | struct btrfs_key *key) | 3121 | struct btrfs_key *key) |
3052 | { | 3122 | { |
3053 | int ret; | 3123 | int ret = 0; |
3054 | struct btrfs_key found_key; | 3124 | struct btrfs_key found_key; |
3055 | struct extent_buffer *leaf; | 3125 | struct extent_buffer *leaf; |
3056 | int slot; | 3126 | int slot; |
3057 | 3127 | ||
3058 | ret = btrfs_search_slot(NULL, root, key, path, 0, 0); | 3128 | ret = btrfs_search_slot(NULL, root, key, path, 0, 0); |
3059 | if (ret < 0) | 3129 | if (ret < 0) |
3060 | return ret; | 3130 | goto out; |
3131 | |||
3061 | while(1) { | 3132 | while(1) { |
3062 | slot = path->slots[0]; | 3133 | slot = path->slots[0]; |
3063 | leaf = path->nodes[0]; | 3134 | leaf = path->nodes[0]; |
@@ -3066,18 +3137,20 @@ int find_first_block_group(struct btrfs_root *root, struct btrfs_path *path, | |||
3066 | if (ret == 0) | 3137 | if (ret == 0) |
3067 | continue; | 3138 | continue; |
3068 | if (ret < 0) | 3139 | if (ret < 0) |
3069 | goto error; | 3140 | goto out; |
3070 | break; | 3141 | break; |
3071 | } | 3142 | } |
3072 | btrfs_item_key_to_cpu(leaf, &found_key, slot); | 3143 | btrfs_item_key_to_cpu(leaf, &found_key, slot); |
3073 | 3144 | ||
3074 | if (found_key.objectid >= key->objectid && | 3145 | if (found_key.objectid >= key->objectid && |
3075 | found_key.type == BTRFS_BLOCK_GROUP_ITEM_KEY) | 3146 | found_key.type == BTRFS_BLOCK_GROUP_ITEM_KEY) { |
3076 | return 0; | 3147 | ret = 0; |
3148 | goto out; | ||
3149 | } | ||
3077 | path->slots[0]++; | 3150 | path->slots[0]++; |
3078 | } | 3151 | } |
3079 | ret = -ENOENT; | 3152 | ret = -ENOENT; |
3080 | error: | 3153 | out: |
3081 | return ret; | 3154 | return ret; |
3082 | } | 3155 | } |
3083 | 3156 | ||
@@ -3103,6 +3176,7 @@ int btrfs_read_block_groups(struct btrfs_root *root) | |||
3103 | if (!path) | 3176 | if (!path) |
3104 | return -ENOMEM; | 3177 | return -ENOMEM; |
3105 | 3178 | ||
3179 | mutex_lock(&root->fs_info->alloc_mutex); | ||
3106 | while(1) { | 3180 | while(1) { |
3107 | ret = find_first_block_group(root, path, &key); | 3181 | ret = find_first_block_group(root, path, &key); |
3108 | if (ret > 0) { | 3182 | if (ret > 0) { |
@@ -3158,6 +3232,7 @@ int btrfs_read_block_groups(struct btrfs_root *root) | |||
3158 | ret = 0; | 3232 | ret = 0; |
3159 | error: | 3233 | error: |
3160 | btrfs_free_path(path); | 3234 | btrfs_free_path(path); |
3235 | mutex_unlock(&root->fs_info->alloc_mutex); | ||
3161 | return ret; | 3236 | return ret; |
3162 | } | 3237 | } |
3163 | 3238 | ||
@@ -3205,5 +3280,6 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans, | |||
3205 | ret = del_pending_extents(trans, extent_root); | 3280 | ret = del_pending_extents(trans, extent_root); |
3206 | BUG_ON(ret); | 3281 | BUG_ON(ret); |
3207 | set_avail_alloc_bits(extent_root->fs_info, type); | 3282 | set_avail_alloc_bits(extent_root->fs_info, type); |
3283 | |||
3208 | return 0; | 3284 | return 0; |
3209 | } | 3285 | } |