summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEdmund Nadolski <enadolski@suse.com>2017-06-28 23:56:58 -0400
committerDavid Sterba <dsterba@suse.com>2017-08-16 08:19:53 -0400
commitbb739cf08e8f32ea0b4a6d2ae22466488182c2fe (patch)
treece7db405a42cbe74ba5f5d782ee26cf90860fbd2
parente0c476b128e37daa37d630dd68da5681e9c16bab (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.c30
-rw-r--r--fs/btrfs/backref.h4
-rw-r--r--fs/btrfs/extent_io.c22
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 */
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;
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);
71int btrfs_check_shared(struct btrfs_trans_handle *trans, 71int 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
75int __init btrfs_prelim_ref_init(void); 73int __init btrfs_prelim_ref_init(void);
76void btrfs_prelim_ref_exit(void); 74void 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
25static struct kmem_cache *extent_state_cache; 24static struct kmem_cache *extent_state_cache;
26static struct kmem_cache *extent_buffer_cache; 25static 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)