diff options
Diffstat (limited to 'fs/btrfs/relocation.c')
-rw-r--r-- | fs/btrfs/relocation.c | 52 |
1 files changed, 32 insertions, 20 deletions
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index cfcc93c93a7b..e558dd941ded 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/writeback.h> | 21 | #include <linux/writeback.h> |
22 | #include <linux/blkdev.h> | 22 | #include <linux/blkdev.h> |
23 | #include <linux/rbtree.h> | 23 | #include <linux/rbtree.h> |
24 | #include <linux/slab.h> | ||
24 | #include "ctree.h" | 25 | #include "ctree.h" |
25 | #include "disk-io.h" | 26 | #include "disk-io.h" |
26 | #include "transaction.h" | 27 | #include "transaction.h" |
@@ -170,14 +171,14 @@ struct async_merge { | |||
170 | 171 | ||
171 | static void mapping_tree_init(struct mapping_tree *tree) | 172 | static void mapping_tree_init(struct mapping_tree *tree) |
172 | { | 173 | { |
173 | tree->rb_root.rb_node = NULL; | 174 | tree->rb_root = RB_ROOT; |
174 | spin_lock_init(&tree->lock); | 175 | spin_lock_init(&tree->lock); |
175 | } | 176 | } |
176 | 177 | ||
177 | static void backref_cache_init(struct backref_cache *cache) | 178 | static void backref_cache_init(struct backref_cache *cache) |
178 | { | 179 | { |
179 | int i; | 180 | int i; |
180 | cache->rb_root.rb_node = NULL; | 181 | cache->rb_root = RB_ROOT; |
181 | for (i = 0; i < BTRFS_MAX_LEVEL; i++) | 182 | for (i = 0; i < BTRFS_MAX_LEVEL; i++) |
182 | INIT_LIST_HEAD(&cache->pending[i]); | 183 | INIT_LIST_HEAD(&cache->pending[i]); |
183 | spin_lock_init(&cache->lock); | 184 | spin_lock_init(&cache->lock); |
@@ -1561,6 +1562,20 @@ static int invalidate_extent_cache(struct btrfs_root *root, | |||
1561 | return 0; | 1562 | return 0; |
1562 | } | 1563 | } |
1563 | 1564 | ||
1565 | static void put_inodes(struct list_head *list) | ||
1566 | { | ||
1567 | struct inodevec *ivec; | ||
1568 | while (!list_empty(list)) { | ||
1569 | ivec = list_entry(list->next, struct inodevec, list); | ||
1570 | list_del(&ivec->list); | ||
1571 | while (ivec->nr > 0) { | ||
1572 | ivec->nr--; | ||
1573 | iput(ivec->inode[ivec->nr]); | ||
1574 | } | ||
1575 | kfree(ivec); | ||
1576 | } | ||
1577 | } | ||
1578 | |||
1564 | static int find_next_key(struct btrfs_path *path, int level, | 1579 | static int find_next_key(struct btrfs_path *path, int level, |
1565 | struct btrfs_key *key) | 1580 | struct btrfs_key *key) |
1566 | 1581 | ||
@@ -1723,6 +1738,11 @@ static noinline_for_stack int merge_reloc_root(struct reloc_control *rc, | |||
1723 | 1738 | ||
1724 | btrfs_btree_balance_dirty(root, nr); | 1739 | btrfs_btree_balance_dirty(root, nr); |
1725 | 1740 | ||
1741 | /* | ||
1742 | * put inodes outside transaction, otherwise we may deadlock. | ||
1743 | */ | ||
1744 | put_inodes(&inode_list); | ||
1745 | |||
1726 | if (replaced && rc->stage == UPDATE_DATA_PTRS) | 1746 | if (replaced && rc->stage == UPDATE_DATA_PTRS) |
1727 | invalidate_extent_cache(root, &key, &next_key); | 1747 | invalidate_extent_cache(root, &key, &next_key); |
1728 | } | 1748 | } |
@@ -1752,19 +1772,7 @@ out: | |||
1752 | 1772 | ||
1753 | btrfs_btree_balance_dirty(root, nr); | 1773 | btrfs_btree_balance_dirty(root, nr); |
1754 | 1774 | ||
1755 | /* | 1775 | put_inodes(&inode_list); |
1756 | * put inodes while we aren't holding the tree locks | ||
1757 | */ | ||
1758 | while (!list_empty(&inode_list)) { | ||
1759 | struct inodevec *ivec; | ||
1760 | ivec = list_entry(inode_list.next, struct inodevec, list); | ||
1761 | list_del(&ivec->list); | ||
1762 | while (ivec->nr > 0) { | ||
1763 | ivec->nr--; | ||
1764 | iput(ivec->inode[ivec->nr]); | ||
1765 | } | ||
1766 | kfree(ivec); | ||
1767 | } | ||
1768 | 1776 | ||
1769 | if (replaced && rc->stage == UPDATE_DATA_PTRS) | 1777 | if (replaced && rc->stage == UPDATE_DATA_PTRS) |
1770 | invalidate_extent_cache(root, &key, &next_key); | 1778 | invalidate_extent_cache(root, &key, &next_key); |
@@ -2652,7 +2660,7 @@ static int relocate_file_extent_cluster(struct inode *inode, | |||
2652 | EXTENT_BOUNDARY, GFP_NOFS); | 2660 | EXTENT_BOUNDARY, GFP_NOFS); |
2653 | nr++; | 2661 | nr++; |
2654 | } | 2662 | } |
2655 | btrfs_set_extent_delalloc(inode, page_start, page_end); | 2663 | btrfs_set_extent_delalloc(inode, page_start, page_end, NULL); |
2656 | 2664 | ||
2657 | set_page_dirty(page); | 2665 | set_page_dirty(page); |
2658 | dirty_page++; | 2666 | dirty_page++; |
@@ -3274,8 +3282,10 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc) | |||
3274 | return -ENOMEM; | 3282 | return -ENOMEM; |
3275 | 3283 | ||
3276 | path = btrfs_alloc_path(); | 3284 | path = btrfs_alloc_path(); |
3277 | if (!path) | 3285 | if (!path) { |
3286 | kfree(cluster); | ||
3278 | return -ENOMEM; | 3287 | return -ENOMEM; |
3288 | } | ||
3279 | 3289 | ||
3280 | rc->extents_found = 0; | 3290 | rc->extents_found = 0; |
3281 | rc->extents_skipped = 0; | 3291 | rc->extents_skipped = 0; |
@@ -3478,7 +3488,7 @@ static struct inode *create_reloc_inode(struct btrfs_fs_info *fs_info, | |||
3478 | key.objectid = objectid; | 3488 | key.objectid = objectid; |
3479 | key.type = BTRFS_INODE_ITEM_KEY; | 3489 | key.type = BTRFS_INODE_ITEM_KEY; |
3480 | key.offset = 0; | 3490 | key.offset = 0; |
3481 | inode = btrfs_iget(root->fs_info->sb, &key, root); | 3491 | inode = btrfs_iget(root->fs_info->sb, &key, root, NULL); |
3482 | BUG_ON(IS_ERR(inode) || is_bad_inode(inode)); | 3492 | BUG_ON(IS_ERR(inode) || is_bad_inode(inode)); |
3483 | BTRFS_I(inode)->index_cnt = group->key.objectid; | 3493 | BTRFS_I(inode)->index_cnt = group->key.objectid; |
3484 | 3494 | ||
@@ -3534,8 +3544,8 @@ int btrfs_relocate_block_group(struct btrfs_root *extent_root, u64 group_start) | |||
3534 | (unsigned long long)rc->block_group->key.objectid, | 3544 | (unsigned long long)rc->block_group->key.objectid, |
3535 | (unsigned long long)rc->block_group->flags); | 3545 | (unsigned long long)rc->block_group->flags); |
3536 | 3546 | ||
3537 | btrfs_start_delalloc_inodes(fs_info->tree_root); | 3547 | btrfs_start_delalloc_inodes(fs_info->tree_root, 0); |
3538 | btrfs_wait_ordered_extents(fs_info->tree_root, 0); | 3548 | btrfs_wait_ordered_extents(fs_info->tree_root, 0, 0); |
3539 | 3549 | ||
3540 | while (1) { | 3550 | while (1) { |
3541 | rc->extents_found = 0; | 3551 | rc->extents_found = 0; |
@@ -3755,6 +3765,8 @@ out: | |||
3755 | BTRFS_DATA_RELOC_TREE_OBJECTID); | 3765 | BTRFS_DATA_RELOC_TREE_OBJECTID); |
3756 | if (IS_ERR(fs_root)) | 3766 | if (IS_ERR(fs_root)) |
3757 | err = PTR_ERR(fs_root); | 3767 | err = PTR_ERR(fs_root); |
3768 | else | ||
3769 | btrfs_orphan_cleanup(fs_root); | ||
3758 | } | 3770 | } |
3759 | return err; | 3771 | return err; |
3760 | } | 3772 | } |