diff options
author | Edmund Nadolski <enadolski@suse.com> | 2017-06-28 23:56:58 -0400 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2017-08-16 08:19:53 -0400 |
commit | bb739cf08e8f32ea0b4a6d2ae22466488182c2fe (patch) | |
tree | ce7db405a42cbe74ba5f5d782ee26cf90860fbd2 | |
parent | e0c476b128e37daa37d630dd68da5681e9c16bab (diff) |
btrfs: btrfs_check_shared should manage its own transaction
Commit afce772e87c3 ("btrfs: fix check_shared for fiemap ioctl") added
transaction semantics around calls to btrfs_check_shared() in order to
provide accurate accounting of delayed refs. The transaction management
should be done inside btrfs_check_shared(), so that callers do not need
to manage transactions individually.
Signed-off-by: Edmund Nadolski <enadolski@suse.com>
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
-rw-r--r-- | fs/btrfs/backref.c | 30 | ||||
-rw-r--r-- | fs/btrfs/backref.h | 4 | ||||
-rw-r--r-- | fs/btrfs/extent_io.c | 22 |
3 files changed, 23 insertions, 33 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 | */ |
1593 | int btrfs_check_shared(struct btrfs_trans_handle *trans, | 1594 | int 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; |
diff --git a/fs/btrfs/backref.h b/fs/btrfs/backref.h index 9c41fbac3009..f9428aaaa77a 100644 --- a/fs/btrfs/backref.h +++ b/fs/btrfs/backref.h | |||
@@ -68,9 +68,7 @@ int btrfs_find_one_extref(struct btrfs_root *root, u64 inode_objectid, | |||
68 | u64 start_off, struct btrfs_path *path, | 68 | u64 start_off, struct btrfs_path *path, |
69 | struct btrfs_inode_extref **ret_extref, | 69 | struct btrfs_inode_extref **ret_extref, |
70 | u64 *found_off); | 70 | u64 *found_off); |
71 | int btrfs_check_shared(struct btrfs_trans_handle *trans, | 71 | int btrfs_check_shared(struct btrfs_root *root, u64 inum, u64 bytenr); |
72 | struct btrfs_fs_info *fs_info, u64 root_objectid, | ||
73 | u64 inum, u64 bytenr); | ||
74 | 72 | ||
75 | int __init btrfs_prelim_ref_init(void); | 73 | int __init btrfs_prelim_ref_init(void); |
76 | void btrfs_prelim_ref_exit(void); | 74 | void btrfs_prelim_ref_exit(void); |
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index d6f761b4fae0..7dd1b2dc7c68 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
@@ -20,7 +20,6 @@ | |||
20 | #include "locking.h" | 20 | #include "locking.h" |
21 | #include "rcu-string.h" | 21 | #include "rcu-string.h" |
22 | #include "backref.h" | 22 | #include "backref.h" |
23 | #include "transaction.h" | ||
24 | 23 | ||
25 | static struct kmem_cache *extent_state_cache; | 24 | static struct kmem_cache *extent_state_cache; |
26 | static struct kmem_cache *extent_buffer_cache; | 25 | static struct kmem_cache *extent_buffer_cache; |
@@ -4606,36 +4605,21 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | |||
4606 | flags |= (FIEMAP_EXTENT_DELALLOC | | 4605 | flags |= (FIEMAP_EXTENT_DELALLOC | |
4607 | FIEMAP_EXTENT_UNKNOWN); | 4606 | FIEMAP_EXTENT_UNKNOWN); |
4608 | } else if (fieinfo->fi_extents_max) { | 4607 | } else if (fieinfo->fi_extents_max) { |
4609 | struct btrfs_trans_handle *trans; | ||
4610 | |||
4611 | u64 bytenr = em->block_start - | 4608 | u64 bytenr = em->block_start - |
4612 | (em->start - em->orig_start); | 4609 | (em->start - em->orig_start); |
4613 | 4610 | ||
4614 | disko = em->block_start + offset_in_extent; | 4611 | disko = em->block_start + offset_in_extent; |
4615 | 4612 | ||
4616 | /* | 4613 | /* |
4617 | * We need a trans handle to get delayed refs | ||
4618 | */ | ||
4619 | trans = btrfs_join_transaction(root); | ||
4620 | /* | ||
4621 | * It's OK if we can't start a trans we can still check | ||
4622 | * from commit_root | ||
4623 | */ | ||
4624 | if (IS_ERR(trans)) | ||
4625 | trans = NULL; | ||
4626 | |||
4627 | /* | ||
4628 | * As btrfs supports shared space, this information | 4614 | * As btrfs supports shared space, this information |
4629 | * can be exported to userspace tools via | 4615 | * can be exported to userspace tools via |
4630 | * flag FIEMAP_EXTENT_SHARED. If fi_extents_max == 0 | 4616 | * flag FIEMAP_EXTENT_SHARED. If fi_extents_max == 0 |
4631 | * then we're just getting a count and we can skip the | 4617 | * then we're just getting a count and we can skip the |
4632 | * lookup stuff. | 4618 | * lookup stuff. |
4633 | */ | 4619 | */ |
4634 | ret = btrfs_check_shared(trans, root->fs_info, | 4620 | ret = btrfs_check_shared(root, |
4635 | root->objectid, | 4621 | btrfs_ino(BTRFS_I(inode)), |
4636 | btrfs_ino(BTRFS_I(inode)), bytenr); | 4622 | bytenr); |
4637 | if (trans) | ||
4638 | btrfs_end_transaction(trans); | ||
4639 | if (ret < 0) | 4623 | if (ret < 0) |
4640 | goto out_free; | 4624 | goto out_free; |
4641 | if (ret) | 4625 | if (ret) |