Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 22cd2e7d authored by Arne Jansen's avatar Arne Jansen Committed by Chris Mason
Browse files

Btrfs: fix race in run_clustered_refs



With commit

commit d1270cd9
Author: Arne Jansen <sensille@gmx.net>
Date:   Tue Sep 13 15:16:43 2011 +0200

     Btrfs: put back delayed refs that are too new

I added a window where the delayed_ref's head->ref_mod code can diverge
from the sum of the remaining refs, because we release the head->mutex
in the middle. This leads to btrfs_lookup_extent_info returning wrong
numbers. This patch fixes this by adjusting the head's ref_mod with each
delayed ref we run.

Signed-off-by: default avatarArne Jansen <sensille@gmx.net>
Signed-off-by: default avatarChris Mason <chris.mason@fusionio.com>
parent b12a3b1e
Loading
Loading
Loading
Loading
+17 −0
Original line number Original line Diff line number Diff line
@@ -2318,6 +2318,23 @@ static noinline int run_clustered_refs(struct btrfs_trans_handle *trans,
		ref->in_tree = 0;
		ref->in_tree = 0;
		rb_erase(&ref->rb_node, &delayed_refs->root);
		rb_erase(&ref->rb_node, &delayed_refs->root);
		delayed_refs->num_entries--;
		delayed_refs->num_entries--;
		if (locked_ref) {
			/*
			 * when we play the delayed ref, also correct the
			 * ref_mod on head
			 */
			switch (ref->action) {
			case BTRFS_ADD_DELAYED_REF:
			case BTRFS_ADD_DELAYED_EXTENT:
				locked_ref->node.ref_mod -= ref->ref_mod;
				break;
			case BTRFS_DROP_DELAYED_REF:
				locked_ref->node.ref_mod += ref->ref_mod;
				break;
			default:
				WARN_ON(1);
			}
		}
		spin_unlock(&delayed_refs->lock);
		spin_unlock(&delayed_refs->lock);


		ret = run_one_delayed_ref(trans, root, ref, extent_op,
		ret = run_one_delayed_ref(trans, root, ref, extent_op,