diff options
Diffstat (limited to 'fs/btrfs/relocation.c')
| -rw-r--r-- | fs/btrfs/relocation.c | 38 |
1 files changed, 23 insertions, 15 deletions
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index cfcc93c93a7b..a9728680eca8 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c | |||
| @@ -1561,6 +1561,20 @@ static int invalidate_extent_cache(struct btrfs_root *root, | |||
| 1561 | return 0; | 1561 | return 0; |
| 1562 | } | 1562 | } |
| 1563 | 1563 | ||
| 1564 | static void put_inodes(struct list_head *list) | ||
| 1565 | { | ||
| 1566 | struct inodevec *ivec; | ||
| 1567 | while (!list_empty(list)) { | ||
| 1568 | ivec = list_entry(list->next, struct inodevec, list); | ||
| 1569 | list_del(&ivec->list); | ||
| 1570 | while (ivec->nr > 0) { | ||
| 1571 | ivec->nr--; | ||
| 1572 | iput(ivec->inode[ivec->nr]); | ||
| 1573 | } | ||
| 1574 | kfree(ivec); | ||
| 1575 | } | ||
| 1576 | } | ||
| 1577 | |||
| 1564 | static int find_next_key(struct btrfs_path *path, int level, | 1578 | static int find_next_key(struct btrfs_path *path, int level, |
| 1565 | struct btrfs_key *key) | 1579 | struct btrfs_key *key) |
| 1566 | 1580 | ||
| @@ -1723,6 +1737,11 @@ static noinline_for_stack int merge_reloc_root(struct reloc_control *rc, | |||
| 1723 | 1737 | ||
| 1724 | btrfs_btree_balance_dirty(root, nr); | 1738 | btrfs_btree_balance_dirty(root, nr); |
| 1725 | 1739 | ||
| 1740 | /* | ||
| 1741 | * put inodes outside transaction, otherwise we may deadlock. | ||
| 1742 | */ | ||
| 1743 | put_inodes(&inode_list); | ||
| 1744 | |||
| 1726 | if (replaced && rc->stage == UPDATE_DATA_PTRS) | 1745 | if (replaced && rc->stage == UPDATE_DATA_PTRS) |
| 1727 | invalidate_extent_cache(root, &key, &next_key); | 1746 | invalidate_extent_cache(root, &key, &next_key); |
| 1728 | } | 1747 | } |
| @@ -1752,19 +1771,7 @@ out: | |||
| 1752 | 1771 | ||
| 1753 | btrfs_btree_balance_dirty(root, nr); | 1772 | btrfs_btree_balance_dirty(root, nr); |
| 1754 | 1773 | ||
| 1755 | /* | 1774 | 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 | 1775 | ||
| 1769 | if (replaced && rc->stage == UPDATE_DATA_PTRS) | 1776 | if (replaced && rc->stage == UPDATE_DATA_PTRS) |
| 1770 | invalidate_extent_cache(root, &key, &next_key); | 1777 | invalidate_extent_cache(root, &key, &next_key); |
| @@ -3534,8 +3541,8 @@ int btrfs_relocate_block_group(struct btrfs_root *extent_root, u64 group_start) | |||
| 3534 | (unsigned long long)rc->block_group->key.objectid, | 3541 | (unsigned long long)rc->block_group->key.objectid, |
| 3535 | (unsigned long long)rc->block_group->flags); | 3542 | (unsigned long long)rc->block_group->flags); |
| 3536 | 3543 | ||
| 3537 | btrfs_start_delalloc_inodes(fs_info->tree_root); | 3544 | btrfs_start_delalloc_inodes(fs_info->tree_root, 0); |
| 3538 | btrfs_wait_ordered_extents(fs_info->tree_root, 0); | 3545 | btrfs_wait_ordered_extents(fs_info->tree_root, 0, 0); |
| 3539 | 3546 | ||
| 3540 | while (1) { | 3547 | while (1) { |
| 3541 | rc->extents_found = 0; | 3548 | rc->extents_found = 0; |
| @@ -3755,6 +3762,7 @@ out: | |||
| 3755 | BTRFS_DATA_RELOC_TREE_OBJECTID); | 3762 | BTRFS_DATA_RELOC_TREE_OBJECTID); |
| 3756 | if (IS_ERR(fs_root)) | 3763 | if (IS_ERR(fs_root)) |
| 3757 | err = PTR_ERR(fs_root); | 3764 | err = PTR_ERR(fs_root); |
| 3765 | btrfs_orphan_cleanup(fs_root); | ||
| 3758 | } | 3766 | } |
| 3759 | return err; | 3767 | return err; |
| 3760 | } | 3768 | } |
