diff options
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r-- | fs/btrfs/extent-tree.c | 69 |
1 files changed, 50 insertions, 19 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index a421c32c6cfe..8933d15a240f 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -56,9 +56,6 @@ static int __btrfs_alloc_reserved_extent(struct btrfs_trans_handle *trans, | |||
56 | int ref_mod); | 56 | int ref_mod); |
57 | static int update_reserved_extents(struct btrfs_root *root, | 57 | static int update_reserved_extents(struct btrfs_root *root, |
58 | u64 bytenr, u64 num, int reserve); | 58 | u64 bytenr, u64 num, int reserve); |
59 | static int pin_down_bytes(struct btrfs_trans_handle *trans, | ||
60 | struct btrfs_root *root, | ||
61 | u64 bytenr, u64 num_bytes, int is_data); | ||
62 | static int update_block_group(struct btrfs_trans_handle *trans, | 59 | static int update_block_group(struct btrfs_trans_handle *trans, |
63 | struct btrfs_root *root, | 60 | struct btrfs_root *root, |
64 | u64 bytenr, u64 num_bytes, int alloc, | 61 | u64 bytenr, u64 num_bytes, int alloc, |
@@ -618,6 +615,7 @@ static noinline int insert_extent_backref(struct btrfs_trans_handle *trans, | |||
618 | } else { | 615 | } else { |
619 | goto out; | 616 | goto out; |
620 | } | 617 | } |
618 | btrfs_unlock_up_safe(path, 1); | ||
621 | btrfs_mark_buffer_dirty(path->nodes[0]); | 619 | btrfs_mark_buffer_dirty(path->nodes[0]); |
622 | out: | 620 | out: |
623 | btrfs_release_path(root, path); | 621 | btrfs_release_path(root, path); |
@@ -760,6 +758,7 @@ static noinline_for_stack int add_extent_ref(struct btrfs_trans_handle *trans, | |||
760 | return -ENOMEM; | 758 | return -ENOMEM; |
761 | 759 | ||
762 | path->reada = 1; | 760 | path->reada = 1; |
761 | path->leave_spinning = 1; | ||
763 | key.objectid = bytenr; | 762 | key.objectid = bytenr; |
764 | key.type = BTRFS_EXTENT_ITEM_KEY; | 763 | key.type = BTRFS_EXTENT_ITEM_KEY; |
765 | key.offset = num_bytes; | 764 | key.offset = num_bytes; |
@@ -767,8 +766,10 @@ static noinline_for_stack int add_extent_ref(struct btrfs_trans_handle *trans, | |||
767 | /* first find the extent item and update its reference count */ | 766 | /* first find the extent item and update its reference count */ |
768 | ret = btrfs_search_slot(trans, root->fs_info->extent_root, &key, | 767 | ret = btrfs_search_slot(trans, root->fs_info->extent_root, &key, |
769 | path, 0, 1); | 768 | path, 0, 1); |
770 | if (ret < 0) | 769 | if (ret < 0) { |
770 | btrfs_set_path_blocking(path); | ||
771 | return ret; | 771 | return ret; |
772 | } | ||
772 | 773 | ||
773 | if (ret > 0) { | 774 | if (ret > 0) { |
774 | WARN_ON(1); | 775 | WARN_ON(1); |
@@ -791,11 +792,15 @@ static noinline_for_stack int add_extent_ref(struct btrfs_trans_handle *trans, | |||
791 | 792 | ||
792 | refs = btrfs_extent_refs(l, item); | 793 | refs = btrfs_extent_refs(l, item); |
793 | btrfs_set_extent_refs(l, item, refs + refs_to_add); | 794 | btrfs_set_extent_refs(l, item, refs + refs_to_add); |
795 | btrfs_unlock_up_safe(path, 1); | ||
796 | |||
794 | btrfs_mark_buffer_dirty(path->nodes[0]); | 797 | btrfs_mark_buffer_dirty(path->nodes[0]); |
795 | 798 | ||
796 | btrfs_release_path(root->fs_info->extent_root, path); | 799 | btrfs_release_path(root->fs_info->extent_root, path); |
797 | 800 | ||
798 | path->reada = 1; | 801 | path->reada = 1; |
802 | path->leave_spinning = 1; | ||
803 | |||
799 | /* now insert the actual backref */ | 804 | /* now insert the actual backref */ |
800 | ret = insert_extent_backref(trans, root->fs_info->extent_root, | 805 | ret = insert_extent_backref(trans, root->fs_info->extent_root, |
801 | path, bytenr, parent, | 806 | path, bytenr, parent, |
@@ -2050,6 +2055,8 @@ int btrfs_update_pinned_extents(struct btrfs_root *root, | |||
2050 | clear_extent_dirty(&fs_info->pinned_extents, | 2055 | clear_extent_dirty(&fs_info->pinned_extents, |
2051 | bytenr, bytenr + num - 1, GFP_NOFS); | 2056 | bytenr, bytenr + num - 1, GFP_NOFS); |
2052 | } | 2057 | } |
2058 | mutex_unlock(&root->fs_info->pinned_mutex); | ||
2059 | |||
2053 | while (num > 0) { | 2060 | while (num > 0) { |
2054 | cache = btrfs_lookup_block_group(fs_info, bytenr); | 2061 | cache = btrfs_lookup_block_group(fs_info, bytenr); |
2055 | BUG_ON(!cache); | 2062 | BUG_ON(!cache); |
@@ -2141,8 +2148,8 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, | |||
2141 | u64 end; | 2148 | u64 end; |
2142 | int ret; | 2149 | int ret; |
2143 | 2150 | ||
2144 | mutex_lock(&root->fs_info->pinned_mutex); | ||
2145 | while (1) { | 2151 | while (1) { |
2152 | mutex_lock(&root->fs_info->pinned_mutex); | ||
2146 | ret = find_first_extent_bit(unpin, 0, &start, &end, | 2153 | ret = find_first_extent_bit(unpin, 0, &start, &end, |
2147 | EXTENT_DIRTY); | 2154 | EXTENT_DIRTY); |
2148 | if (ret) | 2155 | if (ret) |
@@ -2150,14 +2157,11 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, | |||
2150 | 2157 | ||
2151 | ret = btrfs_discard_extent(root, start, end + 1 - start); | 2158 | ret = btrfs_discard_extent(root, start, end + 1 - start); |
2152 | 2159 | ||
2160 | /* unlocks the pinned mutex */ | ||
2153 | btrfs_update_pinned_extents(root, start, end + 1 - start, 0); | 2161 | btrfs_update_pinned_extents(root, start, end + 1 - start, 0); |
2154 | clear_extent_dirty(unpin, start, end, GFP_NOFS); | 2162 | clear_extent_dirty(unpin, start, end, GFP_NOFS); |
2155 | 2163 | ||
2156 | if (need_resched()) { | 2164 | cond_resched(); |
2157 | mutex_unlock(&root->fs_info->pinned_mutex); | ||
2158 | cond_resched(); | ||
2159 | mutex_lock(&root->fs_info->pinned_mutex); | ||
2160 | } | ||
2161 | } | 2165 | } |
2162 | mutex_unlock(&root->fs_info->pinned_mutex); | 2166 | mutex_unlock(&root->fs_info->pinned_mutex); |
2163 | return ret; | 2167 | return ret; |
@@ -2165,7 +2169,9 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, | |||
2165 | 2169 | ||
2166 | static int pin_down_bytes(struct btrfs_trans_handle *trans, | 2170 | static int pin_down_bytes(struct btrfs_trans_handle *trans, |
2167 | struct btrfs_root *root, | 2171 | struct btrfs_root *root, |
2168 | u64 bytenr, u64 num_bytes, int is_data) | 2172 | struct btrfs_path *path, |
2173 | u64 bytenr, u64 num_bytes, int is_data, | ||
2174 | struct extent_buffer **must_clean) | ||
2169 | { | 2175 | { |
2170 | int err = 0; | 2176 | int err = 0; |
2171 | struct extent_buffer *buf; | 2177 | struct extent_buffer *buf; |
@@ -2191,15 +2197,16 @@ static int pin_down_bytes(struct btrfs_trans_handle *trans, | |||
2191 | header_owner != BTRFS_DATA_RELOC_TREE_OBJECTID && | 2197 | header_owner != BTRFS_DATA_RELOC_TREE_OBJECTID && |
2192 | header_transid == trans->transid && | 2198 | header_transid == trans->transid && |
2193 | !btrfs_header_flag(buf, BTRFS_HEADER_FLAG_WRITTEN)) { | 2199 | !btrfs_header_flag(buf, BTRFS_HEADER_FLAG_WRITTEN)) { |
2194 | clean_tree_block(NULL, root, buf); | 2200 | *must_clean = buf; |
2195 | btrfs_tree_unlock(buf); | ||
2196 | free_extent_buffer(buf); | ||
2197 | return 1; | 2201 | return 1; |
2198 | } | 2202 | } |
2199 | btrfs_tree_unlock(buf); | 2203 | btrfs_tree_unlock(buf); |
2200 | } | 2204 | } |
2201 | free_extent_buffer(buf); | 2205 | free_extent_buffer(buf); |
2202 | pinit: | 2206 | pinit: |
2207 | btrfs_set_path_blocking(path); | ||
2208 | mutex_lock(&root->fs_info->pinned_mutex); | ||
2209 | /* unlocks the pinned mutex */ | ||
2203 | btrfs_update_pinned_extents(root, bytenr, num_bytes, 1); | 2210 | btrfs_update_pinned_extents(root, bytenr, num_bytes, 1); |
2204 | 2211 | ||
2205 | BUG_ON(err < 0); | 2212 | BUG_ON(err < 0); |
@@ -2236,6 +2243,7 @@ static int __free_extent(struct btrfs_trans_handle *trans, | |||
2236 | return -ENOMEM; | 2243 | return -ENOMEM; |
2237 | 2244 | ||
2238 | path->reada = 1; | 2245 | path->reada = 1; |
2246 | path->leave_spinning = 1; | ||
2239 | ret = lookup_extent_backref(trans, extent_root, path, | 2247 | ret = lookup_extent_backref(trans, extent_root, path, |
2240 | bytenr, parent, root_objectid, | 2248 | bytenr, parent, root_objectid, |
2241 | ref_generation, owner_objectid, 1); | 2249 | ref_generation, owner_objectid, 1); |
@@ -2261,6 +2269,7 @@ static int __free_extent(struct btrfs_trans_handle *trans, | |||
2261 | refs_to_drop); | 2269 | refs_to_drop); |
2262 | BUG_ON(ret); | 2270 | BUG_ON(ret); |
2263 | btrfs_release_path(extent_root, path); | 2271 | btrfs_release_path(extent_root, path); |
2272 | path->leave_spinning = 1; | ||
2264 | ret = btrfs_search_slot(trans, extent_root, | 2273 | ret = btrfs_search_slot(trans, extent_root, |
2265 | &key, path, -1, 1); | 2274 | &key, path, -1, 1); |
2266 | if (ret) { | 2275 | if (ret) { |
@@ -2318,6 +2327,7 @@ static int __free_extent(struct btrfs_trans_handle *trans, | |||
2318 | /* if refs are 0, we need to setup the path for deletion */ | 2327 | /* if refs are 0, we need to setup the path for deletion */ |
2319 | if (refs == 0) { | 2328 | if (refs == 0) { |
2320 | btrfs_release_path(extent_root, path); | 2329 | btrfs_release_path(extent_root, path); |
2330 | path->leave_spinning = 1; | ||
2321 | ret = btrfs_search_slot(trans, extent_root, &key, path, | 2331 | ret = btrfs_search_slot(trans, extent_root, &key, path, |
2322 | -1, 1); | 2332 | -1, 1); |
2323 | BUG_ON(ret); | 2333 | BUG_ON(ret); |
@@ -2327,16 +2337,18 @@ static int __free_extent(struct btrfs_trans_handle *trans, | |||
2327 | if (refs == 0) { | 2337 | if (refs == 0) { |
2328 | u64 super_used; | 2338 | u64 super_used; |
2329 | u64 root_used; | 2339 | u64 root_used; |
2340 | struct extent_buffer *must_clean = NULL; | ||
2330 | 2341 | ||
2331 | if (pin) { | 2342 | if (pin) { |
2332 | mutex_lock(&root->fs_info->pinned_mutex); | 2343 | ret = pin_down_bytes(trans, root, path, |
2333 | ret = pin_down_bytes(trans, root, bytenr, num_bytes, | 2344 | bytenr, num_bytes, |
2334 | owner_objectid >= BTRFS_FIRST_FREE_OBJECTID); | 2345 | owner_objectid >= BTRFS_FIRST_FREE_OBJECTID, |
2335 | mutex_unlock(&root->fs_info->pinned_mutex); | 2346 | &must_clean); |
2336 | if (ret > 0) | 2347 | if (ret > 0) |
2337 | mark_free = 1; | 2348 | mark_free = 1; |
2338 | BUG_ON(ret < 0); | 2349 | BUG_ON(ret < 0); |
2339 | } | 2350 | } |
2351 | |||
2340 | /* block accounting for super block */ | 2352 | /* block accounting for super block */ |
2341 | spin_lock(&info->delalloc_lock); | 2353 | spin_lock(&info->delalloc_lock); |
2342 | super_used = btrfs_super_bytes_used(&info->super_copy); | 2354 | super_used = btrfs_super_bytes_used(&info->super_copy); |
@@ -2348,11 +2360,27 @@ static int __free_extent(struct btrfs_trans_handle *trans, | |||
2348 | btrfs_set_root_used(&root->root_item, | 2360 | btrfs_set_root_used(&root->root_item, |
2349 | root_used - num_bytes); | 2361 | root_used - num_bytes); |
2350 | spin_unlock(&info->delalloc_lock); | 2362 | spin_unlock(&info->delalloc_lock); |
2363 | |||
2364 | /* | ||
2365 | * it is going to be very rare for someone to be waiting | ||
2366 | * on the block we're freeing. del_items might need to | ||
2367 | * schedule, so rather than get fancy, just force it | ||
2368 | * to blocking here | ||
2369 | */ | ||
2370 | if (must_clean) | ||
2371 | btrfs_set_lock_blocking(must_clean); | ||
2372 | |||
2351 | ret = btrfs_del_items(trans, extent_root, path, path->slots[0], | 2373 | ret = btrfs_del_items(trans, extent_root, path, path->slots[0], |
2352 | num_to_del); | 2374 | num_to_del); |
2353 | BUG_ON(ret); | 2375 | BUG_ON(ret); |
2354 | btrfs_release_path(extent_root, path); | 2376 | btrfs_release_path(extent_root, path); |
2355 | 2377 | ||
2378 | if (must_clean) { | ||
2379 | clean_tree_block(NULL, root, must_clean); | ||
2380 | btrfs_tree_unlock(must_clean); | ||
2381 | free_extent_buffer(must_clean); | ||
2382 | } | ||
2383 | |||
2356 | if (owner_objectid >= BTRFS_FIRST_FREE_OBJECTID) { | 2384 | if (owner_objectid >= BTRFS_FIRST_FREE_OBJECTID) { |
2357 | ret = btrfs_del_csums(trans, root, bytenr, num_bytes); | 2385 | ret = btrfs_del_csums(trans, root, bytenr, num_bytes); |
2358 | BUG_ON(ret); | 2386 | BUG_ON(ret); |
@@ -2480,8 +2508,9 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans, | |||
2480 | if (root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID && | 2508 | if (root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID && |
2481 | owner_objectid < BTRFS_FIRST_FREE_OBJECTID) { | 2509 | owner_objectid < BTRFS_FIRST_FREE_OBJECTID) { |
2482 | mutex_lock(&root->fs_info->pinned_mutex); | 2510 | mutex_lock(&root->fs_info->pinned_mutex); |
2511 | |||
2512 | /* unlocks the pinned mutex */ | ||
2483 | btrfs_update_pinned_extents(root, bytenr, num_bytes, 1); | 2513 | btrfs_update_pinned_extents(root, bytenr, num_bytes, 1); |
2484 | mutex_unlock(&root->fs_info->pinned_mutex); | ||
2485 | update_reserved_extents(root, bytenr, num_bytes, 0); | 2514 | update_reserved_extents(root, bytenr, num_bytes, 0); |
2486 | ret = 0; | 2515 | ret = 0; |
2487 | } else { | 2516 | } else { |
@@ -2931,6 +2960,7 @@ static int __btrfs_alloc_reserved_extent(struct btrfs_trans_handle *trans, | |||
2931 | path = btrfs_alloc_path(); | 2960 | path = btrfs_alloc_path(); |
2932 | BUG_ON(!path); | 2961 | BUG_ON(!path); |
2933 | 2962 | ||
2963 | path->leave_spinning = 1; | ||
2934 | ret = btrfs_insert_empty_items(trans, extent_root, path, keys, | 2964 | ret = btrfs_insert_empty_items(trans, extent_root, path, keys, |
2935 | sizes, 2); | 2965 | sizes, 2); |
2936 | BUG_ON(ret); | 2966 | BUG_ON(ret); |
@@ -5435,6 +5465,7 @@ static int __insert_orphan_inode(struct btrfs_trans_handle *trans, | |||
5435 | if (!path) | 5465 | if (!path) |
5436 | return -ENOMEM; | 5466 | return -ENOMEM; |
5437 | 5467 | ||
5468 | path->leave_spinning = 1; | ||
5438 | ret = btrfs_insert_empty_inode(trans, root, path, objectid); | 5469 | ret = btrfs_insert_empty_inode(trans, root, path, objectid); |
5439 | if (ret) | 5470 | if (ret) |
5440 | goto out; | 5471 | goto out; |