]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
btrfs: simplify obtaining a delayed ref head
authorFilipe Manana <fdmanana@suse.com>
Mon, 21 Oct 2024 11:40:08 +0000 (12:40 +0100)
committerDavid Sterba <dsterba@suse.com>
Mon, 11 Nov 2024 13:34:20 +0000 (14:34 +0100)
Instead of doing it in two steps outside of delayed-ref.c, leaking low
level details such as locking, move the logic entirely to delayed-ref.c
under btrfs_select_ref_head(), reducing code and making things simpler
for the caller.

Reviewed-by: Boris Burkov <boris@bur.io>
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/delayed-ref.c
fs/btrfs/delayed-ref.h
fs/btrfs/extent-tree.c

index 8392cb366700e0ca42b3fb3ca75ace3233d6657b..fdecdd02db946c93603f0b1d321e134b6ec55767 100644 (file)
@@ -431,8 +431,8 @@ static struct btrfs_delayed_ref_head *find_ref_head(
        return NULL;
 }
 
-bool btrfs_delayed_ref_lock(struct btrfs_delayed_ref_root *delayed_refs,
-                           struct btrfs_delayed_ref_head *head)
+static bool btrfs_delayed_ref_lock(struct btrfs_delayed_ref_root *delayed_refs,
+                                  struct btrfs_delayed_ref_head *head)
 {
        lockdep_assert_held(&delayed_refs->lock);
        if (mutex_trylock(&head->mutex))
@@ -561,8 +561,9 @@ struct btrfs_delayed_ref_head *btrfs_select_ref_head(
                struct btrfs_delayed_ref_root *delayed_refs)
 {
        struct btrfs_delayed_ref_head *head;
+       bool locked;
 
-       lockdep_assert_held(&delayed_refs->lock);
+       spin_lock(&delayed_refs->lock);
 again:
        head = find_ref_head(delayed_refs, delayed_refs->run_delayed_start,
                             true);
@@ -570,16 +571,20 @@ again:
                delayed_refs->run_delayed_start = 0;
                head = find_first_ref_head(delayed_refs);
        }
-       if (!head)
+       if (!head) {
+               spin_unlock(&delayed_refs->lock);
                return NULL;
+       }
 
        while (head->processing) {
                struct rb_node *node;
 
                node = rb_next(&head->href_node);
                if (!node) {
-                       if (delayed_refs->run_delayed_start == 0)
+                       if (delayed_refs->run_delayed_start == 0) {
+                               spin_unlock(&delayed_refs->lock);
                                return NULL;
+                       }
                        delayed_refs->run_delayed_start = 0;
                        goto again;
                }
@@ -592,6 +597,18 @@ again:
        delayed_refs->num_heads_ready--;
        delayed_refs->run_delayed_start = head->bytenr +
                head->num_bytes;
+
+       locked = btrfs_delayed_ref_lock(delayed_refs, 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 (!locked)
+               return ERR_PTR(-EAGAIN);
+
        return head;
 }
 
index 04730c6502126b533ac896c973bab5cbd2cbce46..956fbe5d69849e06dfc516d2ef99a42ea699275b 100644 (file)
@@ -369,8 +369,6 @@ void btrfs_merge_delayed_refs(struct btrfs_fs_info *fs_info,
 struct btrfs_delayed_ref_head *
 btrfs_find_delayed_ref_head(struct btrfs_delayed_ref_root *delayed_refs,
                            u64 bytenr);
-bool btrfs_delayed_ref_lock(struct btrfs_delayed_ref_root *delayed_refs,
-                           struct btrfs_delayed_ref_head *head);
 static inline void btrfs_delayed_ref_unlock(struct btrfs_delayed_ref_head *head)
 {
        mutex_unlock(&head->mutex);
index b9f455ae8788a4042c26c7fd517bbbe469125e06..887706e87524aa31dd9ab5c2c31490d9b8c79a43 100644 (file)
@@ -1953,39 +1953,6 @@ static int cleanup_ref_head(struct btrfs_trans_handle *trans,
        return ret;
 }
 
-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;
-       bool locked;
-
-       spin_lock(&delayed_refs->lock);
-       head = btrfs_select_ref_head(delayed_refs);
-       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
-        */
-       locked = btrfs_delayed_ref_lock(delayed_refs, 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 (!locked)
-               head = ERR_PTR(-EAGAIN);
-
-       return head;
-}
-
 static int btrfs_run_delayed_refs_for_head(struct btrfs_trans_handle *trans,
                                           struct btrfs_delayed_ref_head *locked_ref,
                                           u64 *bytes_released)
@@ -2092,7 +2059,7 @@ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
 
        do {
                if (!locked_ref) {
-                       locked_ref = btrfs_obtain_ref_head(trans);
+                       locked_ref = btrfs_select_ref_head(delayed_refs);
                        if (IS_ERR_OR_NULL(locked_ref)) {
                                if (PTR_ERR(locked_ref) == -EAGAIN) {
                                        continue;