diff options
-rw-r--r-- | fs/btrfs/ctree.c | 19 | ||||
-rw-r--r-- | fs/btrfs/ctree.h | 12 | ||||
-rw-r--r-- | fs/btrfs/dir-item.c | 3 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 67 | ||||
-rw-r--r-- | fs/btrfs/disk-io.h | 1 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 69 | ||||
-rw-r--r-- | fs/btrfs/extent_io.c | 51 | ||||
-rw-r--r-- | fs/btrfs/extent_io.h | 3 | ||||
-rw-r--r-- | fs/btrfs/file-item.c | 7 | ||||
-rw-r--r-- | fs/btrfs/file.c | 4 | ||||
-rw-r--r-- | fs/btrfs/inode-item.c | 3 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 17 | ||||
-rw-r--r-- | fs/btrfs/locking.c | 11 | ||||
-rw-r--r-- | fs/btrfs/tree-log.c | 1 |
14 files changed, 172 insertions, 96 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 3764248bdc05..8686a3d2ab3a 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -1684,7 +1684,8 @@ done: | |||
1684 | * we don't really know what they plan on doing with the path | 1684 | * we don't really know what they plan on doing with the path |
1685 | * from here on, so for now just mark it as blocking | 1685 | * from here on, so for now just mark it as blocking |
1686 | */ | 1686 | */ |
1687 | btrfs_set_path_blocking(p); | 1687 | if (!p->leave_spinning) |
1688 | btrfs_set_path_blocking(p); | ||
1688 | return ret; | 1689 | return ret; |
1689 | } | 1690 | } |
1690 | 1691 | ||
@@ -3032,26 +3033,27 @@ int btrfs_split_item(struct btrfs_trans_handle *trans, | |||
3032 | return -EAGAIN; | 3033 | return -EAGAIN; |
3033 | } | 3034 | } |
3034 | 3035 | ||
3036 | btrfs_set_path_blocking(path); | ||
3035 | ret = split_leaf(trans, root, &orig_key, path, | 3037 | ret = split_leaf(trans, root, &orig_key, path, |
3036 | sizeof(struct btrfs_item), 1); | 3038 | sizeof(struct btrfs_item), 1); |
3037 | path->keep_locks = 0; | 3039 | path->keep_locks = 0; |
3038 | BUG_ON(ret); | 3040 | BUG_ON(ret); |
3039 | 3041 | ||
3042 | btrfs_unlock_up_safe(path, 1); | ||
3043 | leaf = path->nodes[0]; | ||
3044 | BUG_ON(btrfs_leaf_free_space(root, leaf) < sizeof(struct btrfs_item)); | ||
3045 | |||
3046 | split: | ||
3040 | /* | 3047 | /* |
3041 | * make sure any changes to the path from split_leaf leave it | 3048 | * make sure any changes to the path from split_leaf leave it |
3042 | * in a blocking state | 3049 | * in a blocking state |
3043 | */ | 3050 | */ |
3044 | btrfs_set_path_blocking(path); | 3051 | btrfs_set_path_blocking(path); |
3045 | 3052 | ||
3046 | leaf = path->nodes[0]; | ||
3047 | BUG_ON(btrfs_leaf_free_space(root, leaf) < sizeof(struct btrfs_item)); | ||
3048 | |||
3049 | split: | ||
3050 | item = btrfs_item_nr(leaf, path->slots[0]); | 3053 | item = btrfs_item_nr(leaf, path->slots[0]); |
3051 | orig_offset = btrfs_item_offset(leaf, item); | 3054 | orig_offset = btrfs_item_offset(leaf, item); |
3052 | item_size = btrfs_item_size(leaf, item); | 3055 | item_size = btrfs_item_size(leaf, item); |
3053 | 3056 | ||
3054 | |||
3055 | buf = kmalloc(item_size, GFP_NOFS); | 3057 | buf = kmalloc(item_size, GFP_NOFS); |
3056 | read_extent_buffer(leaf, buf, btrfs_item_ptr_offset(leaf, | 3058 | read_extent_buffer(leaf, buf, btrfs_item_ptr_offset(leaf, |
3057 | path->slots[0]), item_size); | 3059 | path->slots[0]), item_size); |
@@ -3545,7 +3547,6 @@ setup_items_for_insert(struct btrfs_trans_handle *trans, | |||
3545 | } | 3547 | } |
3546 | 3548 | ||
3547 | btrfs_set_header_nritems(leaf, nritems + nr); | 3549 | btrfs_set_header_nritems(leaf, nritems + nr); |
3548 | btrfs_mark_buffer_dirty(leaf); | ||
3549 | 3550 | ||
3550 | ret = 0; | 3551 | ret = 0; |
3551 | if (slot == 0) { | 3552 | if (slot == 0) { |
@@ -3553,6 +3554,8 @@ setup_items_for_insert(struct btrfs_trans_handle *trans, | |||
3553 | btrfs_cpu_key_to_disk(&disk_key, cpu_key); | 3554 | btrfs_cpu_key_to_disk(&disk_key, cpu_key); |
3554 | ret = fixup_low_keys(trans, root, path, &disk_key, 1); | 3555 | ret = fixup_low_keys(trans, root, path, &disk_key, 1); |
3555 | } | 3556 | } |
3557 | btrfs_unlock_up_safe(path, 1); | ||
3558 | btrfs_mark_buffer_dirty(leaf); | ||
3556 | 3559 | ||
3557 | if (btrfs_leaf_free_space(root, leaf) < 0) { | 3560 | if (btrfs_leaf_free_space(root, leaf) < 0) { |
3558 | btrfs_print_leaf(root, leaf); | 3561 | btrfs_print_leaf(root, leaf); |
@@ -3596,7 +3599,6 @@ int btrfs_insert_empty_items(struct btrfs_trans_handle *trans, | |||
3596 | total_data, total_size, nr); | 3599 | total_data, total_size, nr); |
3597 | 3600 | ||
3598 | out: | 3601 | out: |
3599 | btrfs_unlock_up_safe(path, 1); | ||
3600 | return ret; | 3602 | return ret; |
3601 | } | 3603 | } |
3602 | 3604 | ||
@@ -3792,6 +3794,7 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
3792 | slot = path->slots[1]; | 3794 | slot = path->slots[1]; |
3793 | extent_buffer_get(leaf); | 3795 | extent_buffer_get(leaf); |
3794 | 3796 | ||
3797 | btrfs_set_path_blocking(path); | ||
3795 | wret = push_leaf_left(trans, root, path, 1, 1); | 3798 | wret = push_leaf_left(trans, root, path, 1, 1); |
3796 | if (wret < 0 && wret != -ENOSPC) | 3799 | if (wret < 0 && wret != -ENOSPC) |
3797 | ret = wret; | 3800 | ret = wret; |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 08d9f8d15538..4ddce91cf3f9 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -401,15 +401,16 @@ struct btrfs_path { | |||
401 | int locks[BTRFS_MAX_LEVEL]; | 401 | int locks[BTRFS_MAX_LEVEL]; |
402 | int reada; | 402 | int reada; |
403 | /* keep some upper locks as we walk down */ | 403 | /* keep some upper locks as we walk down */ |
404 | int keep_locks; | ||
405 | int skip_locking; | ||
406 | int lowest_level; | 404 | int lowest_level; |
407 | 405 | ||
408 | /* | 406 | /* |
409 | * set by btrfs_split_item, tells search_slot to keep all locks | 407 | * set by btrfs_split_item, tells search_slot to keep all locks |
410 | * and to force calls to keep space in the nodes | 408 | * and to force calls to keep space in the nodes |
411 | */ | 409 | */ |
412 | int search_for_split; | 410 | unsigned int search_for_split:1; |
411 | unsigned int keep_locks:1; | ||
412 | unsigned int skip_locking:1; | ||
413 | unsigned int leave_spinning:1; | ||
413 | }; | 414 | }; |
414 | 415 | ||
415 | /* | 416 | /* |
@@ -779,6 +780,11 @@ struct btrfs_fs_info { | |||
779 | atomic_t throttle_gen; | 780 | atomic_t throttle_gen; |
780 | 781 | ||
781 | u64 total_pinned; | 782 | u64 total_pinned; |
783 | |||
784 | /* protected by the delalloc lock, used to keep from writing | ||
785 | * metadata until there is a nice batch | ||
786 | */ | ||
787 | u64 dirty_metadata_bytes; | ||
782 | struct list_head dirty_cowonly_roots; | 788 | struct list_head dirty_cowonly_roots; |
783 | 789 | ||
784 | struct btrfs_fs_devices *fs_devices; | 790 | struct btrfs_fs_devices *fs_devices; |
diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c index 926a0b287a7d..1d70236ba00c 100644 --- a/fs/btrfs/dir-item.c +++ b/fs/btrfs/dir-item.c | |||
@@ -145,7 +145,10 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
145 | key.objectid = dir; | 145 | key.objectid = dir; |
146 | btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY); | 146 | btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY); |
147 | key.offset = btrfs_name_hash(name, name_len); | 147 | key.offset = btrfs_name_hash(name, name_len); |
148 | |||
148 | path = btrfs_alloc_path(); | 149 | path = btrfs_alloc_path(); |
150 | path->leave_spinning = 1; | ||
151 | |||
149 | data_size = sizeof(*dir_item) + name_len; | 152 | data_size = sizeof(*dir_item) + name_len; |
150 | dir_item = insert_with_overflow(trans, root, path, &key, data_size, | 153 | dir_item = insert_with_overflow(trans, root, path, &key, data_size, |
151 | name, name_len); | 154 | name, name_len); |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 1f1d89b18818..9244cd7313d4 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -668,14 +668,31 @@ static int btree_submit_bio_hook(struct inode *inode, int rw, struct bio *bio, | |||
668 | static int btree_writepage(struct page *page, struct writeback_control *wbc) | 668 | static int btree_writepage(struct page *page, struct writeback_control *wbc) |
669 | { | 669 | { |
670 | struct extent_io_tree *tree; | 670 | struct extent_io_tree *tree; |
671 | struct btrfs_root *root = BTRFS_I(page->mapping->host)->root; | ||
672 | struct extent_buffer *eb; | ||
673 | int was_dirty; | ||
674 | |||
671 | tree = &BTRFS_I(page->mapping->host)->io_tree; | 675 | tree = &BTRFS_I(page->mapping->host)->io_tree; |
676 | if (!(current->flags & PF_MEMALLOC)) { | ||
677 | return extent_write_full_page(tree, page, | ||
678 | btree_get_extent, wbc); | ||
679 | } | ||
672 | 680 | ||
673 | if (current->flags & PF_MEMALLOC) { | 681 | redirty_page_for_writepage(wbc, page); |
674 | redirty_page_for_writepage(wbc, page); | 682 | eb = btrfs_find_tree_block(root, page_offset(page), |
675 | unlock_page(page); | 683 | PAGE_CACHE_SIZE); |
676 | return 0; | 684 | WARN_ON(!eb); |
685 | |||
686 | was_dirty = test_and_set_bit(EXTENT_BUFFER_DIRTY, &eb->bflags); | ||
687 | if (!was_dirty) { | ||
688 | spin_lock(&root->fs_info->delalloc_lock); | ||
689 | root->fs_info->dirty_metadata_bytes += PAGE_CACHE_SIZE; | ||
690 | spin_unlock(&root->fs_info->delalloc_lock); | ||
677 | } | 691 | } |
678 | return extent_write_full_page(tree, page, btree_get_extent, wbc); | 692 | free_extent_buffer(eb); |
693 | |||
694 | unlock_page(page); | ||
695 | return 0; | ||
679 | } | 696 | } |
680 | 697 | ||
681 | static int btree_writepages(struct address_space *mapping, | 698 | static int btree_writepages(struct address_space *mapping, |
@@ -684,15 +701,15 @@ static int btree_writepages(struct address_space *mapping, | |||
684 | struct extent_io_tree *tree; | 701 | struct extent_io_tree *tree; |
685 | tree = &BTRFS_I(mapping->host)->io_tree; | 702 | tree = &BTRFS_I(mapping->host)->io_tree; |
686 | if (wbc->sync_mode == WB_SYNC_NONE) { | 703 | if (wbc->sync_mode == WB_SYNC_NONE) { |
704 | struct btrfs_root *root = BTRFS_I(mapping->host)->root; | ||
687 | u64 num_dirty; | 705 | u64 num_dirty; |
688 | u64 start = 0; | ||
689 | unsigned long thresh = 32 * 1024 * 1024; | 706 | unsigned long thresh = 32 * 1024 * 1024; |
690 | 707 | ||
691 | if (wbc->for_kupdate) | 708 | if (wbc->for_kupdate) |
692 | return 0; | 709 | return 0; |
693 | 710 | ||
694 | num_dirty = count_range_bits(tree, &start, (u64)-1, | 711 | /* this is a bit racy, but that's ok */ |
695 | thresh, EXTENT_DIRTY); | 712 | num_dirty = root->fs_info->dirty_metadata_bytes; |
696 | if (num_dirty < thresh) | 713 | if (num_dirty < thresh) |
697 | return 0; | 714 | return 0; |
698 | } | 715 | } |
@@ -859,9 +876,17 @@ int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
859 | root->fs_info->running_transaction->transid) { | 876 | root->fs_info->running_transaction->transid) { |
860 | btrfs_assert_tree_locked(buf); | 877 | btrfs_assert_tree_locked(buf); |
861 | 878 | ||
862 | /* ugh, clear_extent_buffer_dirty can be expensive */ | 879 | if (test_and_clear_bit(EXTENT_BUFFER_DIRTY, &buf->bflags)) { |
863 | btrfs_set_lock_blocking(buf); | 880 | spin_lock(&root->fs_info->delalloc_lock); |
881 | if (root->fs_info->dirty_metadata_bytes >= buf->len) | ||
882 | root->fs_info->dirty_metadata_bytes -= buf->len; | ||
883 | else | ||
884 | WARN_ON(1); | ||
885 | spin_unlock(&root->fs_info->delalloc_lock); | ||
886 | } | ||
864 | 887 | ||
888 | /* ugh, clear_extent_buffer_dirty needs to lock the page */ | ||
889 | btrfs_set_lock_blocking(buf); | ||
865 | clear_extent_buffer_dirty(&BTRFS_I(btree_inode)->io_tree, | 890 | clear_extent_buffer_dirty(&BTRFS_I(btree_inode)->io_tree, |
866 | buf); | 891 | buf); |
867 | } | 892 | } |
@@ -2348,8 +2373,7 @@ void btrfs_mark_buffer_dirty(struct extent_buffer *buf) | |||
2348 | struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; | 2373 | struct btrfs_root *root = BTRFS_I(buf->first_page->mapping->host)->root; |
2349 | u64 transid = btrfs_header_generation(buf); | 2374 | u64 transid = btrfs_header_generation(buf); |
2350 | struct inode *btree_inode = root->fs_info->btree_inode; | 2375 | struct inode *btree_inode = root->fs_info->btree_inode; |
2351 | 2376 | int was_dirty; | |
2352 | btrfs_set_lock_blocking(buf); | ||
2353 | 2377 | ||
2354 | btrfs_assert_tree_locked(buf); | 2378 | btrfs_assert_tree_locked(buf); |
2355 | if (transid != root->fs_info->generation) { | 2379 | if (transid != root->fs_info->generation) { |
@@ -2360,7 +2384,13 @@ void btrfs_mark_buffer_dirty(struct extent_buffer *buf) | |||
2360 | (unsigned long long)root->fs_info->generation); | 2384 | (unsigned long long)root->fs_info->generation); |
2361 | WARN_ON(1); | 2385 | WARN_ON(1); |
2362 | } | 2386 | } |
2363 | set_extent_buffer_dirty(&BTRFS_I(btree_inode)->io_tree, buf); | 2387 | was_dirty = set_extent_buffer_dirty(&BTRFS_I(btree_inode)->io_tree, |
2388 | buf); | ||
2389 | if (!was_dirty) { | ||
2390 | spin_lock(&root->fs_info->delalloc_lock); | ||
2391 | root->fs_info->dirty_metadata_bytes += buf->len; | ||
2392 | spin_unlock(&root->fs_info->delalloc_lock); | ||
2393 | } | ||
2364 | } | 2394 | } |
2365 | 2395 | ||
2366 | void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr) | 2396 | void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr) |
@@ -2400,6 +2430,7 @@ int btrfs_read_buffer(struct extent_buffer *buf, u64 parent_transid) | |||
2400 | int btree_lock_page_hook(struct page *page) | 2430 | int btree_lock_page_hook(struct page *page) |
2401 | { | 2431 | { |
2402 | struct inode *inode = page->mapping->host; | 2432 | struct inode *inode = page->mapping->host; |
2433 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
2403 | struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; | 2434 | struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; |
2404 | struct extent_buffer *eb; | 2435 | struct extent_buffer *eb; |
2405 | unsigned long len; | 2436 | unsigned long len; |
@@ -2415,6 +2446,16 @@ int btree_lock_page_hook(struct page *page) | |||
2415 | 2446 | ||
2416 | btrfs_tree_lock(eb); | 2447 | btrfs_tree_lock(eb); |
2417 | btrfs_set_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN); | 2448 | btrfs_set_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN); |
2449 | |||
2450 | if (test_and_clear_bit(EXTENT_BUFFER_DIRTY, &eb->bflags)) { | ||
2451 | spin_lock(&root->fs_info->delalloc_lock); | ||
2452 | if (root->fs_info->dirty_metadata_bytes >= eb->len) | ||
2453 | root->fs_info->dirty_metadata_bytes -= eb->len; | ||
2454 | else | ||
2455 | WARN_ON(1); | ||
2456 | spin_unlock(&root->fs_info->delalloc_lock); | ||
2457 | } | ||
2458 | |||
2418 | btrfs_tree_unlock(eb); | 2459 | btrfs_tree_unlock(eb); |
2419 | free_extent_buffer(eb); | 2460 | free_extent_buffer(eb); |
2420 | out: | 2461 | out: |
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h index 95029db227be..c958ecbc1916 100644 --- a/fs/btrfs/disk-io.h +++ b/fs/btrfs/disk-io.h | |||
@@ -72,6 +72,7 @@ int btrfs_insert_dev_radix(struct btrfs_root *root, | |||
72 | void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr); | 72 | void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr); |
73 | int btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root); | 73 | int btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root); |
74 | void btrfs_mark_buffer_dirty(struct extent_buffer *buf); | 74 | void btrfs_mark_buffer_dirty(struct extent_buffer *buf); |
75 | void btrfs_mark_buffer_dirty_nonblocking(struct extent_buffer *buf); | ||
75 | int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid); | 76 | int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid); |
76 | int btrfs_set_buffer_uptodate(struct extent_buffer *buf); | 77 | int btrfs_set_buffer_uptodate(struct extent_buffer *buf); |
77 | int wait_on_tree_block_writeback(struct btrfs_root *root, | 78 | int wait_on_tree_block_writeback(struct btrfs_root *root, |
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; |
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index ebe6b29e6069..08085af089e2 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
@@ -3124,20 +3124,15 @@ void free_extent_buffer(struct extent_buffer *eb) | |||
3124 | int clear_extent_buffer_dirty(struct extent_io_tree *tree, | 3124 | int clear_extent_buffer_dirty(struct extent_io_tree *tree, |
3125 | struct extent_buffer *eb) | 3125 | struct extent_buffer *eb) |
3126 | { | 3126 | { |
3127 | int set; | ||
3128 | unsigned long i; | 3127 | unsigned long i; |
3129 | unsigned long num_pages; | 3128 | unsigned long num_pages; |
3130 | struct page *page; | 3129 | struct page *page; |
3131 | 3130 | ||
3132 | u64 start = eb->start; | ||
3133 | u64 end = start + eb->len - 1; | ||
3134 | |||
3135 | set = clear_extent_dirty(tree, start, end, GFP_NOFS); | ||
3136 | num_pages = num_extent_pages(eb->start, eb->len); | 3131 | num_pages = num_extent_pages(eb->start, eb->len); |
3137 | 3132 | ||
3138 | for (i = 0; i < num_pages; i++) { | 3133 | for (i = 0; i < num_pages; i++) { |
3139 | page = extent_buffer_page(eb, i); | 3134 | page = extent_buffer_page(eb, i); |
3140 | if (!set && !PageDirty(page)) | 3135 | if (!PageDirty(page)) |
3141 | continue; | 3136 | continue; |
3142 | 3137 | ||
3143 | lock_page(page); | 3138 | lock_page(page); |
@@ -3146,22 +3141,6 @@ int clear_extent_buffer_dirty(struct extent_io_tree *tree, | |||
3146 | else | 3141 | else |
3147 | set_page_private(page, EXTENT_PAGE_PRIVATE); | 3142 | set_page_private(page, EXTENT_PAGE_PRIVATE); |
3148 | 3143 | ||
3149 | /* | ||
3150 | * if we're on the last page or the first page and the | ||
3151 | * block isn't aligned on a page boundary, do extra checks | ||
3152 | * to make sure we don't clean page that is partially dirty | ||
3153 | */ | ||
3154 | if ((i == 0 && (eb->start & (PAGE_CACHE_SIZE - 1))) || | ||
3155 | ((i == num_pages - 1) && | ||
3156 | ((eb->start + eb->len) & (PAGE_CACHE_SIZE - 1)))) { | ||
3157 | start = (u64)page->index << PAGE_CACHE_SHIFT; | ||
3158 | end = start + PAGE_CACHE_SIZE - 1; | ||
3159 | if (test_range_bit(tree, start, end, | ||
3160 | EXTENT_DIRTY, 0)) { | ||
3161 | unlock_page(page); | ||
3162 | continue; | ||
3163 | } | ||
3164 | } | ||
3165 | clear_page_dirty_for_io(page); | 3144 | clear_page_dirty_for_io(page); |
3166 | spin_lock_irq(&page->mapping->tree_lock); | 3145 | spin_lock_irq(&page->mapping->tree_lock); |
3167 | if (!PageDirty(page)) { | 3146 | if (!PageDirty(page)) { |
@@ -3187,29 +3166,13 @@ int set_extent_buffer_dirty(struct extent_io_tree *tree, | |||
3187 | { | 3166 | { |
3188 | unsigned long i; | 3167 | unsigned long i; |
3189 | unsigned long num_pages; | 3168 | unsigned long num_pages; |
3169 | int was_dirty = 0; | ||
3190 | 3170 | ||
3171 | was_dirty = test_and_set_bit(EXTENT_BUFFER_DIRTY, &eb->bflags); | ||
3191 | num_pages = num_extent_pages(eb->start, eb->len); | 3172 | num_pages = num_extent_pages(eb->start, eb->len); |
3192 | for (i = 0; i < num_pages; i++) { | 3173 | for (i = 0; i < num_pages; i++) |
3193 | struct page *page = extent_buffer_page(eb, i); | ||
3194 | /* writepage may need to do something special for the | ||
3195 | * first page, we have to make sure page->private is | ||
3196 | * properly set. releasepage may drop page->private | ||
3197 | * on us if the page isn't already dirty. | ||
3198 | */ | ||
3199 | lock_page(page); | ||
3200 | if (i == 0) { | ||
3201 | set_page_extent_head(page, eb->len); | ||
3202 | } else if (PagePrivate(page) && | ||
3203 | page->private != EXTENT_PAGE_PRIVATE) { | ||
3204 | set_page_extent_mapped(page); | ||
3205 | } | ||
3206 | __set_page_dirty_nobuffers(extent_buffer_page(eb, i)); | 3174 | __set_page_dirty_nobuffers(extent_buffer_page(eb, i)); |
3207 | set_extent_dirty(tree, page_offset(page), | 3175 | return was_dirty; |
3208 | page_offset(page) + PAGE_CACHE_SIZE - 1, | ||
3209 | GFP_NOFS); | ||
3210 | unlock_page(page); | ||
3211 | } | ||
3212 | return 0; | ||
3213 | } | 3176 | } |
3214 | 3177 | ||
3215 | int clear_extent_buffer_uptodate(struct extent_io_tree *tree, | 3178 | int clear_extent_buffer_uptodate(struct extent_io_tree *tree, |
@@ -3789,6 +3752,10 @@ int try_release_extent_buffer(struct extent_io_tree *tree, struct page *page) | |||
3789 | ret = 0; | 3752 | ret = 0; |
3790 | goto out; | 3753 | goto out; |
3791 | } | 3754 | } |
3755 | if (test_bit(EXTENT_BUFFER_DIRTY, &eb->bflags)) { | ||
3756 | ret = 0; | ||
3757 | goto out; | ||
3758 | } | ||
3792 | /* at this point we can safely release the extent buffer */ | 3759 | /* at this point we can safely release the extent buffer */ |
3793 | num_pages = num_extent_pages(eb->start, eb->len); | 3760 | num_pages = num_extent_pages(eb->start, eb->len); |
3794 | for (i = 0; i < num_pages; i++) | 3761 | for (i = 0; i < num_pages; i++) |
diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index 1f9df88afbf6..5bc20abf3f3d 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h | |||
@@ -25,6 +25,7 @@ | |||
25 | /* these are bit numbers for test/set bit */ | 25 | /* these are bit numbers for test/set bit */ |
26 | #define EXTENT_BUFFER_UPTODATE 0 | 26 | #define EXTENT_BUFFER_UPTODATE 0 |
27 | #define EXTENT_BUFFER_BLOCKING 1 | 27 | #define EXTENT_BUFFER_BLOCKING 1 |
28 | #define EXTENT_BUFFER_DIRTY 2 | ||
28 | 29 | ||
29 | /* | 30 | /* |
30 | * page->private values. Every page that is controlled by the extent | 31 | * page->private values. Every page that is controlled by the extent |
@@ -254,6 +255,8 @@ int clear_extent_buffer_dirty(struct extent_io_tree *tree, | |||
254 | struct extent_buffer *eb); | 255 | struct extent_buffer *eb); |
255 | int set_extent_buffer_dirty(struct extent_io_tree *tree, | 256 | int set_extent_buffer_dirty(struct extent_io_tree *tree, |
256 | struct extent_buffer *eb); | 257 | struct extent_buffer *eb); |
258 | int test_extent_buffer_dirty(struct extent_io_tree *tree, | ||
259 | struct extent_buffer *eb); | ||
257 | int set_extent_buffer_uptodate(struct extent_io_tree *tree, | 260 | int set_extent_buffer_uptodate(struct extent_io_tree *tree, |
258 | struct extent_buffer *eb); | 261 | struct extent_buffer *eb); |
259 | int clear_extent_buffer_uptodate(struct extent_io_tree *tree, | 262 | int clear_extent_buffer_uptodate(struct extent_io_tree *tree, |
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index 964652435fd1..9b99886562d0 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c | |||
@@ -52,6 +52,7 @@ int btrfs_insert_file_extent(struct btrfs_trans_handle *trans, | |||
52 | file_key.offset = pos; | 52 | file_key.offset = pos; |
53 | btrfs_set_key_type(&file_key, BTRFS_EXTENT_DATA_KEY); | 53 | btrfs_set_key_type(&file_key, BTRFS_EXTENT_DATA_KEY); |
54 | 54 | ||
55 | path->leave_spinning = 1; | ||
55 | ret = btrfs_insert_empty_item(trans, root, path, &file_key, | 56 | ret = btrfs_insert_empty_item(trans, root, path, &file_key, |
56 | sizeof(*item)); | 57 | sizeof(*item)); |
57 | if (ret < 0) | 58 | if (ret < 0) |
@@ -523,6 +524,7 @@ int btrfs_del_csums(struct btrfs_trans_handle *trans, | |||
523 | key.offset = end_byte - 1; | 524 | key.offset = end_byte - 1; |
524 | key.type = BTRFS_EXTENT_CSUM_KEY; | 525 | key.type = BTRFS_EXTENT_CSUM_KEY; |
525 | 526 | ||
527 | path->leave_spinning = 1; | ||
526 | ret = btrfs_search_slot(trans, root, &key, path, -1, 1); | 528 | ret = btrfs_search_slot(trans, root, &key, path, -1, 1); |
527 | if (ret > 0) { | 529 | if (ret > 0) { |
528 | if (path->slots[0] == 0) | 530 | if (path->slots[0] == 0) |
@@ -757,8 +759,10 @@ insert: | |||
757 | } else { | 759 | } else { |
758 | ins_size = csum_size; | 760 | ins_size = csum_size; |
759 | } | 761 | } |
762 | path->leave_spinning = 1; | ||
760 | ret = btrfs_insert_empty_item(trans, root, path, &file_key, | 763 | ret = btrfs_insert_empty_item(trans, root, path, &file_key, |
761 | ins_size); | 764 | ins_size); |
765 | path->leave_spinning = 0; | ||
762 | if (ret < 0) | 766 | if (ret < 0) |
763 | goto fail_unlock; | 767 | goto fail_unlock; |
764 | if (ret != 0) { | 768 | if (ret != 0) { |
@@ -776,7 +780,6 @@ found: | |||
776 | item_end = (struct btrfs_csum_item *)((unsigned char *)item_end + | 780 | item_end = (struct btrfs_csum_item *)((unsigned char *)item_end + |
777 | btrfs_item_size_nr(leaf, path->slots[0])); | 781 | btrfs_item_size_nr(leaf, path->slots[0])); |
778 | eb_token = NULL; | 782 | eb_token = NULL; |
779 | cond_resched(); | ||
780 | next_sector: | 783 | next_sector: |
781 | 784 | ||
782 | if (!eb_token || | 785 | if (!eb_token || |
@@ -817,9 +820,9 @@ next_sector: | |||
817 | eb_token = NULL; | 820 | eb_token = NULL; |
818 | } | 821 | } |
819 | btrfs_mark_buffer_dirty(path->nodes[0]); | 822 | btrfs_mark_buffer_dirty(path->nodes[0]); |
820 | cond_resched(); | ||
821 | if (total_bytes < sums->len) { | 823 | if (total_bytes < sums->len) { |
822 | btrfs_release_path(root, path); | 824 | btrfs_release_path(root, path); |
825 | cond_resched(); | ||
823 | goto again; | 826 | goto again; |
824 | } | 827 | } |
825 | out: | 828 | out: |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index c80075497645..f06c275644b7 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -606,6 +606,7 @@ next_slot: | |||
606 | btrfs_set_key_type(&ins, BTRFS_EXTENT_DATA_KEY); | 606 | btrfs_set_key_type(&ins, BTRFS_EXTENT_DATA_KEY); |
607 | 607 | ||
608 | btrfs_release_path(root, path); | 608 | btrfs_release_path(root, path); |
609 | path->leave_spinning = 1; | ||
609 | ret = btrfs_insert_empty_item(trans, root, path, &ins, | 610 | ret = btrfs_insert_empty_item(trans, root, path, &ins, |
610 | sizeof(*extent)); | 611 | sizeof(*extent)); |
611 | BUG_ON(ret); | 612 | BUG_ON(ret); |
@@ -639,7 +640,9 @@ next_slot: | |||
639 | ram_bytes); | 640 | ram_bytes); |
640 | btrfs_set_file_extent_type(leaf, extent, found_type); | 641 | btrfs_set_file_extent_type(leaf, extent, found_type); |
641 | 642 | ||
643 | btrfs_unlock_up_safe(path, 1); | ||
642 | btrfs_mark_buffer_dirty(path->nodes[0]); | 644 | btrfs_mark_buffer_dirty(path->nodes[0]); |
645 | btrfs_set_lock_blocking(path->nodes[0]); | ||
643 | 646 | ||
644 | if (disk_bytenr != 0) { | 647 | if (disk_bytenr != 0) { |
645 | ret = btrfs_update_extent_ref(trans, root, | 648 | ret = btrfs_update_extent_ref(trans, root, |
@@ -652,6 +655,7 @@ next_slot: | |||
652 | 655 | ||
653 | BUG_ON(ret); | 656 | BUG_ON(ret); |
654 | } | 657 | } |
658 | path->leave_spinning = 0; | ||
655 | btrfs_release_path(root, path); | 659 | btrfs_release_path(root, path); |
656 | if (disk_bytenr != 0) | 660 | if (disk_bytenr != 0) |
657 | inode_add_bytes(inode, extent_end - end); | 661 | inode_add_bytes(inode, extent_end - end); |
diff --git a/fs/btrfs/inode-item.c b/fs/btrfs/inode-item.c index 3d46fa1f29a4..6b627c611808 100644 --- a/fs/btrfs/inode-item.c +++ b/fs/btrfs/inode-item.c | |||
@@ -73,6 +73,8 @@ int btrfs_del_inode_ref(struct btrfs_trans_handle *trans, | |||
73 | if (!path) | 73 | if (!path) |
74 | return -ENOMEM; | 74 | return -ENOMEM; |
75 | 75 | ||
76 | path->leave_spinning = 1; | ||
77 | |||
76 | ret = btrfs_search_slot(trans, root, &key, path, -1, 1); | 78 | ret = btrfs_search_slot(trans, root, &key, path, -1, 1); |
77 | if (ret > 0) { | 79 | if (ret > 0) { |
78 | ret = -ENOENT; | 80 | ret = -ENOENT; |
@@ -127,6 +129,7 @@ int btrfs_insert_inode_ref(struct btrfs_trans_handle *trans, | |||
127 | if (!path) | 129 | if (!path) |
128 | return -ENOMEM; | 130 | return -ENOMEM; |
129 | 131 | ||
132 | path->leave_spinning = 1; | ||
130 | ret = btrfs_insert_empty_item(trans, root, path, &key, | 133 | ret = btrfs_insert_empty_item(trans, root, path, &key, |
131 | ins_len); | 134 | ins_len); |
132 | if (ret == -EEXIST) { | 135 | if (ret == -EEXIST) { |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index c427011dc453..b83a45dc717e 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -134,6 +134,7 @@ static noinline int insert_inline_extent(struct btrfs_trans_handle *trans, | |||
134 | if (!path) | 134 | if (!path) |
135 | return -ENOMEM; | 135 | return -ENOMEM; |
136 | 136 | ||
137 | path->leave_spinning = 1; | ||
137 | btrfs_set_trans_block_group(trans, inode); | 138 | btrfs_set_trans_block_group(trans, inode); |
138 | 139 | ||
139 | key.objectid = inode->i_ino; | 140 | key.objectid = inode->i_ino; |
@@ -167,9 +168,9 @@ static noinline int insert_inline_extent(struct btrfs_trans_handle *trans, | |||
167 | cur_size = min_t(unsigned long, compressed_size, | 168 | cur_size = min_t(unsigned long, compressed_size, |
168 | PAGE_CACHE_SIZE); | 169 | PAGE_CACHE_SIZE); |
169 | 170 | ||
170 | kaddr = kmap(cpage); | 171 | kaddr = kmap_atomic(cpage, KM_USER0); |
171 | write_extent_buffer(leaf, kaddr, ptr, cur_size); | 172 | write_extent_buffer(leaf, kaddr, ptr, cur_size); |
172 | kunmap(cpage); | 173 | kunmap_atomic(kaddr, KM_USER0); |
173 | 174 | ||
174 | i++; | 175 | i++; |
175 | ptr += cur_size; | 176 | ptr += cur_size; |
@@ -1452,6 +1453,7 @@ static int insert_reserved_file_extent(struct btrfs_trans_handle *trans, | |||
1452 | path = btrfs_alloc_path(); | 1453 | path = btrfs_alloc_path(); |
1453 | BUG_ON(!path); | 1454 | BUG_ON(!path); |
1454 | 1455 | ||
1456 | path->leave_spinning = 1; | ||
1455 | ret = btrfs_drop_extents(trans, root, inode, file_pos, | 1457 | ret = btrfs_drop_extents(trans, root, inode, file_pos, |
1456 | file_pos + num_bytes, file_pos, &hint); | 1458 | file_pos + num_bytes, file_pos, &hint); |
1457 | BUG_ON(ret); | 1459 | BUG_ON(ret); |
@@ -1474,6 +1476,10 @@ static int insert_reserved_file_extent(struct btrfs_trans_handle *trans, | |||
1474 | btrfs_set_file_extent_compression(leaf, fi, compression); | 1476 | btrfs_set_file_extent_compression(leaf, fi, compression); |
1475 | btrfs_set_file_extent_encryption(leaf, fi, encryption); | 1477 | btrfs_set_file_extent_encryption(leaf, fi, encryption); |
1476 | btrfs_set_file_extent_other_encoding(leaf, fi, other_encoding); | 1478 | btrfs_set_file_extent_other_encoding(leaf, fi, other_encoding); |
1479 | |||
1480 | btrfs_unlock_up_safe(path, 1); | ||
1481 | btrfs_set_lock_blocking(leaf); | ||
1482 | |||
1477 | btrfs_mark_buffer_dirty(leaf); | 1483 | btrfs_mark_buffer_dirty(leaf); |
1478 | 1484 | ||
1479 | inode_add_bytes(inode, num_bytes); | 1485 | inode_add_bytes(inode, num_bytes); |
@@ -1486,8 +1492,8 @@ static int insert_reserved_file_extent(struct btrfs_trans_handle *trans, | |||
1486 | root->root_key.objectid, | 1492 | root->root_key.objectid, |
1487 | trans->transid, inode->i_ino, &ins); | 1493 | trans->transid, inode->i_ino, &ins); |
1488 | BUG_ON(ret); | 1494 | BUG_ON(ret); |
1489 | |||
1490 | btrfs_free_path(path); | 1495 | btrfs_free_path(path); |
1496 | |||
1491 | return 0; | 1497 | return 0; |
1492 | } | 1498 | } |
1493 | 1499 | ||
@@ -2118,6 +2124,7 @@ noinline int btrfs_update_inode(struct btrfs_trans_handle *trans, | |||
2118 | 2124 | ||
2119 | path = btrfs_alloc_path(); | 2125 | path = btrfs_alloc_path(); |
2120 | BUG_ON(!path); | 2126 | BUG_ON(!path); |
2127 | path->leave_spinning = 1; | ||
2121 | ret = btrfs_lookup_inode(trans, root, path, | 2128 | ret = btrfs_lookup_inode(trans, root, path, |
2122 | &BTRFS_I(inode)->location, 1); | 2129 | &BTRFS_I(inode)->location, 1); |
2123 | if (ret) { | 2130 | if (ret) { |
@@ -2164,6 +2171,7 @@ int btrfs_unlink_inode(struct btrfs_trans_handle *trans, | |||
2164 | goto err; | 2171 | goto err; |
2165 | } | 2172 | } |
2166 | 2173 | ||
2174 | path->leave_spinning = 1; | ||
2167 | di = btrfs_lookup_dir_item(trans, root, path, dir->i_ino, | 2175 | di = btrfs_lookup_dir_item(trans, root, path, dir->i_ino, |
2168 | name, name_len, -1); | 2176 | name, name_len, -1); |
2169 | if (IS_ERR(di)) { | 2177 | if (IS_ERR(di)) { |
@@ -2515,6 +2523,7 @@ noinline int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans, | |||
2515 | key.type = (u8)-1; | 2523 | key.type = (u8)-1; |
2516 | 2524 | ||
2517 | search_again: | 2525 | search_again: |
2526 | path->leave_spinning = 1; | ||
2518 | ret = btrfs_search_slot(trans, root, &key, path, -1, 1); | 2527 | ret = btrfs_search_slot(trans, root, &key, path, -1, 1); |
2519 | if (ret < 0) | 2528 | if (ret < 0) |
2520 | goto error; | 2529 | goto error; |
@@ -2661,6 +2670,7 @@ delete: | |||
2661 | break; | 2670 | break; |
2662 | } | 2671 | } |
2663 | if (found_extent) { | 2672 | if (found_extent) { |
2673 | btrfs_set_path_blocking(path); | ||
2664 | ret = btrfs_free_extent(trans, root, extent_start, | 2674 | ret = btrfs_free_extent(trans, root, extent_start, |
2665 | extent_num_bytes, | 2675 | extent_num_bytes, |
2666 | leaf->start, root_owner, | 2676 | leaf->start, root_owner, |
@@ -3466,6 +3476,7 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, | |||
3466 | sizes[0] = sizeof(struct btrfs_inode_item); | 3476 | sizes[0] = sizeof(struct btrfs_inode_item); |
3467 | sizes[1] = name_len + sizeof(*ref); | 3477 | sizes[1] = name_len + sizeof(*ref); |
3468 | 3478 | ||
3479 | path->leave_spinning = 1; | ||
3469 | ret = btrfs_insert_empty_items(trans, root, path, key, sizes, 2); | 3480 | ret = btrfs_insert_empty_items(trans, root, path, key, sizes, 2); |
3470 | if (ret != 0) | 3481 | if (ret != 0) |
3471 | goto fail; | 3482 | goto fail; |
diff --git a/fs/btrfs/locking.c b/fs/btrfs/locking.c index 6d8db2f5c38d..a5310c0f41e2 100644 --- a/fs/btrfs/locking.c +++ b/fs/btrfs/locking.c | |||
@@ -96,11 +96,12 @@ int btrfs_try_spin_lock(struct extent_buffer *eb) | |||
96 | { | 96 | { |
97 | int i; | 97 | int i; |
98 | 98 | ||
99 | spin_nested(eb); | 99 | if (btrfs_spin_on_block(eb)) { |
100 | if (!test_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags)) | 100 | spin_nested(eb); |
101 | return 1; | 101 | if (!test_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags)) |
102 | spin_unlock(&eb->lock); | 102 | return 1; |
103 | 103 | spin_unlock(&eb->lock); | |
104 | } | ||
104 | /* spin for a bit on the BLOCKING flag */ | 105 | /* spin for a bit on the BLOCKING flag */ |
105 | for (i = 0; i < 2; i++) { | 106 | for (i = 0; i < 2; i++) { |
106 | cpu_relax(); | 107 | cpu_relax(); |
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 9c462fbd60fa..a93934fc93bd 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
@@ -203,7 +203,6 @@ static int process_one_buffer(struct btrfs_root *log, | |||
203 | mutex_lock(&log->fs_info->pinned_mutex); | 203 | mutex_lock(&log->fs_info->pinned_mutex); |
204 | btrfs_update_pinned_extents(log->fs_info->extent_root, | 204 | btrfs_update_pinned_extents(log->fs_info->extent_root, |
205 | eb->start, eb->len, 1); | 205 | eb->start, eb->len, 1); |
206 | mutex_unlock(&log->fs_info->pinned_mutex); | ||
207 | } | 206 | } |
208 | 207 | ||
209 | if (btrfs_buffer_uptodate(eb, gen)) { | 208 | if (btrfs_buffer_uptodate(eb, gen)) { |