diff options
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/Makefile | 2 | ||||
-rw-r--r-- | fs/btrfs/ctree.c | 386 | ||||
-rw-r--r-- | fs/btrfs/ctree.h | 23 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 13 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 252 | ||||
-rw-r--r-- | fs/btrfs/extent_io.c | 8 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 8 | ||||
-rw-r--r-- | fs/btrfs/ioctl.c | 8 | ||||
-rw-r--r-- | fs/btrfs/locking.c | 50 | ||||
-rw-r--r-- | fs/btrfs/locking.h | 26 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 15 | ||||
-rw-r--r-- | fs/btrfs/tree-defrag.c | 2 |
12 files changed, 579 insertions, 214 deletions
diff --git a/fs/btrfs/Makefile b/fs/btrfs/Makefile index 7ed6b39e42d2..0e2dcc718de2 100644 --- a/fs/btrfs/Makefile +++ b/fs/btrfs/Makefile | |||
@@ -6,7 +6,7 @@ btrfs-y := super.o ctree.o extent-tree.o print-tree.o root-tree.o dir-item.o \ | |||
6 | hash.o file-item.o inode-item.o inode-map.o disk-io.o \ | 6 | hash.o file-item.o inode-item.o inode-map.o disk-io.o \ |
7 | transaction.o bit-radix.o inode.o file.o tree-defrag.o \ | 7 | transaction.o bit-radix.o inode.o file.o tree-defrag.o \ |
8 | extent_map.o sysfs.o struct-funcs.o xattr.o ordered-data.o \ | 8 | extent_map.o sysfs.o struct-funcs.o xattr.o ordered-data.o \ |
9 | extent_io.o volumes.o async-thread.o ioctl.o | 9 | extent_io.o volumes.o async-thread.o ioctl.o locking.o |
10 | 10 | ||
11 | btrfs-$(CONFIG_FS_POSIX_ACL) += acl.o | 11 | btrfs-$(CONFIG_FS_POSIX_ACL) += acl.o |
12 | else | 12 | else |
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 1d404bde3cfa..75625c68fdd8 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include "disk-io.h" | 21 | #include "disk-io.h" |
22 | #include "transaction.h" | 22 | #include "transaction.h" |
23 | #include "print-tree.h" | 23 | #include "print-tree.h" |
24 | #include "locking.h" | ||
24 | 25 | ||
25 | static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root | 26 | static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root |
26 | *root, struct btrfs_path *path, int level); | 27 | *root, struct btrfs_path *path, int level); |
@@ -64,12 +65,47 @@ void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p) | |||
64 | int i; | 65 | int i; |
65 | for (i = 0; i < BTRFS_MAX_LEVEL; i++) { | 66 | for (i = 0; i < BTRFS_MAX_LEVEL; i++) { |
66 | if (!p->nodes[i]) | 67 | if (!p->nodes[i]) |
67 | break; | 68 | continue; |
69 | if (p->locks[i]) { | ||
70 | btrfs_tree_unlock(p->nodes[i]); | ||
71 | p->locks[i] = 0; | ||
72 | } | ||
68 | free_extent_buffer(p->nodes[i]); | 73 | free_extent_buffer(p->nodes[i]); |
69 | } | 74 | } |
70 | memset(p, 0, sizeof(*p)); | 75 | memset(p, 0, sizeof(*p)); |
71 | } | 76 | } |
72 | 77 | ||
78 | struct extent_buffer *btrfs_root_node(struct btrfs_root *root) | ||
79 | { | ||
80 | struct extent_buffer *eb; | ||
81 | spin_lock(&root->node_lock); | ||
82 | eb = root->node; | ||
83 | extent_buffer_get(eb); | ||
84 | spin_unlock(&root->node_lock); | ||
85 | return eb; | ||
86 | } | ||
87 | |||
88 | struct extent_buffer *btrfs_lock_root_node(struct btrfs_root *root) | ||
89 | { | ||
90 | struct extent_buffer *eb; | ||
91 | |||
92 | while(1) { | ||
93 | eb = btrfs_root_node(root); | ||
94 | btrfs_tree_lock(eb); | ||
95 | |||
96 | spin_lock(&root->node_lock); | ||
97 | if (eb == root->node) { | ||
98 | spin_unlock(&root->node_lock); | ||
99 | break; | ||
100 | } | ||
101 | spin_unlock(&root->node_lock); | ||
102 | |||
103 | btrfs_tree_unlock(eb); | ||
104 | free_extent_buffer(eb); | ||
105 | } | ||
106 | return eb; | ||
107 | } | ||
108 | |||
73 | static void add_root_to_dirty_list(struct btrfs_root *root) | 109 | static void add_root_to_dirty_list(struct btrfs_root *root) |
74 | { | 110 | { |
75 | if (root->track_dirty && list_empty(&root->dirty_list)) { | 111 | if (root->track_dirty && list_empty(&root->dirty_list)) { |
@@ -111,7 +147,7 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans, | |||
111 | } else { | 147 | } else { |
112 | first_key.objectid = 0; | 148 | first_key.objectid = 0; |
113 | } | 149 | } |
114 | cow = __btrfs_alloc_free_block(trans, new_root, buf->len, | 150 | cow = btrfs_alloc_free_block(trans, new_root, buf->len, |
115 | new_root_objectid, | 151 | new_root_objectid, |
116 | trans->transid, first_key.objectid, | 152 | trans->transid, first_key.objectid, |
117 | level, buf->start, 0); | 153 | level, buf->start, 0); |
@@ -151,8 +187,14 @@ int __btrfs_cow_block(struct btrfs_trans_handle *trans, | |||
151 | int ret = 0; | 187 | int ret = 0; |
152 | int different_trans = 0; | 188 | int different_trans = 0; |
153 | int level; | 189 | int level; |
190 | int unlock_orig = 0; | ||
154 | struct btrfs_key first_key; | 191 | struct btrfs_key first_key; |
155 | 192 | ||
193 | if (*cow_ret == buf) | ||
194 | unlock_orig = 1; | ||
195 | |||
196 | WARN_ON(!btrfs_tree_locked(buf)); | ||
197 | |||
156 | if (root->ref_cows) { | 198 | if (root->ref_cows) { |
157 | root_gen = trans->transid; | 199 | root_gen = trans->transid; |
158 | } else { | 200 | } else { |
@@ -172,7 +214,7 @@ int __btrfs_cow_block(struct btrfs_trans_handle *trans, | |||
172 | } else { | 214 | } else { |
173 | first_key.objectid = 0; | 215 | first_key.objectid = 0; |
174 | } | 216 | } |
175 | cow = __btrfs_alloc_free_block(trans, root, buf->len, | 217 | cow = btrfs_alloc_free_block(trans, root, buf->len, |
176 | root->root_key.objectid, | 218 | root->root_key.objectid, |
177 | root_gen, first_key.objectid, level, | 219 | root_gen, first_key.objectid, level, |
178 | search_start, empty_size); | 220 | search_start, empty_size); |
@@ -196,9 +238,14 @@ int __btrfs_cow_block(struct btrfs_trans_handle *trans, | |||
196 | } | 238 | } |
197 | 239 | ||
198 | if (buf == root->node) { | 240 | if (buf == root->node) { |
241 | WARN_ON(parent && parent != buf); | ||
199 | root_gen = btrfs_header_generation(buf); | 242 | root_gen = btrfs_header_generation(buf); |
243 | |||
244 | spin_lock(&root->node_lock); | ||
200 | root->node = cow; | 245 | root->node = cow; |
201 | extent_buffer_get(cow); | 246 | extent_buffer_get(cow); |
247 | spin_unlock(&root->node_lock); | ||
248 | |||
202 | if (buf != root->commit_root) { | 249 | if (buf != root->commit_root) { |
203 | btrfs_free_extent(trans, root, buf->start, | 250 | btrfs_free_extent(trans, root, buf->start, |
204 | buf->len, root->root_key.objectid, | 251 | buf->len, root->root_key.objectid, |
@@ -219,6 +266,8 @@ int __btrfs_cow_block(struct btrfs_trans_handle *trans, | |||
219 | btrfs_header_owner(parent), root_gen, | 266 | btrfs_header_owner(parent), root_gen, |
220 | 0, 0, 1); | 267 | 0, 0, 1); |
221 | } | 268 | } |
269 | if (unlock_orig) | ||
270 | btrfs_tree_unlock(buf); | ||
222 | free_extent_buffer(buf); | 271 | free_extent_buffer(buf); |
223 | btrfs_mark_buffer_dirty(cow); | 272 | btrfs_mark_buffer_dirty(cow); |
224 | *cow_ret = cow; | 273 | *cow_ret = cow; |
@@ -316,6 +365,9 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, | |||
316 | int progress_passed = 0; | 365 | int progress_passed = 0; |
317 | struct btrfs_disk_key disk_key; | 366 | struct btrfs_disk_key disk_key; |
318 | 367 | ||
368 | /* FIXME this code needs locking */ | ||
369 | return 0; | ||
370 | |||
319 | parent_level = btrfs_header_level(parent); | 371 | parent_level = btrfs_header_level(parent); |
320 | if (cache_only && parent_level != 1) | 372 | if (cache_only && parent_level != 1) |
321 | return 0; | 373 | return 0; |
@@ -729,6 +781,7 @@ static int balance_level(struct btrfs_trans_handle *trans, | |||
729 | return 0; | 781 | return 0; |
730 | 782 | ||
731 | mid = path->nodes[level]; | 783 | mid = path->nodes[level]; |
784 | WARN_ON(!path->locks[level]); | ||
732 | WARN_ON(btrfs_header_generation(mid) != trans->transid); | 785 | WARN_ON(btrfs_header_generation(mid) != trans->transid); |
733 | 786 | ||
734 | orig_ptr = btrfs_node_blockptr(mid, orig_slot); | 787 | orig_ptr = btrfs_node_blockptr(mid, orig_slot); |
@@ -749,14 +802,21 @@ static int balance_level(struct btrfs_trans_handle *trans, | |||
749 | 802 | ||
750 | /* promote the child to a root */ | 803 | /* promote the child to a root */ |
751 | child = read_node_slot(root, mid, 0); | 804 | child = read_node_slot(root, mid, 0); |
805 | btrfs_tree_lock(child); | ||
752 | BUG_ON(!child); | 806 | BUG_ON(!child); |
753 | ret = btrfs_cow_block(trans, root, child, mid, 0, &child); | 807 | ret = btrfs_cow_block(trans, root, child, mid, 0, &child); |
754 | BUG_ON(ret); | 808 | BUG_ON(ret); |
755 | 809 | ||
810 | spin_lock(&root->node_lock); | ||
756 | root->node = child; | 811 | root->node = child; |
812 | spin_unlock(&root->node_lock); | ||
813 | |||
757 | add_root_to_dirty_list(root); | 814 | add_root_to_dirty_list(root); |
815 | btrfs_tree_unlock(child); | ||
816 | path->locks[level] = 0; | ||
758 | path->nodes[level] = NULL; | 817 | path->nodes[level] = NULL; |
759 | clean_tree_block(trans, root, mid); | 818 | clean_tree_block(trans, root, mid); |
819 | btrfs_tree_unlock(mid); | ||
760 | /* once for the path */ | 820 | /* once for the path */ |
761 | free_extent_buffer(mid); | 821 | free_extent_buffer(mid); |
762 | ret = btrfs_free_extent(trans, root, mid->start, mid->len, | 822 | ret = btrfs_free_extent(trans, root, mid->start, mid->len, |
@@ -775,6 +835,7 @@ static int balance_level(struct btrfs_trans_handle *trans, | |||
775 | 835 | ||
776 | left = read_node_slot(root, parent, pslot - 1); | 836 | left = read_node_slot(root, parent, pslot - 1); |
777 | if (left) { | 837 | if (left) { |
838 | btrfs_tree_lock(left); | ||
778 | wret = btrfs_cow_block(trans, root, left, | 839 | wret = btrfs_cow_block(trans, root, left, |
779 | parent, pslot - 1, &left); | 840 | parent, pslot - 1, &left); |
780 | if (wret) { | 841 | if (wret) { |
@@ -784,6 +845,7 @@ static int balance_level(struct btrfs_trans_handle *trans, | |||
784 | } | 845 | } |
785 | right = read_node_slot(root, parent, pslot + 1); | 846 | right = read_node_slot(root, parent, pslot + 1); |
786 | if (right) { | 847 | if (right) { |
848 | btrfs_tree_lock(right); | ||
787 | wret = btrfs_cow_block(trans, root, right, | 849 | wret = btrfs_cow_block(trans, root, right, |
788 | parent, pslot + 1, &right); | 850 | parent, pslot + 1, &right); |
789 | if (wret) { | 851 | if (wret) { |
@@ -815,6 +877,7 @@ static int balance_level(struct btrfs_trans_handle *trans, | |||
815 | u32 blocksize = right->len; | 877 | u32 blocksize = right->len; |
816 | 878 | ||
817 | clean_tree_block(trans, root, right); | 879 | clean_tree_block(trans, root, right); |
880 | btrfs_tree_unlock(right); | ||
818 | free_extent_buffer(right); | 881 | free_extent_buffer(right); |
819 | right = NULL; | 882 | right = NULL; |
820 | wret = del_ptr(trans, root, path, level + 1, pslot + | 883 | wret = del_ptr(trans, root, path, level + 1, pslot + |
@@ -862,7 +925,9 @@ static int balance_level(struct btrfs_trans_handle *trans, | |||
862 | u64 root_gen = btrfs_header_generation(parent); | 925 | u64 root_gen = btrfs_header_generation(parent); |
863 | u64 bytenr = mid->start; | 926 | u64 bytenr = mid->start; |
864 | u32 blocksize = mid->len; | 927 | u32 blocksize = mid->len; |
928 | |||
865 | clean_tree_block(trans, root, mid); | 929 | clean_tree_block(trans, root, mid); |
930 | btrfs_tree_unlock(mid); | ||
866 | free_extent_buffer(mid); | 931 | free_extent_buffer(mid); |
867 | mid = NULL; | 932 | mid = NULL; |
868 | wret = del_ptr(trans, root, path, level + 1, pslot); | 933 | wret = del_ptr(trans, root, path, level + 1, pslot); |
@@ -885,11 +950,14 @@ static int balance_level(struct btrfs_trans_handle *trans, | |||
885 | if (left) { | 950 | if (left) { |
886 | if (btrfs_header_nritems(left) > orig_slot) { | 951 | if (btrfs_header_nritems(left) > orig_slot) { |
887 | extent_buffer_get(left); | 952 | extent_buffer_get(left); |
953 | /* left was locked after cow */ | ||
888 | path->nodes[level] = left; | 954 | path->nodes[level] = left; |
889 | path->slots[level + 1] -= 1; | 955 | path->slots[level + 1] -= 1; |
890 | path->slots[level] = orig_slot; | 956 | path->slots[level] = orig_slot; |
891 | if (mid) | 957 | if (mid) { |
958 | btrfs_tree_unlock(mid); | ||
892 | free_extent_buffer(mid); | 959 | free_extent_buffer(mid); |
960 | } | ||
893 | } else { | 961 | } else { |
894 | orig_slot -= btrfs_header_nritems(left); | 962 | orig_slot -= btrfs_header_nritems(left); |
895 | path->slots[level] = orig_slot; | 963 | path->slots[level] = orig_slot; |
@@ -901,10 +969,15 @@ static int balance_level(struct btrfs_trans_handle *trans, | |||
901 | btrfs_node_blockptr(path->nodes[level], path->slots[level])) | 969 | btrfs_node_blockptr(path->nodes[level], path->slots[level])) |
902 | BUG(); | 970 | BUG(); |
903 | enospc: | 971 | enospc: |
904 | if (right) | 972 | if (right) { |
973 | btrfs_tree_unlock(right); | ||
905 | free_extent_buffer(right); | 974 | free_extent_buffer(right); |
906 | if (left) | 975 | } |
976 | if (left) { | ||
977 | if (path->nodes[level] != left) | ||
978 | btrfs_tree_unlock(left); | ||
907 | free_extent_buffer(left); | 979 | free_extent_buffer(left); |
980 | } | ||
908 | return ret; | 981 | return ret; |
909 | } | 982 | } |
910 | 983 | ||
@@ -942,6 +1015,8 @@ static int noinline push_nodes_for_insert(struct btrfs_trans_handle *trans, | |||
942 | /* first, try to make some room in the middle buffer */ | 1015 | /* first, try to make some room in the middle buffer */ |
943 | if (left) { | 1016 | if (left) { |
944 | u32 left_nr; | 1017 | u32 left_nr; |
1018 | |||
1019 | btrfs_tree_lock(left); | ||
945 | left_nr = btrfs_header_nritems(left); | 1020 | left_nr = btrfs_header_nritems(left); |
946 | if (left_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) { | 1021 | if (left_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) { |
947 | wret = 1; | 1022 | wret = 1; |
@@ -967,24 +1042,28 @@ static int noinline push_nodes_for_insert(struct btrfs_trans_handle *trans, | |||
967 | path->nodes[level] = left; | 1042 | path->nodes[level] = left; |
968 | path->slots[level + 1] -= 1; | 1043 | path->slots[level + 1] -= 1; |
969 | path->slots[level] = orig_slot; | 1044 | path->slots[level] = orig_slot; |
1045 | btrfs_tree_unlock(mid); | ||
970 | free_extent_buffer(mid); | 1046 | free_extent_buffer(mid); |
971 | } else { | 1047 | } else { |
972 | orig_slot -= | 1048 | orig_slot -= |
973 | btrfs_header_nritems(left); | 1049 | btrfs_header_nritems(left); |
974 | path->slots[level] = orig_slot; | 1050 | path->slots[level] = orig_slot; |
1051 | btrfs_tree_unlock(left); | ||
975 | free_extent_buffer(left); | 1052 | free_extent_buffer(left); |
976 | } | 1053 | } |
977 | return 0; | 1054 | return 0; |
978 | } | 1055 | } |
1056 | btrfs_tree_unlock(left); | ||
979 | free_extent_buffer(left); | 1057 | free_extent_buffer(left); |
980 | } | 1058 | } |
981 | right= read_node_slot(root, parent, pslot + 1); | 1059 | right = read_node_slot(root, parent, pslot + 1); |
982 | 1060 | ||
983 | /* | 1061 | /* |
984 | * then try to empty the right most buffer into the middle | 1062 | * then try to empty the right most buffer into the middle |
985 | */ | 1063 | */ |
986 | if (right) { | 1064 | if (right) { |
987 | u32 right_nr; | 1065 | u32 right_nr; |
1066 | btrfs_tree_lock(right); | ||
988 | right_nr = btrfs_header_nritems(right); | 1067 | right_nr = btrfs_header_nritems(right); |
989 | if (right_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) { | 1068 | if (right_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) { |
990 | wret = 1; | 1069 | wret = 1; |
@@ -1013,12 +1092,15 @@ static int noinline push_nodes_for_insert(struct btrfs_trans_handle *trans, | |||
1013 | path->slots[level + 1] += 1; | 1092 | path->slots[level + 1] += 1; |
1014 | path->slots[level] = orig_slot - | 1093 | path->slots[level] = orig_slot - |
1015 | btrfs_header_nritems(mid); | 1094 | btrfs_header_nritems(mid); |
1095 | btrfs_tree_unlock(mid); | ||
1016 | free_extent_buffer(mid); | 1096 | free_extent_buffer(mid); |
1017 | } else { | 1097 | } else { |
1098 | btrfs_tree_unlock(right); | ||
1018 | free_extent_buffer(right); | 1099 | free_extent_buffer(right); |
1019 | } | 1100 | } |
1020 | return 0; | 1101 | return 0; |
1021 | } | 1102 | } |
1103 | btrfs_tree_unlock(right); | ||
1022 | free_extent_buffer(right); | 1104 | free_extent_buffer(right); |
1023 | } | 1105 | } |
1024 | return 1; | 1106 | return 1; |
@@ -1050,6 +1132,8 @@ static void reada_for_search(struct btrfs_root *root, struct btrfs_path *path, | |||
1050 | return; | 1132 | return; |
1051 | 1133 | ||
1052 | node = path->nodes[level]; | 1134 | node = path->nodes[level]; |
1135 | WARN_ON(!path->skip_locking && !btrfs_tree_locked(node)); | ||
1136 | |||
1053 | search = btrfs_node_blockptr(node, slot); | 1137 | search = btrfs_node_blockptr(node, slot); |
1054 | blocksize = btrfs_level_size(root, level - 1); | 1138 | blocksize = btrfs_level_size(root, level - 1); |
1055 | eb = btrfs_find_tree_block(root, search, blocksize); | 1139 | eb = btrfs_find_tree_block(root, search, blocksize); |
@@ -1098,6 +1182,39 @@ static void reada_for_search(struct btrfs_root *root, struct btrfs_path *path, | |||
1098 | highest_read = search; | 1182 | highest_read = search; |
1099 | } | 1183 | } |
1100 | } | 1184 | } |
1185 | |||
1186 | static void unlock_up(struct btrfs_path *path, int level, int lowest_unlock) | ||
1187 | { | ||
1188 | int i; | ||
1189 | int skip_level = level; | ||
1190 | struct extent_buffer *t; | ||
1191 | |||
1192 | for (i = level; i < BTRFS_MAX_LEVEL; i++) { | ||
1193 | if (!path->nodes[i]) | ||
1194 | break; | ||
1195 | if (!path->locks[i]) | ||
1196 | break; | ||
1197 | if (path->slots[i] == 0) { | ||
1198 | skip_level = i + 1; | ||
1199 | continue; | ||
1200 | } | ||
1201 | if (path->keep_locks) { | ||
1202 | u32 nritems; | ||
1203 | t = path->nodes[i]; | ||
1204 | nritems = btrfs_header_nritems(t); | ||
1205 | if (path->slots[i] >= nritems - 1) { | ||
1206 | skip_level = i + 1; | ||
1207 | continue; | ||
1208 | } | ||
1209 | } | ||
1210 | t = path->nodes[i]; | ||
1211 | if (i >= lowest_unlock && i > skip_level && path->locks[i]) { | ||
1212 | btrfs_tree_unlock(t); | ||
1213 | path->locks[i] = 0; | ||
1214 | } | ||
1215 | } | ||
1216 | } | ||
1217 | |||
1101 | /* | 1218 | /* |
1102 | * look for key in the tree. path is filled in with nodes along the way | 1219 | * look for key in the tree. path is filled in with nodes along the way |
1103 | * if key is found, we return zero and you can find the item in the leaf | 1220 | * if key is found, we return zero and you can find the item in the leaf |
@@ -1120,15 +1237,27 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1120 | int ret; | 1237 | int ret; |
1121 | int level; | 1238 | int level; |
1122 | int should_reada = p->reada; | 1239 | int should_reada = p->reada; |
1240 | int lowest_unlock = 1; | ||
1123 | u8 lowest_level = 0; | 1241 | u8 lowest_level = 0; |
1124 | 1242 | ||
1125 | lowest_level = p->lowest_level; | 1243 | lowest_level = p->lowest_level; |
1126 | WARN_ON(lowest_level && ins_len); | 1244 | WARN_ON(lowest_level && ins_len); |
1127 | WARN_ON(p->nodes[0] != NULL); | 1245 | WARN_ON(p->nodes[0] != NULL); |
1128 | WARN_ON(!mutex_is_locked(&root->fs_info->fs_mutex)); | 1246 | // WARN_ON(!mutex_is_locked(&root->fs_info->fs_mutex)); |
1247 | WARN_ON(root == root->fs_info->extent_root && | ||
1248 | !mutex_is_locked(&root->fs_info->alloc_mutex)); | ||
1249 | WARN_ON(root == root->fs_info->chunk_root && | ||
1250 | !mutex_is_locked(&root->fs_info->chunk_mutex)); | ||
1251 | WARN_ON(root == root->fs_info->dev_root && | ||
1252 | !mutex_is_locked(&root->fs_info->chunk_mutex)); | ||
1253 | if (ins_len < 0) | ||
1254 | lowest_unlock = 2; | ||
1129 | again: | 1255 | again: |
1130 | b = root->node; | 1256 | if (!p->skip_locking) |
1131 | extent_buffer_get(b); | 1257 | b = btrfs_lock_root_node(root); |
1258 | else | ||
1259 | b = btrfs_root_node(root); | ||
1260 | |||
1132 | while (b) { | 1261 | while (b) { |
1133 | level = btrfs_header_level(b); | 1262 | level = btrfs_header_level(b); |
1134 | if (cow) { | 1263 | if (cow) { |
@@ -1147,9 +1276,12 @@ again: | |||
1147 | WARN_ON(1); | 1276 | WARN_ON(1); |
1148 | level = btrfs_header_level(b); | 1277 | level = btrfs_header_level(b); |
1149 | p->nodes[level] = b; | 1278 | p->nodes[level] = b; |
1279 | if (!p->skip_locking) | ||
1280 | p->locks[level] = 1; | ||
1150 | ret = check_block(root, p, level); | 1281 | ret = check_block(root, p, level); |
1151 | if (ret) | 1282 | if (ret) |
1152 | return -1; | 1283 | return -1; |
1284 | |||
1153 | ret = bin_search(b, key, level, &slot); | 1285 | ret = bin_search(b, key, level, &slot); |
1154 | if (level != 0) { | 1286 | if (level != 0) { |
1155 | if (ret && slot > 0) | 1287 | if (ret && slot > 0) |
@@ -1177,14 +1309,19 @@ again: | |||
1177 | BUG_ON(btrfs_header_nritems(b) == 1); | 1309 | BUG_ON(btrfs_header_nritems(b) == 1); |
1178 | } | 1310 | } |
1179 | /* this is only true while dropping a snapshot */ | 1311 | /* this is only true while dropping a snapshot */ |
1180 | if (level == lowest_level) | 1312 | if (level == lowest_level) { |
1313 | unlock_up(p, level, lowest_unlock); | ||
1181 | break; | 1314 | break; |
1315 | } | ||
1182 | 1316 | ||
1183 | if (should_reada) | 1317 | if (should_reada) |
1184 | reada_for_search(root, p, level, slot, | 1318 | reada_for_search(root, p, level, slot, |
1185 | key->objectid); | 1319 | key->objectid); |
1186 | 1320 | ||
1187 | b = read_node_slot(root, b, slot); | 1321 | b = read_node_slot(root, b, slot); |
1322 | if (!p->skip_locking) | ||
1323 | btrfs_tree_lock(b); | ||
1324 | unlock_up(p, level, lowest_unlock); | ||
1188 | } else { | 1325 | } else { |
1189 | p->slots[level] = slot; | 1326 | p->slots[level] = slot; |
1190 | if (ins_len > 0 && btrfs_leaf_free_space(root, b) < | 1327 | if (ins_len > 0 && btrfs_leaf_free_space(root, b) < |
@@ -1195,6 +1332,7 @@ again: | |||
1195 | if (sret) | 1332 | if (sret) |
1196 | return sret; | 1333 | return sret; |
1197 | } | 1334 | } |
1335 | unlock_up(p, level, lowest_unlock); | ||
1198 | return ret; | 1336 | return ret; |
1199 | } | 1337 | } |
1200 | } | 1338 | } |
@@ -1225,6 +1363,13 @@ static int fixup_low_keys(struct btrfs_trans_handle *trans, | |||
1225 | break; | 1363 | break; |
1226 | t = path->nodes[i]; | 1364 | t = path->nodes[i]; |
1227 | btrfs_set_node_key(t, key, tslot); | 1365 | btrfs_set_node_key(t, key, tslot); |
1366 | if (!btrfs_tree_locked(path->nodes[i])) { | ||
1367 | int ii; | ||
1368 | printk("fixup without lock on level %d\n", btrfs_header_level(path->nodes[i])); | ||
1369 | for (ii = 0; ii < BTRFS_MAX_LEVEL; ii++) { | ||
1370 | printk("level %d slot %d\n", ii, path->slots[ii]); | ||
1371 | } | ||
1372 | } | ||
1228 | btrfs_mark_buffer_dirty(path->nodes[i]); | 1373 | btrfs_mark_buffer_dirty(path->nodes[i]); |
1229 | if (tslot != 0) | 1374 | if (tslot != 0) |
1230 | break; | 1375 | break; |
@@ -1370,6 +1515,7 @@ static int noinline insert_new_root(struct btrfs_trans_handle *trans, | |||
1370 | u64 lower_gen; | 1515 | u64 lower_gen; |
1371 | struct extent_buffer *lower; | 1516 | struct extent_buffer *lower; |
1372 | struct extent_buffer *c; | 1517 | struct extent_buffer *c; |
1518 | struct extent_buffer *old; | ||
1373 | struct btrfs_disk_key lower_key; | 1519 | struct btrfs_disk_key lower_key; |
1374 | 1520 | ||
1375 | BUG_ON(path->nodes[level]); | 1521 | BUG_ON(path->nodes[level]); |
@@ -1386,12 +1532,13 @@ static int noinline insert_new_root(struct btrfs_trans_handle *trans, | |||
1386 | else | 1532 | else |
1387 | btrfs_node_key(lower, &lower_key, 0); | 1533 | btrfs_node_key(lower, &lower_key, 0); |
1388 | 1534 | ||
1389 | c = __btrfs_alloc_free_block(trans, root, root->nodesize, | 1535 | c = btrfs_alloc_free_block(trans, root, root->nodesize, |
1390 | root->root_key.objectid, | 1536 | root->root_key.objectid, |
1391 | root_gen, lower_key.objectid, level, | 1537 | root_gen, lower_key.objectid, level, |
1392 | root->node->start, 0); | 1538 | root->node->start, 0); |
1393 | if (IS_ERR(c)) | 1539 | if (IS_ERR(c)) |
1394 | return PTR_ERR(c); | 1540 | return PTR_ERR(c); |
1541 | |||
1395 | memset_extent_buffer(c, 0, 0, root->nodesize); | 1542 | memset_extent_buffer(c, 0, 0, root->nodesize); |
1396 | btrfs_set_header_nritems(c, 1); | 1543 | btrfs_set_header_nritems(c, 1); |
1397 | btrfs_set_header_level(c, level); | 1544 | btrfs_set_header_level(c, level); |
@@ -1416,23 +1563,31 @@ static int noinline insert_new_root(struct btrfs_trans_handle *trans, | |||
1416 | 1563 | ||
1417 | btrfs_mark_buffer_dirty(c); | 1564 | btrfs_mark_buffer_dirty(c); |
1418 | 1565 | ||
1419 | /* the super has an extra ref to root->node */ | 1566 | spin_lock(&root->node_lock); |
1420 | free_extent_buffer(root->node); | 1567 | old = root->node; |
1421 | root->node = c; | 1568 | root->node = c; |
1569 | spin_unlock(&root->node_lock); | ||
1570 | |||
1571 | /* the super has an extra ref to root->node */ | ||
1572 | free_extent_buffer(old); | ||
1573 | |||
1422 | add_root_to_dirty_list(root); | 1574 | add_root_to_dirty_list(root); |
1423 | extent_buffer_get(c); | 1575 | extent_buffer_get(c); |
1424 | path->nodes[level] = c; | 1576 | path->nodes[level] = c; |
1577 | path->locks[level] = 1; | ||
1425 | path->slots[level] = 0; | 1578 | path->slots[level] = 0; |
1426 | 1579 | ||
1427 | if (root->ref_cows && lower_gen != trans->transid) { | 1580 | if (root->ref_cows && lower_gen != trans->transid) { |
1428 | struct btrfs_path *back_path = btrfs_alloc_path(); | 1581 | struct btrfs_path *back_path = btrfs_alloc_path(); |
1429 | int ret; | 1582 | int ret; |
1583 | mutex_lock(&root->fs_info->alloc_mutex); | ||
1430 | ret = btrfs_insert_extent_backref(trans, | 1584 | ret = btrfs_insert_extent_backref(trans, |
1431 | root->fs_info->extent_root, | 1585 | root->fs_info->extent_root, |
1432 | path, lower->start, | 1586 | path, lower->start, |
1433 | root->root_key.objectid, | 1587 | root->root_key.objectid, |
1434 | trans->transid, 0, 0); | 1588 | trans->transid, 0, 0); |
1435 | BUG_ON(ret); | 1589 | BUG_ON(ret); |
1590 | mutex_unlock(&root->fs_info->alloc_mutex); | ||
1436 | btrfs_free_path(back_path); | 1591 | btrfs_free_path(back_path); |
1437 | } | 1592 | } |
1438 | return 0; | 1593 | return 0; |
@@ -1521,7 +1676,7 @@ static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1521 | root_gen = 0; | 1676 | root_gen = 0; |
1522 | 1677 | ||
1523 | btrfs_node_key(c, &disk_key, 0); | 1678 | btrfs_node_key(c, &disk_key, 0); |
1524 | split = __btrfs_alloc_free_block(trans, root, root->nodesize, | 1679 | split = btrfs_alloc_free_block(trans, root, root->nodesize, |
1525 | root->root_key.objectid, | 1680 | root->root_key.objectid, |
1526 | root_gen, | 1681 | root_gen, |
1527 | btrfs_disk_key_objectid(&disk_key), | 1682 | btrfs_disk_key_objectid(&disk_key), |
@@ -1564,10 +1719,12 @@ static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1564 | 1719 | ||
1565 | if (path->slots[level] >= mid) { | 1720 | if (path->slots[level] >= mid) { |
1566 | path->slots[level] -= mid; | 1721 | path->slots[level] -= mid; |
1722 | btrfs_tree_unlock(c); | ||
1567 | free_extent_buffer(c); | 1723 | free_extent_buffer(c); |
1568 | path->nodes[level] = split; | 1724 | path->nodes[level] = split; |
1569 | path->slots[level + 1] += 1; | 1725 | path->slots[level + 1] += 1; |
1570 | } else { | 1726 | } else { |
1727 | btrfs_tree_unlock(split); | ||
1571 | free_extent_buffer(split); | 1728 | free_extent_buffer(split); |
1572 | } | 1729 | } |
1573 | return ret; | 1730 | return ret; |
@@ -1648,30 +1805,24 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1648 | return 1; | 1805 | return 1; |
1649 | 1806 | ||
1650 | right = read_node_slot(root, upper, slot + 1); | 1807 | right = read_node_slot(root, upper, slot + 1); |
1808 | btrfs_tree_lock(right); | ||
1651 | free_space = btrfs_leaf_free_space(root, right); | 1809 | free_space = btrfs_leaf_free_space(root, right); |
1652 | if (free_space < data_size + sizeof(struct btrfs_item)) { | 1810 | if (free_space < data_size + sizeof(struct btrfs_item)) |
1653 | free_extent_buffer(right); | 1811 | goto out_unlock; |
1654 | return 1; | ||
1655 | } | ||
1656 | 1812 | ||
1657 | /* cow and double check */ | 1813 | /* cow and double check */ |
1658 | ret = btrfs_cow_block(trans, root, right, upper, | 1814 | ret = btrfs_cow_block(trans, root, right, upper, |
1659 | slot + 1, &right); | 1815 | slot + 1, &right); |
1660 | if (ret) { | 1816 | if (ret) |
1661 | free_extent_buffer(right); | 1817 | goto out_unlock; |
1662 | return 1; | 1818 | |
1663 | } | ||
1664 | free_space = btrfs_leaf_free_space(root, right); | 1819 | free_space = btrfs_leaf_free_space(root, right); |
1665 | if (free_space < data_size + sizeof(struct btrfs_item)) { | 1820 | if (free_space < data_size + sizeof(struct btrfs_item)) |
1666 | free_extent_buffer(right); | 1821 | goto out_unlock; |
1667 | return 1; | ||
1668 | } | ||
1669 | 1822 | ||
1670 | left_nritems = btrfs_header_nritems(left); | 1823 | left_nritems = btrfs_header_nritems(left); |
1671 | if (left_nritems == 0) { | 1824 | if (left_nritems == 0) |
1672 | free_extent_buffer(right); | 1825 | goto out_unlock; |
1673 | return 1; | ||
1674 | } | ||
1675 | 1826 | ||
1676 | if (empty) | 1827 | if (empty) |
1677 | nr = 0; | 1828 | nr = 0; |
@@ -1707,10 +1858,8 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1707 | left->map_token = NULL; | 1858 | left->map_token = NULL; |
1708 | } | 1859 | } |
1709 | 1860 | ||
1710 | if (push_items == 0) { | 1861 | if (push_items == 0) |
1711 | free_extent_buffer(right); | 1862 | goto out_unlock; |
1712 | return 1; | ||
1713 | } | ||
1714 | 1863 | ||
1715 | if (!empty && push_items == left_nritems) | 1864 | if (!empty && push_items == left_nritems) |
1716 | WARN_ON(1); | 1865 | WARN_ON(1); |
@@ -1778,14 +1927,24 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1778 | /* then fixup the leaf pointer in the path */ | 1927 | /* then fixup the leaf pointer in the path */ |
1779 | if (path->slots[0] >= left_nritems) { | 1928 | if (path->slots[0] >= left_nritems) { |
1780 | path->slots[0] -= left_nritems; | 1929 | path->slots[0] -= left_nritems; |
1930 | if (btrfs_header_nritems(path->nodes[0]) == 0) | ||
1931 | clean_tree_block(trans, root, path->nodes[0]); | ||
1932 | btrfs_tree_unlock(path->nodes[0]); | ||
1781 | free_extent_buffer(path->nodes[0]); | 1933 | free_extent_buffer(path->nodes[0]); |
1782 | path->nodes[0] = right; | 1934 | path->nodes[0] = right; |
1783 | path->slots[1] += 1; | 1935 | path->slots[1] += 1; |
1784 | } else { | 1936 | } else { |
1937 | btrfs_tree_unlock(right); | ||
1785 | free_extent_buffer(right); | 1938 | free_extent_buffer(right); |
1786 | } | 1939 | } |
1787 | return 0; | 1940 | return 0; |
1941 | |||
1942 | out_unlock: | ||
1943 | btrfs_tree_unlock(right); | ||
1944 | free_extent_buffer(right); | ||
1945 | return 1; | ||
1788 | } | 1946 | } |
1947 | |||
1789 | /* | 1948 | /* |
1790 | * push some data in the path leaf to the left, trying to free up at | 1949 | * push some data in the path leaf to the left, trying to free up at |
1791 | * least data_size bytes. returns zero if the push worked, nonzero otherwise | 1950 | * least data_size bytes. returns zero if the push worked, nonzero otherwise |
@@ -1823,10 +1982,11 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1823 | } | 1982 | } |
1824 | 1983 | ||
1825 | left = read_node_slot(root, path->nodes[1], slot - 1); | 1984 | left = read_node_slot(root, path->nodes[1], slot - 1); |
1985 | btrfs_tree_lock(left); | ||
1826 | free_space = btrfs_leaf_free_space(root, left); | 1986 | free_space = btrfs_leaf_free_space(root, left); |
1827 | if (free_space < data_size + sizeof(struct btrfs_item)) { | 1987 | if (free_space < data_size + sizeof(struct btrfs_item)) { |
1828 | free_extent_buffer(left); | 1988 | ret = 1; |
1829 | return 1; | 1989 | goto out; |
1830 | } | 1990 | } |
1831 | 1991 | ||
1832 | /* cow and double check */ | 1992 | /* cow and double check */ |
@@ -1834,14 +1994,14 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1834 | path->nodes[1], slot - 1, &left); | 1994 | path->nodes[1], slot - 1, &left); |
1835 | if (ret) { | 1995 | if (ret) { |
1836 | /* we hit -ENOSPC, but it isn't fatal here */ | 1996 | /* we hit -ENOSPC, but it isn't fatal here */ |
1837 | free_extent_buffer(left); | 1997 | ret = 1; |
1838 | return 1; | 1998 | goto out; |
1839 | } | 1999 | } |
1840 | 2000 | ||
1841 | free_space = btrfs_leaf_free_space(root, left); | 2001 | free_space = btrfs_leaf_free_space(root, left); |
1842 | if (free_space < data_size + sizeof(struct btrfs_item)) { | 2002 | if (free_space < data_size + sizeof(struct btrfs_item)) { |
1843 | free_extent_buffer(left); | 2003 | ret = 1; |
1844 | return 1; | 2004 | goto out; |
1845 | } | 2005 | } |
1846 | 2006 | ||
1847 | if (empty) | 2007 | if (empty) |
@@ -1876,8 +2036,8 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1876 | } | 2036 | } |
1877 | 2037 | ||
1878 | if (push_items == 0) { | 2038 | if (push_items == 0) { |
1879 | free_extent_buffer(left); | 2039 | ret = 1; |
1880 | return 1; | 2040 | goto out; |
1881 | } | 2041 | } |
1882 | if (!empty && push_items == btrfs_header_nritems(right)) | 2042 | if (!empty && push_items == btrfs_header_nritems(right)) |
1883 | WARN_ON(1); | 2043 | WARN_ON(1); |
@@ -1975,15 +2135,23 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1975 | /* then fixup the leaf pointer in the path */ | 2135 | /* then fixup the leaf pointer in the path */ |
1976 | if (path->slots[0] < push_items) { | 2136 | if (path->slots[0] < push_items) { |
1977 | path->slots[0] += old_left_nritems; | 2137 | path->slots[0] += old_left_nritems; |
2138 | if (btrfs_header_nritems(path->nodes[0]) == 0) | ||
2139 | clean_tree_block(trans, root, path->nodes[0]); | ||
2140 | btrfs_tree_unlock(path->nodes[0]); | ||
1978 | free_extent_buffer(path->nodes[0]); | 2141 | free_extent_buffer(path->nodes[0]); |
1979 | path->nodes[0] = left; | 2142 | path->nodes[0] = left; |
1980 | path->slots[1] -= 1; | 2143 | path->slots[1] -= 1; |
1981 | } else { | 2144 | } else { |
2145 | btrfs_tree_unlock(left); | ||
1982 | free_extent_buffer(left); | 2146 | free_extent_buffer(left); |
1983 | path->slots[0] -= push_items; | 2147 | path->slots[0] -= push_items; |
1984 | } | 2148 | } |
1985 | BUG_ON(path->slots[0] < 0); | 2149 | BUG_ON(path->slots[0] < 0); |
1986 | return ret; | 2150 | return ret; |
2151 | out: | ||
2152 | btrfs_tree_unlock(left); | ||
2153 | free_extent_buffer(left); | ||
2154 | return ret; | ||
1987 | } | 2155 | } |
1988 | 2156 | ||
1989 | /* | 2157 | /* |
@@ -2052,7 +2220,7 @@ again: | |||
2052 | 2220 | ||
2053 | btrfs_item_key(l, &disk_key, 0); | 2221 | btrfs_item_key(l, &disk_key, 0); |
2054 | 2222 | ||
2055 | right = __btrfs_alloc_free_block(trans, root, root->leafsize, | 2223 | right = btrfs_alloc_free_block(trans, root, root->leafsize, |
2056 | root->root_key.objectid, | 2224 | root->root_key.objectid, |
2057 | root_gen, disk_key.objectid, 0, | 2225 | root_gen, disk_key.objectid, 0, |
2058 | l->start, 0); | 2226 | l->start, 0); |
@@ -2085,6 +2253,8 @@ again: | |||
2085 | path->slots[1] + 1, 1); | 2253 | path->slots[1] + 1, 1); |
2086 | if (wret) | 2254 | if (wret) |
2087 | ret = wret; | 2255 | ret = wret; |
2256 | |||
2257 | btrfs_tree_unlock(path->nodes[0]); | ||
2088 | free_extent_buffer(path->nodes[0]); | 2258 | free_extent_buffer(path->nodes[0]); |
2089 | path->nodes[0] = right; | 2259 | path->nodes[0] = right; |
2090 | path->slots[0] = 0; | 2260 | path->slots[0] = 0; |
@@ -2111,6 +2281,7 @@ again: | |||
2111 | path->slots[1], 1); | 2281 | path->slots[1], 1); |
2112 | if (wret) | 2282 | if (wret) |
2113 | ret = wret; | 2283 | ret = wret; |
2284 | btrfs_tree_unlock(path->nodes[0]); | ||
2114 | free_extent_buffer(path->nodes[0]); | 2285 | free_extent_buffer(path->nodes[0]); |
2115 | path->nodes[0] = right; | 2286 | path->nodes[0] = right; |
2116 | path->slots[0] = 0; | 2287 | path->slots[0] = 0; |
@@ -2184,12 +2355,15 @@ again: | |||
2184 | BUG_ON(path->slots[0] != slot); | 2355 | BUG_ON(path->slots[0] != slot); |
2185 | 2356 | ||
2186 | if (mid <= slot) { | 2357 | if (mid <= slot) { |
2358 | btrfs_tree_unlock(path->nodes[0]); | ||
2187 | free_extent_buffer(path->nodes[0]); | 2359 | free_extent_buffer(path->nodes[0]); |
2188 | path->nodes[0] = right; | 2360 | path->nodes[0] = right; |
2189 | path->slots[0] -= mid; | 2361 | path->slots[0] -= mid; |
2190 | path->slots[1] += 1; | 2362 | path->slots[1] += 1; |
2191 | } else | 2363 | } else { |
2364 | btrfs_tree_unlock(right); | ||
2192 | free_extent_buffer(right); | 2365 | free_extent_buffer(right); |
2366 | } | ||
2193 | 2367 | ||
2194 | BUG_ON(path->slots[0] < 0); | 2368 | BUG_ON(path->slots[0] < 0); |
2195 | 2369 | ||
@@ -2418,10 +2592,6 @@ int btrfs_insert_empty_items(struct btrfs_trans_handle *trans, | |||
2418 | total_data += data_size[i]; | 2592 | total_data += data_size[i]; |
2419 | } | 2593 | } |
2420 | 2594 | ||
2421 | /* create a root if there isn't one */ | ||
2422 | if (!root->node) | ||
2423 | BUG(); | ||
2424 | |||
2425 | total_size = total_data + (nr - 1) * sizeof(struct btrfs_item); | 2595 | total_size = total_data + (nr - 1) * sizeof(struct btrfs_item); |
2426 | ret = btrfs_search_slot(trans, root, cpu_key, path, total_size, 1); | 2596 | ret = btrfs_search_slot(trans, root, cpu_key, path, total_size, 1); |
2427 | if (ret == 0) { | 2597 | if (ret == 0) { |
@@ -2516,7 +2686,6 @@ int btrfs_insert_empty_items(struct btrfs_trans_handle *trans, | |||
2516 | btrfs_print_leaf(root, leaf); | 2686 | btrfs_print_leaf(root, leaf); |
2517 | BUG(); | 2687 | BUG(); |
2518 | } | 2688 | } |
2519 | |||
2520 | out: | 2689 | out: |
2521 | return ret; | 2690 | return ret; |
2522 | } | 2691 | } |
@@ -2655,7 +2824,6 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
2655 | btrfs_set_header_level(leaf, 0); | 2824 | btrfs_set_header_level(leaf, 0); |
2656 | } else { | 2825 | } else { |
2657 | u64 root_gen = btrfs_header_generation(path->nodes[1]); | 2826 | u64 root_gen = btrfs_header_generation(path->nodes[1]); |
2658 | clean_tree_block(trans, root, leaf); | ||
2659 | wret = del_ptr(trans, root, path, 1, path->slots[1]); | 2827 | wret = del_ptr(trans, root, path, 1, path->slots[1]); |
2660 | if (wret) | 2828 | if (wret) |
2661 | ret = wret; | 2829 | ret = wret; |
@@ -2706,8 +2874,6 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
2706 | root_gen = btrfs_header_generation( | 2874 | root_gen = btrfs_header_generation( |
2707 | path->nodes[1]); | 2875 | path->nodes[1]); |
2708 | 2876 | ||
2709 | clean_tree_block(trans, root, leaf); | ||
2710 | |||
2711 | wret = del_ptr(trans, root, path, 1, slot); | 2877 | wret = del_ptr(trans, root, path, 1, slot); |
2712 | if (wret) | 2878 | if (wret) |
2713 | ret = wret; | 2879 | ret = wret; |
@@ -2720,7 +2886,13 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
2720 | if (wret) | 2886 | if (wret) |
2721 | ret = wret; | 2887 | ret = wret; |
2722 | } else { | 2888 | } else { |
2723 | btrfs_mark_buffer_dirty(leaf); | 2889 | /* if we're still in the path, make sure |
2890 | * we're dirty. Otherwise, one of the | ||
2891 | * push_leaf functions must have already | ||
2892 | * dirtied this buffer | ||
2893 | */ | ||
2894 | if (path->nodes[0] == leaf) | ||
2895 | btrfs_mark_buffer_dirty(leaf); | ||
2724 | free_extent_buffer(leaf); | 2896 | free_extent_buffer(leaf); |
2725 | } | 2897 | } |
2726 | } else { | 2898 | } else { |
@@ -2731,56 +2903,40 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
2731 | } | 2903 | } |
2732 | 2904 | ||
2733 | /* | 2905 | /* |
2734 | * walk up the tree as far as required to find the previous leaf. | 2906 | * search the tree again to find a leaf with lesser keys |
2735 | * returns 0 if it found something or 1 if there are no lesser leaves. | 2907 | * returns 0 if it found something or 1 if there are no lesser leaves. |
2736 | * returns < 0 on io errors. | 2908 | * returns < 0 on io errors. |
2737 | */ | 2909 | */ |
2738 | int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path) | 2910 | int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path) |
2739 | { | 2911 | { |
2740 | int slot; | 2912 | struct btrfs_key key; |
2741 | int level = 1; | 2913 | struct btrfs_disk_key found_key; |
2742 | struct extent_buffer *c; | 2914 | int ret; |
2743 | struct extent_buffer *next = NULL; | ||
2744 | 2915 | ||
2745 | while(level < BTRFS_MAX_LEVEL) { | 2916 | btrfs_item_key_to_cpu(path->nodes[0], &key, 0); |
2746 | if (!path->nodes[level]) | ||
2747 | return 1; | ||
2748 | 2917 | ||
2749 | slot = path->slots[level]; | 2918 | if (key.offset > 0) |
2750 | c = path->nodes[level]; | 2919 | key.offset--; |
2751 | if (slot == 0) { | 2920 | else if (key.type > 0) |
2752 | level++; | 2921 | key.type--; |
2753 | if (level == BTRFS_MAX_LEVEL) | 2922 | else if (key.objectid > 0) |
2754 | return 1; | 2923 | key.objectid--; |
2755 | continue; | 2924 | else |
2756 | } | 2925 | return 1; |
2757 | slot--; | ||
2758 | |||
2759 | if (next) | ||
2760 | free_extent_buffer(next); | ||
2761 | 2926 | ||
2762 | next = read_node_slot(root, c, slot); | 2927 | btrfs_release_path(root, path); |
2763 | break; | 2928 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); |
2764 | } | 2929 | if (ret < 0) |
2765 | path->slots[level] = slot; | 2930 | return ret; |
2766 | while(1) { | 2931 | btrfs_item_key(path->nodes[0], &found_key, 0); |
2767 | level--; | 2932 | ret = comp_keys(&found_key, &key); |
2768 | c = path->nodes[level]; | 2933 | if (ret < 0) |
2769 | free_extent_buffer(c); | 2934 | return 0; |
2770 | slot = btrfs_header_nritems(next); | 2935 | return 1; |
2771 | if (slot != 0) | ||
2772 | slot--; | ||
2773 | path->nodes[level] = next; | ||
2774 | path->slots[level] = slot; | ||
2775 | if (!level) | ||
2776 | break; | ||
2777 | next = read_node_slot(root, next, slot); | ||
2778 | } | ||
2779 | return 0; | ||
2780 | } | 2936 | } |
2781 | 2937 | ||
2782 | /* | 2938 | /* |
2783 | * walk up the tree as far as required to find the next leaf. | 2939 | * search the tree again to find a leaf with greater keys |
2784 | * returns 0 if it found something or 1 if there are no greater leaves. | 2940 | * returns 0 if it found something or 1 if there are no greater leaves. |
2785 | * returns < 0 on io errors. | 2941 | * returns < 0 on io errors. |
2786 | */ | 2942 | */ |
@@ -2790,6 +2946,28 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path) | |||
2790 | int level = 1; | 2946 | int level = 1; |
2791 | struct extent_buffer *c; | 2947 | struct extent_buffer *c; |
2792 | struct extent_buffer *next = NULL; | 2948 | struct extent_buffer *next = NULL; |
2949 | struct btrfs_key key; | ||
2950 | u32 nritems; | ||
2951 | int ret; | ||
2952 | |||
2953 | nritems = btrfs_header_nritems(path->nodes[0]); | ||
2954 | if (nritems == 0) { | ||
2955 | return 1; | ||
2956 | } | ||
2957 | |||
2958 | btrfs_item_key_to_cpu(path->nodes[0], &key, nritems - 1); | ||
2959 | |||
2960 | path->keep_locks = 1; | ||
2961 | btrfs_release_path(root, path); | ||
2962 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | ||
2963 | path->keep_locks = 0; | ||
2964 | |||
2965 | if (ret < 0) | ||
2966 | return ret; | ||
2967 | |||
2968 | if (path->slots[0] < nritems - 1) { | ||
2969 | goto done; | ||
2970 | } | ||
2793 | 2971 | ||
2794 | while(level < BTRFS_MAX_LEVEL) { | 2972 | while(level < BTRFS_MAX_LEVEL) { |
2795 | if (!path->nodes[level]) | 2973 | if (!path->nodes[level]) |
@@ -2799,33 +2977,45 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path) | |||
2799 | c = path->nodes[level]; | 2977 | c = path->nodes[level]; |
2800 | if (slot >= btrfs_header_nritems(c)) { | 2978 | if (slot >= btrfs_header_nritems(c)) { |
2801 | level++; | 2979 | level++; |
2802 | if (level == BTRFS_MAX_LEVEL) | 2980 | if (level == BTRFS_MAX_LEVEL) { |
2803 | return 1; | 2981 | return 1; |
2982 | } | ||
2804 | continue; | 2983 | continue; |
2805 | } | 2984 | } |
2806 | 2985 | ||
2807 | if (next) | 2986 | if (next) { |
2987 | btrfs_tree_unlock(next); | ||
2808 | free_extent_buffer(next); | 2988 | free_extent_buffer(next); |
2989 | } | ||
2809 | 2990 | ||
2810 | if (path->reada) | 2991 | if (level == 1 && path->locks[1] && path->reada) |
2811 | reada_for_search(root, path, level, slot, 0); | 2992 | reada_for_search(root, path, level, slot, 0); |
2812 | 2993 | ||
2813 | next = read_node_slot(root, c, slot); | 2994 | next = read_node_slot(root, c, slot); |
2995 | if (!path->skip_locking) | ||
2996 | btrfs_tree_lock(next); | ||
2814 | break; | 2997 | break; |
2815 | } | 2998 | } |
2816 | path->slots[level] = slot; | 2999 | path->slots[level] = slot; |
2817 | while(1) { | 3000 | while(1) { |
2818 | level--; | 3001 | level--; |
2819 | c = path->nodes[level]; | 3002 | c = path->nodes[level]; |
3003 | if (path->locks[level]) | ||
3004 | btrfs_tree_unlock(c); | ||
2820 | free_extent_buffer(c); | 3005 | free_extent_buffer(c); |
2821 | path->nodes[level] = next; | 3006 | path->nodes[level] = next; |
2822 | path->slots[level] = 0; | 3007 | path->slots[level] = 0; |
3008 | path->locks[level] = 1; | ||
2823 | if (!level) | 3009 | if (!level) |
2824 | break; | 3010 | break; |
2825 | if (path->reada) | 3011 | if (level == 1 && path->locks[1] && path->reada) |
2826 | reada_for_search(root, path, level, 0, 0); | 3012 | reada_for_search(root, path, level, slot, 0); |
2827 | next = read_node_slot(root, next, 0); | 3013 | next = read_node_slot(root, next, 0); |
3014 | if (!path->skip_locking) | ||
3015 | btrfs_tree_lock(next); | ||
2828 | } | 3016 | } |
3017 | done: | ||
3018 | unlock_up(path, 0, 1); | ||
2829 | return 0; | 3019 | return 0; |
2830 | } | 3020 | } |
2831 | 3021 | ||
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index dcea9d706d9b..50891b39f366 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -330,8 +330,13 @@ struct btrfs_node { | |||
330 | struct btrfs_path { | 330 | struct btrfs_path { |
331 | struct extent_buffer *nodes[BTRFS_MAX_LEVEL]; | 331 | struct extent_buffer *nodes[BTRFS_MAX_LEVEL]; |
332 | int slots[BTRFS_MAX_LEVEL]; | 332 | int slots[BTRFS_MAX_LEVEL]; |
333 | /* if there is real range locking, this locks field will change */ | ||
334 | int locks[BTRFS_MAX_LEVEL]; | ||
333 | int reada; | 335 | int reada; |
336 | /* keep some upper locks as we walk down */ | ||
337 | int keep_locks; | ||
334 | int lowest_level; | 338 | int lowest_level; |
339 | int skip_locking; | ||
335 | }; | 340 | }; |
336 | 341 | ||
337 | /* | 342 | /* |
@@ -515,6 +520,8 @@ struct btrfs_fs_info { | |||
515 | spinlock_t hash_lock; | 520 | spinlock_t hash_lock; |
516 | struct mutex trans_mutex; | 521 | struct mutex trans_mutex; |
517 | struct mutex fs_mutex; | 522 | struct mutex fs_mutex; |
523 | struct mutex alloc_mutex; | ||
524 | struct mutex chunk_mutex; | ||
518 | struct list_head trans_list; | 525 | struct list_head trans_list; |
519 | struct list_head hashers; | 526 | struct list_head hashers; |
520 | struct list_head dead_roots; | 527 | struct list_head dead_roots; |
@@ -576,6 +583,10 @@ struct btrfs_fs_info { | |||
576 | */ | 583 | */ |
577 | struct btrfs_root { | 584 | struct btrfs_root { |
578 | struct extent_buffer *node; | 585 | struct extent_buffer *node; |
586 | |||
587 | /* the node lock is held while changing the node pointer */ | ||
588 | spinlock_t node_lock; | ||
589 | |||
579 | struct extent_buffer *commit_root; | 590 | struct extent_buffer *commit_root; |
580 | struct btrfs_root_item root_item; | 591 | struct btrfs_root_item root_item; |
581 | struct btrfs_key root_key; | 592 | struct btrfs_key root_key; |
@@ -1353,13 +1364,7 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root, | |||
1353 | struct btrfs_block_group_cache | 1364 | struct btrfs_block_group_cache |
1354 | *hint, u64 search_start, | 1365 | *hint, u64 search_start, |
1355 | int data, int owner); | 1366 | int data, int owner); |
1356 | int btrfs_inc_root_ref(struct btrfs_trans_handle *trans, | ||
1357 | struct btrfs_root *root, u64 owner_objectid); | ||
1358 | struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, | 1367 | struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, |
1359 | struct btrfs_root *root, u32 size, | ||
1360 | u64 root_objectid, | ||
1361 | u64 hint, u64 empty_size); | ||
1362 | struct extent_buffer *__btrfs_alloc_free_block(struct btrfs_trans_handle *trans, | ||
1363 | struct btrfs_root *root, | 1368 | struct btrfs_root *root, |
1364 | u32 blocksize, | 1369 | u32 blocksize, |
1365 | u64 root_objectid, | 1370 | u64 root_objectid, |
@@ -1368,8 +1373,6 @@ struct extent_buffer *__btrfs_alloc_free_block(struct btrfs_trans_handle *trans, | |||
1368 | int level, | 1373 | int level, |
1369 | u64 hint, | 1374 | u64 hint, |
1370 | u64 empty_size); | 1375 | u64 empty_size); |
1371 | int btrfs_grow_extent_tree(struct btrfs_trans_handle *trans, | ||
1372 | struct btrfs_root *root, u64 new_size); | ||
1373 | int btrfs_shrink_extent_tree(struct btrfs_root *root, u64 new_size); | 1376 | int btrfs_shrink_extent_tree(struct btrfs_root *root, u64 new_size); |
1374 | int btrfs_insert_extent_backref(struct btrfs_trans_handle *trans, | 1377 | int btrfs_insert_extent_backref(struct btrfs_trans_handle *trans, |
1375 | struct btrfs_root *root, | 1378 | struct btrfs_root *root, |
@@ -1409,6 +1412,10 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans, | |||
1409 | int btrfs_previous_item(struct btrfs_root *root, | 1412 | int btrfs_previous_item(struct btrfs_root *root, |
1410 | struct btrfs_path *path, u64 min_objectid, | 1413 | struct btrfs_path *path, u64 min_objectid, |
1411 | int type); | 1414 | int type); |
1415 | |||
1416 | struct extent_buffer *btrfs_root_node(struct btrfs_root *root); | ||
1417 | struct extent_buffer *btrfs_lock_root_node(struct btrfs_root *root); | ||
1418 | |||
1412 | int btrfs_cow_block(struct btrfs_trans_handle *trans, | 1419 | int btrfs_cow_block(struct btrfs_trans_handle *trans, |
1413 | struct btrfs_root *root, struct extent_buffer *buf, | 1420 | struct btrfs_root *root, struct extent_buffer *buf, |
1414 | struct extent_buffer *parent, int parent_slot, | 1421 | struct extent_buffer *parent, int parent_slot, |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index e5c758e306d5..fe40bdd984ff 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include "volumes.h" | 32 | #include "volumes.h" |
33 | #include "print-tree.h" | 33 | #include "print-tree.h" |
34 | #include "async-thread.h" | 34 | #include "async-thread.h" |
35 | #include "locking.h" | ||
35 | 36 | ||
36 | #if 0 | 37 | #if 0 |
37 | static int check_tree_block(struct btrfs_root *root, struct extent_buffer *buf) | 38 | static int check_tree_block(struct btrfs_root *root, struct extent_buffer *buf) |
@@ -681,9 +682,11 @@ int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
681 | { | 682 | { |
682 | struct inode *btree_inode = root->fs_info->btree_inode; | 683 | struct inode *btree_inode = root->fs_info->btree_inode; |
683 | if (btrfs_header_generation(buf) == | 684 | if (btrfs_header_generation(buf) == |
684 | root->fs_info->running_transaction->transid) | 685 | root->fs_info->running_transaction->transid) { |
686 | WARN_ON(!btrfs_tree_locked(buf)); | ||
685 | clear_extent_buffer_dirty(&BTRFS_I(btree_inode)->io_tree, | 687 | clear_extent_buffer_dirty(&BTRFS_I(btree_inode)->io_tree, |
686 | buf); | 688 | buf); |
689 | } | ||
687 | return 0; | 690 | return 0; |
688 | } | 691 | } |
689 | 692 | ||
@@ -720,6 +723,7 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize, | |||
720 | root->in_sysfs = 0; | 723 | root->in_sysfs = 0; |
721 | 724 | ||
722 | INIT_LIST_HEAD(&root->dirty_list); | 725 | INIT_LIST_HEAD(&root->dirty_list); |
726 | spin_lock_init(&root->node_lock); | ||
723 | memset(&root->root_key, 0, sizeof(root->root_key)); | 727 | memset(&root->root_key, 0, sizeof(root->root_key)); |
724 | memset(&root->root_item, 0, sizeof(root->root_item)); | 728 | memset(&root->root_item, 0, sizeof(root->root_item)); |
725 | memset(&root->defrag_progress, 0, sizeof(root->defrag_progress)); | 729 | memset(&root->defrag_progress, 0, sizeof(root->defrag_progress)); |
@@ -1196,6 +1200,8 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1196 | 1200 | ||
1197 | mutex_init(&fs_info->trans_mutex); | 1201 | mutex_init(&fs_info->trans_mutex); |
1198 | mutex_init(&fs_info->fs_mutex); | 1202 | mutex_init(&fs_info->fs_mutex); |
1203 | mutex_init(&fs_info->alloc_mutex); | ||
1204 | mutex_init(&fs_info->chunk_mutex); | ||
1199 | 1205 | ||
1200 | #if 0 | 1206 | #if 0 |
1201 | ret = add_hasher(fs_info, "crc32c"); | 1207 | ret = add_hasher(fs_info, "crc32c"); |
@@ -1274,7 +1280,9 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1274 | 1280 | ||
1275 | mutex_lock(&fs_info->fs_mutex); | 1281 | mutex_lock(&fs_info->fs_mutex); |
1276 | 1282 | ||
1283 | mutex_lock(&fs_info->chunk_mutex); | ||
1277 | ret = btrfs_read_sys_array(tree_root); | 1284 | ret = btrfs_read_sys_array(tree_root); |
1285 | mutex_unlock(&fs_info->chunk_mutex); | ||
1278 | if (ret) { | 1286 | if (ret) { |
1279 | printk("btrfs: failed to read the system array on %s\n", | 1287 | printk("btrfs: failed to read the system array on %s\n", |
1280 | sb->s_id); | 1288 | sb->s_id); |
@@ -1296,7 +1304,9 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1296 | (unsigned long)btrfs_header_chunk_tree_uuid(chunk_root->node), | 1304 | (unsigned long)btrfs_header_chunk_tree_uuid(chunk_root->node), |
1297 | BTRFS_UUID_SIZE); | 1305 | BTRFS_UUID_SIZE); |
1298 | 1306 | ||
1307 | mutex_lock(&fs_info->chunk_mutex); | ||
1299 | ret = btrfs_read_chunk_tree(chunk_root); | 1308 | ret = btrfs_read_chunk_tree(chunk_root); |
1309 | mutex_unlock(&fs_info->chunk_mutex); | ||
1300 | BUG_ON(ret); | 1310 | BUG_ON(ret); |
1301 | 1311 | ||
1302 | btrfs_close_extra_devices(fs_devices); | 1312 | btrfs_close_extra_devices(fs_devices); |
@@ -1654,6 +1664,7 @@ void btrfs_mark_buffer_dirty(struct extent_buffer *buf) | |||
1654 | u64 transid = btrfs_header_generation(buf); | 1664 | u64 transid = btrfs_header_generation(buf); |
1655 | struct inode *btree_inode = root->fs_info->btree_inode; | 1665 | struct inode *btree_inode = root->fs_info->btree_inode; |
1656 | 1666 | ||
1667 | WARN_ON(!btrfs_tree_locked(buf)); | ||
1657 | if (transid != root->fs_info->generation) { | 1668 | if (transid != root->fs_info->generation) { |
1658 | printk(KERN_CRIT "transid mismatch buffer %llu, found %Lu running %Lu\n", | 1669 | printk(KERN_CRIT "transid mismatch buffer %llu, found %Lu running %Lu\n", |
1659 | (unsigned long long)buf->start, | 1670 | (unsigned long long)buf->start, |
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 | } |
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 17c508a941eb..bd15cdcaba95 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
@@ -2889,7 +2889,6 @@ int clear_extent_buffer_dirty(struct extent_io_tree *tree, | |||
2889 | 2889 | ||
2890 | for (i = 0; i < num_pages; i++) { | 2890 | for (i = 0; i < num_pages; i++) { |
2891 | page = extent_buffer_page(eb, i); | 2891 | page = extent_buffer_page(eb, i); |
2892 | lock_page(page); | ||
2893 | if (i == 0) | 2892 | if (i == 0) |
2894 | set_page_extent_head(page, eb->len); | 2893 | set_page_extent_head(page, eb->len); |
2895 | else | 2894 | else |
@@ -2907,7 +2906,6 @@ int clear_extent_buffer_dirty(struct extent_io_tree *tree, | |||
2907 | end = start + PAGE_CACHE_SIZE - 1; | 2906 | end = start + PAGE_CACHE_SIZE - 1; |
2908 | if (test_range_bit(tree, start, end, | 2907 | if (test_range_bit(tree, start, end, |
2909 | EXTENT_DIRTY, 0)) { | 2908 | EXTENT_DIRTY, 0)) { |
2910 | unlock_page(page); | ||
2911 | continue; | 2909 | continue; |
2912 | } | 2910 | } |
2913 | } | 2911 | } |
@@ -2919,7 +2917,6 @@ int clear_extent_buffer_dirty(struct extent_io_tree *tree, | |||
2919 | PAGECACHE_TAG_DIRTY); | 2917 | PAGECACHE_TAG_DIRTY); |
2920 | } | 2918 | } |
2921 | read_unlock_irq(&page->mapping->tree_lock); | 2919 | read_unlock_irq(&page->mapping->tree_lock); |
2922 | unlock_page(page); | ||
2923 | } | 2920 | } |
2924 | return 0; | 2921 | return 0; |
2925 | } | 2922 | } |
@@ -2948,17 +2945,12 @@ int set_extent_buffer_dirty(struct extent_io_tree *tree, | |||
2948 | * on us if the page isn't already dirty. | 2945 | * on us if the page isn't already dirty. |
2949 | */ | 2946 | */ |
2950 | if (i == 0) { | 2947 | if (i == 0) { |
2951 | lock_page(page); | ||
2952 | set_page_extent_head(page, eb->len); | 2948 | set_page_extent_head(page, eb->len); |
2953 | } else if (PagePrivate(page) && | 2949 | } else if (PagePrivate(page) && |
2954 | page->private != EXTENT_PAGE_PRIVATE) { | 2950 | page->private != EXTENT_PAGE_PRIVATE) { |
2955 | lock_page(page); | ||
2956 | set_page_extent_mapped(page); | 2951 | set_page_extent_mapped(page); |
2957 | unlock_page(page); | ||
2958 | } | 2952 | } |
2959 | __set_page_dirty_nobuffers(extent_buffer_page(eb, i)); | 2953 | __set_page_dirty_nobuffers(extent_buffer_page(eb, i)); |
2960 | if (i == 0) | ||
2961 | unlock_page(page); | ||
2962 | } | 2954 | } |
2963 | return set_extent_dirty(tree, eb->start, | 2955 | return set_extent_dirty(tree, eb->start, |
2964 | eb->start + eb->len - 1, GFP_NOFS); | 2956 | eb->start + eb->len - 1, GFP_NOFS); |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 0c79346fd2c9..61bd8953a683 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -115,6 +115,7 @@ static int cow_file_range(struct inode *inode, u64 start, u64 end) | |||
115 | trans = btrfs_start_transaction(root, 1); | 115 | trans = btrfs_start_transaction(root, 1); |
116 | BUG_ON(!trans); | 116 | BUG_ON(!trans); |
117 | btrfs_set_trans_block_group(trans, inode); | 117 | btrfs_set_trans_block_group(trans, inode); |
118 | mutex_unlock(&root->fs_info->fs_mutex); | ||
118 | 119 | ||
119 | num_bytes = (end - start + blocksize) & ~(blocksize - 1); | 120 | num_bytes = (end - start + blocksize) & ~(blocksize - 1); |
120 | num_bytes = max(blocksize, num_bytes); | 121 | num_bytes = max(blocksize, num_bytes); |
@@ -159,6 +160,7 @@ static int cow_file_range(struct inode *inode, u64 start, u64 end) | |||
159 | btrfs_add_ordered_inode(inode); | 160 | btrfs_add_ordered_inode(inode); |
160 | btrfs_update_inode(trans, root, inode); | 161 | btrfs_update_inode(trans, root, inode); |
161 | out: | 162 | out: |
163 | mutex_lock(&root->fs_info->fs_mutex); | ||
162 | btrfs_end_transaction(trans, root); | 164 | btrfs_end_transaction(trans, root); |
163 | return ret; | 165 | return ret; |
164 | } | 166 | } |
@@ -349,10 +351,12 @@ int __btrfs_submit_bio_hook(struct inode *inode, int rw, struct bio *bio, | |||
349 | 351 | ||
350 | mutex_lock(&root->fs_info->fs_mutex); | 352 | mutex_lock(&root->fs_info->fs_mutex); |
351 | trans = btrfs_start_transaction(root, 1); | 353 | trans = btrfs_start_transaction(root, 1); |
354 | mutex_unlock(&root->fs_info->fs_mutex); | ||
352 | 355 | ||
353 | btrfs_set_trans_block_group(trans, inode); | 356 | btrfs_set_trans_block_group(trans, inode); |
354 | btrfs_csum_file_blocks(trans, root, inode, bio, sums); | 357 | btrfs_csum_file_blocks(trans, root, inode, bio, sums); |
355 | 358 | ||
359 | mutex_lock(&root->fs_info->fs_mutex); | ||
356 | ret = btrfs_end_transaction(trans, root); | 360 | ret = btrfs_end_transaction(trans, root); |
357 | BUG_ON(ret); | 361 | BUG_ON(ret); |
358 | mutex_unlock(&root->fs_info->fs_mutex); | 362 | mutex_unlock(&root->fs_info->fs_mutex); |
@@ -807,6 +811,7 @@ static int btrfs_unlink_trans(struct btrfs_trans_handle *trans, | |||
807 | goto err; | 811 | goto err; |
808 | } | 812 | } |
809 | ret = btrfs_delete_one_dir_name(trans, root, path, di); | 813 | ret = btrfs_delete_one_dir_name(trans, root, path, di); |
814 | btrfs_release_path(root, path); | ||
810 | 815 | ||
811 | dentry->d_inode->i_ctime = dir->i_ctime; | 816 | dentry->d_inode->i_ctime = dir->i_ctime; |
812 | ret = btrfs_del_inode_ref(trans, root, name, name_len, | 817 | ret = btrfs_del_inode_ref(trans, root, name, name_len, |
@@ -881,8 +886,9 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
881 | struct btrfs_trans_handle *trans; | 886 | struct btrfs_trans_handle *trans; |
882 | unsigned long nr = 0; | 887 | unsigned long nr = 0; |
883 | 888 | ||
884 | if (inode->i_size > BTRFS_EMPTY_DIR_SIZE) | 889 | if (inode->i_size > BTRFS_EMPTY_DIR_SIZE) { |
885 | return -ENOTEMPTY; | 890 | return -ENOTEMPTY; |
891 | } | ||
886 | 892 | ||
887 | mutex_lock(&root->fs_info->fs_mutex); | 893 | mutex_lock(&root->fs_info->fs_mutex); |
888 | ret = btrfs_check_free_space(root, 1, 1); | 894 | ret = btrfs_check_free_space(root, 1, 1); |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 6fb455802759..3fbf74e93dba 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include "ioctl.h" | 43 | #include "ioctl.h" |
44 | #include "print-tree.h" | 44 | #include "print-tree.h" |
45 | #include "volumes.h" | 45 | #include "volumes.h" |
46 | #include "locking.h" | ||
46 | 47 | ||
47 | 48 | ||
48 | 49 | ||
@@ -75,9 +76,9 @@ static noinline int create_subvol(struct btrfs_root *root, char *name, | |||
75 | if (ret) | 76 | if (ret) |
76 | goto fail; | 77 | goto fail; |
77 | 78 | ||
78 | leaf = __btrfs_alloc_free_block(trans, root, root->leafsize, | 79 | leaf = btrfs_alloc_free_block(trans, root, root->leafsize, |
79 | objectid, trans->transid, 0, 0, | 80 | objectid, trans->transid, 0, 0, |
80 | 0, 0); | 81 | 0, 0); |
81 | if (IS_ERR(leaf)) | 82 | if (IS_ERR(leaf)) |
82 | return PTR_ERR(leaf); | 83 | return PTR_ERR(leaf); |
83 | 84 | ||
@@ -108,6 +109,7 @@ static noinline int create_subvol(struct btrfs_root *root, char *name, | |||
108 | memset(&root_item.drop_progress, 0, sizeof(root_item.drop_progress)); | 109 | memset(&root_item.drop_progress, 0, sizeof(root_item.drop_progress)); |
109 | root_item.drop_level = 0; | 110 | root_item.drop_level = 0; |
110 | 111 | ||
112 | btrfs_tree_unlock(leaf); | ||
111 | free_extent_buffer(leaf); | 113 | free_extent_buffer(leaf); |
112 | leaf = NULL; | 114 | leaf = NULL; |
113 | 115 | ||
diff --git a/fs/btrfs/locking.c b/fs/btrfs/locking.c new file mode 100644 index 000000000000..80813a307b4b --- /dev/null +++ b/fs/btrfs/locking.c | |||
@@ -0,0 +1,50 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2008 Oracle. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public | ||
6 | * License v2 as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
11 | * General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public | ||
14 | * License along with this program; if not, write to the | ||
15 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
16 | * Boston, MA 021110-1307, USA. | ||
17 | */ | ||
18 | #include <linux/sched.h> | ||
19 | #include <linux/gfp.h> | ||
20 | #include <linux/pagemap.h> | ||
21 | #include <linux/spinlock.h> | ||
22 | #include <linux/page-flags.h> | ||
23 | #include <linux/bug.h> | ||
24 | #include "ctree.h" | ||
25 | #include "extent_io.h" | ||
26 | #include "locking.h" | ||
27 | |||
28 | int btrfs_tree_lock(struct extent_buffer *eb) | ||
29 | { | ||
30 | lock_page(eb->first_page); | ||
31 | return 0; | ||
32 | } | ||
33 | |||
34 | int btrfs_try_tree_lock(struct extent_buffer *eb) | ||
35 | { | ||
36 | return TestSetPageLocked(eb->first_page); | ||
37 | } | ||
38 | |||
39 | int btrfs_tree_unlock(struct extent_buffer *eb) | ||
40 | { | ||
41 | WARN_ON(!PageLocked(eb->first_page)); | ||
42 | unlock_page(eb->first_page); | ||
43 | return 0; | ||
44 | } | ||
45 | |||
46 | int btrfs_tree_locked(struct extent_buffer *eb) | ||
47 | { | ||
48 | return PageLocked(eb->first_page); | ||
49 | } | ||
50 | |||
diff --git a/fs/btrfs/locking.h b/fs/btrfs/locking.h new file mode 100644 index 000000000000..2dab96d8280e --- /dev/null +++ b/fs/btrfs/locking.h | |||
@@ -0,0 +1,26 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2008 Oracle. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public | ||
6 | * License v2 as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
11 | * General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public | ||
14 | * License along with this program; if not, write to the | ||
15 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
16 | * Boston, MA 021110-1307, USA. | ||
17 | */ | ||
18 | |||
19 | #ifndef __BTRFS_LOCKING_ | ||
20 | #define __BTRFS_LOCKING_ | ||
21 | |||
22 | int btrfs_tree_lock(struct extent_buffer *eb); | ||
23 | int btrfs_tree_unlock(struct extent_buffer *eb); | ||
24 | int btrfs_tree_locked(struct extent_buffer *eb); | ||
25 | int btrfs_try_tree_lock(struct extent_buffer *eb); | ||
26 | #endif | ||
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index f04684f7fea3..1ed433a71493 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include "ctree.h" | 23 | #include "ctree.h" |
24 | #include "disk-io.h" | 24 | #include "disk-io.h" |
25 | #include "transaction.h" | 25 | #include "transaction.h" |
26 | #include "locking.h" | ||
26 | 27 | ||
27 | static int total_trans = 0; | 28 | static int total_trans = 0; |
28 | extern struct kmem_cache *btrfs_trans_handle_cachep; | 29 | extern struct kmem_cache *btrfs_trans_handle_cachep; |
@@ -96,8 +97,7 @@ static noinline int record_root_in_trans(struct btrfs_root *root) | |||
96 | radix_tree_tag_set(&root->fs_info->fs_roots_radix, | 97 | radix_tree_tag_set(&root->fs_info->fs_roots_radix, |
97 | (unsigned long)root->root_key.objectid, | 98 | (unsigned long)root->root_key.objectid, |
98 | BTRFS_ROOT_DEFRAG_TAG); | 99 | BTRFS_ROOT_DEFRAG_TAG); |
99 | root->commit_root = root->node; | 100 | root->commit_root = btrfs_root_node(root); |
100 | extent_buffer_get(root->node); | ||
101 | } else { | 101 | } else { |
102 | WARN_ON(1); | 102 | WARN_ON(1); |
103 | } | 103 | } |
@@ -559,6 +559,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
559 | struct btrfs_root *tree_root = fs_info->tree_root; | 559 | struct btrfs_root *tree_root = fs_info->tree_root; |
560 | struct btrfs_root *root = pending->root; | 560 | struct btrfs_root *root = pending->root; |
561 | struct extent_buffer *tmp; | 561 | struct extent_buffer *tmp; |
562 | struct extent_buffer *old; | ||
562 | int ret; | 563 | int ret; |
563 | int namelen; | 564 | int namelen; |
564 | u64 objectid; | 565 | u64 objectid; |
@@ -578,16 +579,18 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
578 | key.offset = 1; | 579 | key.offset = 1; |
579 | btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY); | 580 | btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY); |
580 | 581 | ||
581 | extent_buffer_get(root->node); | 582 | old = btrfs_lock_root_node(root); |
582 | btrfs_cow_block(trans, root, root->node, NULL, 0, &tmp); | 583 | btrfs_cow_block(trans, root, old, NULL, 0, &old); |
583 | free_extent_buffer(tmp); | ||
584 | 584 | ||
585 | btrfs_copy_root(trans, root, root->node, &tmp, objectid); | 585 | btrfs_copy_root(trans, root, old, &tmp, objectid); |
586 | btrfs_tree_unlock(old); | ||
587 | free_extent_buffer(old); | ||
586 | 588 | ||
587 | btrfs_set_root_bytenr(new_root_item, tmp->start); | 589 | btrfs_set_root_bytenr(new_root_item, tmp->start); |
588 | btrfs_set_root_level(new_root_item, btrfs_header_level(tmp)); | 590 | btrfs_set_root_level(new_root_item, btrfs_header_level(tmp)); |
589 | ret = btrfs_insert_root(trans, root->fs_info->tree_root, &key, | 591 | ret = btrfs_insert_root(trans, root->fs_info->tree_root, &key, |
590 | new_root_item); | 592 | new_root_item); |
593 | btrfs_tree_unlock(tmp); | ||
591 | free_extent_buffer(tmp); | 594 | free_extent_buffer(tmp); |
592 | if (ret) | 595 | if (ret) |
593 | goto fail; | 596 | goto fail; |
diff --git a/fs/btrfs/tree-defrag.c b/fs/btrfs/tree-defrag.c index 155961c7b4d5..fab851d85383 100644 --- a/fs/btrfs/tree-defrag.c +++ b/fs/btrfs/tree-defrag.c | |||
@@ -181,6 +181,8 @@ int btrfs_defrag_leaves(struct btrfs_trans_handle *trans, | |||
181 | if (root->fs_info->extent_root == root) | 181 | if (root->fs_info->extent_root == root) |
182 | is_extent = 1; | 182 | is_extent = 1; |
183 | 183 | ||
184 | goto out; | ||
185 | |||
184 | if (root->ref_cows == 0 && !is_extent) | 186 | if (root->ref_cows == 0 && !is_extent) |
185 | goto out; | 187 | goto out; |
186 | 188 | ||