diff options
author | Nikolay Borisov <nborisov@suse.com> | 2018-08-15 10:39:54 +0300 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2018-10-15 17:23:34 +0200 |
commit | b1cdbcb53a6edd84d50b72117d49a350575bbe6a (patch) | |
tree | 2feca4dbba95ee7d382768b7ef21bbe630865129 /fs/btrfs/extent-tree.c | |
parent | b2fa11547bc1693a8dd8e7379dd4e43d31f49c50 (diff) | |
download | linux-b1cdbcb53a6edd84d50b72117d49a350575bbe6a.tar.bz2 |
btrfs: Factor out ref head locking code in __btrfs_run_delayed_refs
This is in preparation to refactor the giant loop in
__btrfs_run_delayed_refs. As a first step define a new function
which implements acquiring a reference to a btrfs_delayed_refs_head and
use it. No functional changes.
Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r-- | fs/btrfs/extent-tree.c | 53 |
1 files changed, 36 insertions, 17 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 26fb9cbf3807..ee027a7fe7f4 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -2502,6 +2502,39 @@ static int cleanup_ref_head(struct btrfs_trans_handle *trans, return 0; } +static struct btrfs_delayed_ref_head *btrfs_obtain_ref_head( + struct btrfs_trans_handle *trans) +{ + struct btrfs_delayed_ref_root *delayed_refs = + &trans->transaction->delayed_refs; + struct btrfs_delayed_ref_head *head = NULL; + int ret; + + spin_lock(&delayed_refs->lock); + head = btrfs_select_ref_head(trans); + if (!head) { + spin_unlock(&delayed_refs->lock); + return head; + } + + /* + * Grab the lock that says we are going to process all the refs for + * this head + */ + ret = btrfs_delayed_ref_lock(trans, head); + spin_unlock(&delayed_refs->lock); + + /* + * We may have dropped the spin lock to get the head mutex lock, and + * that might have given someone else time to free the head. If that's + * true, it has been removed from our list and we can move on. + */ + if (ret == -EAGAIN) + head = ERR_PTR(-EAGAIN); + + return head; +} + /* * Returns 0 on success or if called with an already aborted transaction. * Returns -ENOMEM or -EIO on failure and will abort the transaction. @@ -2526,24 +2559,10 @@ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, if (count >= nr) break; - spin_lock(&delayed_refs->lock); - locked_ref = btrfs_select_ref_head(trans); - if (!locked_ref) { - spin_unlock(&delayed_refs->lock); + locked_ref = btrfs_obtain_ref_head(trans); + if (!locked_ref) break; - } - - /* grab the lock that says we are going to process - * all the refs for this head */ - ret = btrfs_delayed_ref_lock(trans, locked_ref); - spin_unlock(&delayed_refs->lock); - /* - * we may have dropped the spin lock to get the head - * mutex lock, and that might have given someone else - * time to free the head. If that's true, it has been - * removed from our list and we can move on. - */ - if (ret == -EAGAIN) { + else if (PTR_ERR(locked_ref) == -EAGAIN) { locked_ref = NULL; count++; continue; |