summaryrefslogtreecommitdiffstats
path: root/fs/btrfs/backref.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/backref.c')
-rw-r--r--fs/btrfs/backref.c30
1 files changed, 19 insertions, 11 deletions
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
index 3725277f6e08..35cfa388dc0b 100644
--- a/fs/btrfs/backref.c
+++ b/fs/btrfs/backref.c
@@ -1580,20 +1580,21 @@ int btrfs_find_all_roots(struct btrfs_trans_handle *trans,
1580/** 1580/**
1581 * btrfs_check_shared - tell us whether an extent is shared 1581 * btrfs_check_shared - tell us whether an extent is shared
1582 * 1582 *
1583 * @trans: optional trans handle
1584 *
1585 * btrfs_check_shared uses the backref walking code but will short 1583 * btrfs_check_shared uses the backref walking code but will short
1586 * circuit as soon as it finds a root or inode that doesn't match the 1584 * circuit as soon as it finds a root or inode that doesn't match the
1587 * one passed in. This provides a significant performance benefit for 1585 * one passed in. This provides a significant performance benefit for
1588 * callers (such as fiemap) which want to know whether the extent is 1586 * callers (such as fiemap) which want to know whether the extent is
1589 * shared but do not need a ref count. 1587 * shared but do not need a ref count.
1590 * 1588 *
1589 * This attempts to allocate a transaction in order to account for
1590 * delayed refs, but continues on even when the alloc fails.
1591 *
1591 * Return: 0 if extent is not shared, 1 if it is shared, < 0 on error. 1592 * Return: 0 if extent is not shared, 1 if it is shared, < 0 on error.
1592 */ 1593 */
1593int btrfs_check_shared(struct btrfs_trans_handle *trans, 1594int btrfs_check_shared(struct btrfs_root *root, u64 inum, u64 bytenr)
1594 struct btrfs_fs_info *fs_info, u64 root_objectid,
1595 u64 inum, u64 bytenr)
1596{ 1595{
1596 struct btrfs_fs_info *fs_info = root->fs_info;
1597 struct btrfs_trans_handle *trans;
1597 struct ulist *tmp = NULL; 1598 struct ulist *tmp = NULL;
1598 struct ulist *roots = NULL; 1599 struct ulist *roots = NULL;
1599 struct ulist_iterator uiter; 1600 struct ulist_iterator uiter;
@@ -1609,14 +1610,18 @@ int btrfs_check_shared(struct btrfs_trans_handle *trans,
1609 return -ENOMEM; 1610 return -ENOMEM;
1610 } 1611 }
1611 1612
1612 if (trans) 1613 trans = btrfs_join_transaction(root);
1613 btrfs_get_tree_mod_seq(fs_info, &elem); 1614 if (IS_ERR(trans)) {
1614 else 1615 trans = NULL;
1615 down_read(&fs_info->commit_root_sem); 1616 down_read(&fs_info->commit_root_sem);
1617 } else {
1618 btrfs_get_tree_mod_seq(fs_info, &elem);
1619 }
1620
1616 ULIST_ITER_INIT(&uiter); 1621 ULIST_ITER_INIT(&uiter);
1617 while (1) { 1622 while (1) {
1618 ret = find_parent_nodes(trans, fs_info, bytenr, elem.seq, tmp, 1623 ret = find_parent_nodes(trans, fs_info, bytenr, elem.seq, tmp,
1619 roots, NULL, root_objectid, inum, 1); 1624 roots, NULL, root->objectid, inum, 1);
1620 if (ret == BACKREF_FOUND_SHARED) { 1625 if (ret == BACKREF_FOUND_SHARED) {
1621 /* this is the only condition under which we return 1 */ 1626 /* this is the only condition under which we return 1 */
1622 ret = 1; 1627 ret = 1;
@@ -1631,10 +1636,13 @@ int btrfs_check_shared(struct btrfs_trans_handle *trans,
1631 bytenr = node->val; 1636 bytenr = node->val;
1632 cond_resched(); 1637 cond_resched();
1633 } 1638 }
1634 if (trans) 1639
1640 if (trans) {
1635 btrfs_put_tree_mod_seq(fs_info, &elem); 1641 btrfs_put_tree_mod_seq(fs_info, &elem);
1636 else 1642 btrfs_end_transaction(trans);
1643 } else {
1637 up_read(&fs_info->commit_root_sem); 1644 up_read(&fs_info->commit_root_sem);
1645 }
1638 ulist_free(tmp); 1646 ulist_free(tmp);
1639 ulist_free(roots); 1647 ulist_free(roots);
1640 return ret; 1648 return ret;