aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fusionio.com>2013-08-22 17:03:29 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-10-13 19:08:34 -0400
commit322d9a97c490b890975e0d61f2b034bc18ea1100 (patch)
treee7fcb8dced28d6522a1e9b52d97e16294e6a2f4e
parent0ac5762ca876c8554cea6e8a05422d561b98947f (diff)
Btrfs: remove ourselves from the cluster list under lock
commit b8d0c69b9469ffd33df30fee3e990f2d4aa68a09 upstream. A user was reporting weird warnings from btrfs_put_delayed_ref() and I noticed that we were doing this list_del_init() on our head ref outside of delayed_refs->lock. This is a problem if we have people still on the list, we could end up modifying old pointers and such. Fix this by removing us from the list before we do our run_delayed_ref on our head ref. Thanks, Signed-off-by: Josef Bacik <jbacik@fusionio.com> Signed-off-by: Chris Mason <chris.mason@fusionio.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--fs/btrfs/extent-tree.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 0b272d068337..3b6d20bc2388 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -2402,6 +2402,8 @@ static noinline int run_clustered_refs(struct btrfs_trans_handle *trans,
2402 default: 2402 default:
2403 WARN_ON(1); 2403 WARN_ON(1);
2404 } 2404 }
2405 } else {
2406 list_del_init(&locked_ref->cluster);
2405 } 2407 }
2406 spin_unlock(&delayed_refs->lock); 2408 spin_unlock(&delayed_refs->lock);
2407 2409
@@ -2424,7 +2426,6 @@ static noinline int run_clustered_refs(struct btrfs_trans_handle *trans,
2424 * list before we release it. 2426 * list before we release it.
2425 */ 2427 */
2426 if (btrfs_delayed_ref_is_head(ref)) { 2428 if (btrfs_delayed_ref_is_head(ref)) {
2427 list_del_init(&locked_ref->cluster);
2428 btrfs_delayed_ref_unlock(locked_ref); 2429 btrfs_delayed_ref_unlock(locked_ref);
2429 locked_ref = NULL; 2430 locked_ref = NULL;
2430 } 2431 }