diff options
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r-- | fs/btrfs/extent-tree.c | 20 |
1 files changed, 17 insertions, 3 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 646b9148ca21..3181759da1cf 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -1590,13 +1590,17 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, | |||
1590 | } | 1590 | } |
1591 | 1591 | ||
1592 | static int pin_down_bytes(struct btrfs_root *root, u64 bytenr, u32 num_bytes, | 1592 | static int pin_down_bytes(struct btrfs_root *root, u64 bytenr, u32 num_bytes, |
1593 | int pending) | 1593 | int is_data, int pending) |
1594 | { | 1594 | { |
1595 | int err = 0; | 1595 | int err = 0; |
1596 | 1596 | ||
1597 | WARN_ON(!mutex_is_locked(&root->fs_info->alloc_mutex)); | 1597 | WARN_ON(!mutex_is_locked(&root->fs_info->alloc_mutex)); |
1598 | if (!pending) { | 1598 | if (!pending) { |
1599 | struct extent_buffer *buf; | 1599 | struct extent_buffer *buf; |
1600 | |||
1601 | if (is_data) | ||
1602 | goto pinit; | ||
1603 | |||
1600 | buf = btrfs_find_tree_block(root, bytenr, num_bytes); | 1604 | buf = btrfs_find_tree_block(root, bytenr, num_bytes); |
1601 | if (buf) { | 1605 | if (buf) { |
1602 | /* we can reuse a block if it hasn't been written | 1606 | /* we can reuse a block if it hasn't been written |
@@ -1624,6 +1628,7 @@ static int pin_down_bytes(struct btrfs_root *root, u64 bytenr, u32 num_bytes, | |||
1624 | } | 1628 | } |
1625 | free_extent_buffer(buf); | 1629 | free_extent_buffer(buf); |
1626 | } | 1630 | } |
1631 | pinit: | ||
1627 | btrfs_update_pinned_extents(root, bytenr, num_bytes, 1); | 1632 | btrfs_update_pinned_extents(root, bytenr, num_bytes, 1); |
1628 | } else { | 1633 | } else { |
1629 | set_extent_bits(&root->fs_info->pending_del, | 1634 | set_extent_bits(&root->fs_info->pending_del, |
@@ -1744,7 +1749,8 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1744 | #endif | 1749 | #endif |
1745 | 1750 | ||
1746 | if (pin) { | 1751 | if (pin) { |
1747 | ret = pin_down_bytes(root, bytenr, num_bytes, 0); | 1752 | ret = pin_down_bytes(root, bytenr, num_bytes, |
1753 | owner_objectid >= BTRFS_FIRST_FREE_OBJECTID, 0); | ||
1748 | if (ret > 0) | 1754 | if (ret > 0) |
1749 | mark_free = 1; | 1755 | mark_free = 1; |
1750 | BUG_ON(ret < 0); | 1756 | BUG_ON(ret < 0); |
@@ -1862,9 +1868,17 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans, | |||
1862 | ref_generation = 0; | 1868 | ref_generation = 0; |
1863 | 1869 | ||
1864 | if (root == extent_root) { | 1870 | if (root == extent_root) { |
1865 | pin_down_bytes(root, bytenr, num_bytes, 1); | 1871 | pin_down_bytes(root, bytenr, num_bytes, 0, 1); |
1866 | return 0; | 1872 | return 0; |
1867 | } | 1873 | } |
1874 | /* if metadata always pin */ | ||
1875 | if (owner_objectid < BTRFS_FIRST_FREE_OBJECTID) | ||
1876 | pin = 1; | ||
1877 | |||
1878 | /* if data pin when any transaction has committed this */ | ||
1879 | if (ref_generation != trans->transid) | ||
1880 | pin = 1; | ||
1881 | |||
1868 | ret = __free_extent(trans, root, bytenr, num_bytes, root_objectid, | 1882 | ret = __free_extent(trans, root, bytenr, num_bytes, root_objectid, |
1869 | ref_generation, owner_objectid, owner_offset, | 1883 | ref_generation, owner_objectid, owner_offset, |
1870 | pin, pin == 0); | 1884 | pin, pin == 0); |