mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-01 00:58:39 +02:00 
			
		
		
		
	btrfs: remove delayed_ref_node from ref_head
This is just excessive information in the ref_head, and makes the code complicated. It is a relic from when we had the heads and the refs in the same tree, which is no longer the case. With this removal I've cleaned up a bunch of the cruft around this old assumption as well. Signed-off-by: Josef Bacik <jbacik@fb.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
		
							parent
							
								
									c1103f7a5d
								
							
						
					
					
						commit
						d278850eff
					
				
					 6 changed files with 120 additions and 176 deletions
				
			
		|  | @ -1178,7 +1178,7 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans, | ||||||
| 		head = btrfs_find_delayed_ref_head(delayed_refs, bytenr); | 		head = btrfs_find_delayed_ref_head(delayed_refs, bytenr); | ||||||
| 		if (head) { | 		if (head) { | ||||||
| 			if (!mutex_trylock(&head->mutex)) { | 			if (!mutex_trylock(&head->mutex)) { | ||||||
| 				refcount_inc(&head->node.refs); | 				refcount_inc(&head->refs); | ||||||
| 				spin_unlock(&delayed_refs->lock); | 				spin_unlock(&delayed_refs->lock); | ||||||
| 
 | 
 | ||||||
| 				btrfs_release_path(path); | 				btrfs_release_path(path); | ||||||
|  | @ -1189,7 +1189,7 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans, | ||||||
| 				 */ | 				 */ | ||||||
| 				mutex_lock(&head->mutex); | 				mutex_lock(&head->mutex); | ||||||
| 				mutex_unlock(&head->mutex); | 				mutex_unlock(&head->mutex); | ||||||
| 				btrfs_put_delayed_ref(&head->node); | 				btrfs_put_delayed_ref_head(head); | ||||||
| 				goto again; | 				goto again; | ||||||
| 			} | 			} | ||||||
| 			spin_unlock(&delayed_refs->lock); | 			spin_unlock(&delayed_refs->lock); | ||||||
|  |  | ||||||
|  | @ -96,15 +96,15 @@ static struct btrfs_delayed_ref_head *htree_insert(struct rb_root *root, | ||||||
| 	u64 bytenr; | 	u64 bytenr; | ||||||
| 
 | 
 | ||||||
| 	ins = rb_entry(node, struct btrfs_delayed_ref_head, href_node); | 	ins = rb_entry(node, struct btrfs_delayed_ref_head, href_node); | ||||||
| 	bytenr = ins->node.bytenr; | 	bytenr = ins->bytenr; | ||||||
| 	while (*p) { | 	while (*p) { | ||||||
| 		parent_node = *p; | 		parent_node = *p; | ||||||
| 		entry = rb_entry(parent_node, struct btrfs_delayed_ref_head, | 		entry = rb_entry(parent_node, struct btrfs_delayed_ref_head, | ||||||
| 				 href_node); | 				 href_node); | ||||||
| 
 | 
 | ||||||
| 		if (bytenr < entry->node.bytenr) | 		if (bytenr < entry->bytenr) | ||||||
| 			p = &(*p)->rb_left; | 			p = &(*p)->rb_left; | ||||||
| 		else if (bytenr > entry->node.bytenr) | 		else if (bytenr > entry->bytenr) | ||||||
| 			p = &(*p)->rb_right; | 			p = &(*p)->rb_right; | ||||||
| 		else | 		else | ||||||
| 			return entry; | 			return entry; | ||||||
|  | @ -133,15 +133,15 @@ find_ref_head(struct rb_root *root, u64 bytenr, | ||||||
| 	while (n) { | 	while (n) { | ||||||
| 		entry = rb_entry(n, struct btrfs_delayed_ref_head, href_node); | 		entry = rb_entry(n, struct btrfs_delayed_ref_head, href_node); | ||||||
| 
 | 
 | ||||||
| 		if (bytenr < entry->node.bytenr) | 		if (bytenr < entry->bytenr) | ||||||
| 			n = n->rb_left; | 			n = n->rb_left; | ||||||
| 		else if (bytenr > entry->node.bytenr) | 		else if (bytenr > entry->bytenr) | ||||||
| 			n = n->rb_right; | 			n = n->rb_right; | ||||||
| 		else | 		else | ||||||
| 			return entry; | 			return entry; | ||||||
| 	} | 	} | ||||||
| 	if (entry && return_bigger) { | 	if (entry && return_bigger) { | ||||||
| 		if (bytenr > entry->node.bytenr) { | 		if (bytenr > entry->bytenr) { | ||||||
| 			n = rb_next(&entry->href_node); | 			n = rb_next(&entry->href_node); | ||||||
| 			if (!n) | 			if (!n) | ||||||
| 				n = rb_first(root); | 				n = rb_first(root); | ||||||
|  | @ -164,17 +164,17 @@ int btrfs_delayed_ref_lock(struct btrfs_trans_handle *trans, | ||||||
| 	if (mutex_trylock(&head->mutex)) | 	if (mutex_trylock(&head->mutex)) | ||||||
| 		return 0; | 		return 0; | ||||||
| 
 | 
 | ||||||
| 	refcount_inc(&head->node.refs); | 	refcount_inc(&head->refs); | ||||||
| 	spin_unlock(&delayed_refs->lock); | 	spin_unlock(&delayed_refs->lock); | ||||||
| 
 | 
 | ||||||
| 	mutex_lock(&head->mutex); | 	mutex_lock(&head->mutex); | ||||||
| 	spin_lock(&delayed_refs->lock); | 	spin_lock(&delayed_refs->lock); | ||||||
| 	if (!head->node.in_tree) { | 	if (RB_EMPTY_NODE(&head->href_node)) { | ||||||
| 		mutex_unlock(&head->mutex); | 		mutex_unlock(&head->mutex); | ||||||
| 		btrfs_put_delayed_ref(&head->node); | 		btrfs_put_delayed_ref_head(head); | ||||||
| 		return -EAGAIN; | 		return -EAGAIN; | ||||||
| 	} | 	} | ||||||
| 	btrfs_put_delayed_ref(&head->node); | 	btrfs_put_delayed_ref_head(head); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -183,15 +183,10 @@ static inline void drop_delayed_ref(struct btrfs_trans_handle *trans, | ||||||
| 				    struct btrfs_delayed_ref_head *head, | 				    struct btrfs_delayed_ref_head *head, | ||||||
| 				    struct btrfs_delayed_ref_node *ref) | 				    struct btrfs_delayed_ref_node *ref) | ||||||
| { | { | ||||||
| 	if (btrfs_delayed_ref_is_head(ref)) { |  | ||||||
| 		head = btrfs_delayed_node_to_head(ref); |  | ||||||
| 		rb_erase(&head->href_node, &delayed_refs->href_root); |  | ||||||
| 	} else { |  | ||||||
| 	assert_spin_locked(&head->lock); | 	assert_spin_locked(&head->lock); | ||||||
| 	list_del(&ref->list); | 	list_del(&ref->list); | ||||||
| 	if (!list_empty(&ref->add_list)) | 	if (!list_empty(&ref->add_list)) | ||||||
| 		list_del(&ref->add_list); | 		list_del(&ref->add_list); | ||||||
| 	} |  | ||||||
| 	ref->in_tree = 0; | 	ref->in_tree = 0; | ||||||
| 	btrfs_put_delayed_ref(ref); | 	btrfs_put_delayed_ref(ref); | ||||||
| 	atomic_dec(&delayed_refs->num_entries); | 	atomic_dec(&delayed_refs->num_entries); | ||||||
|  | @ -380,8 +375,8 @@ btrfs_select_ref_head(struct btrfs_trans_handle *trans) | ||||||
| 	head->processing = 1; | 	head->processing = 1; | ||||||
| 	WARN_ON(delayed_refs->num_heads_ready == 0); | 	WARN_ON(delayed_refs->num_heads_ready == 0); | ||||||
| 	delayed_refs->num_heads_ready--; | 	delayed_refs->num_heads_ready--; | ||||||
| 	delayed_refs->run_delayed_start = head->node.bytenr + | 	delayed_refs->run_delayed_start = head->bytenr + | ||||||
| 		head->node.num_bytes; | 		head->num_bytes; | ||||||
| 	return head; | 	return head; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -469,20 +464,16 @@ add_delayed_ref_tail_merge(struct btrfs_trans_handle *trans, | ||||||
|  */ |  */ | ||||||
| static noinline void | static noinline void | ||||||
| update_existing_head_ref(struct btrfs_delayed_ref_root *delayed_refs, | update_existing_head_ref(struct btrfs_delayed_ref_root *delayed_refs, | ||||||
| 			 struct btrfs_delayed_ref_node *existing, | 			 struct btrfs_delayed_ref_head *existing, | ||||||
| 			 struct btrfs_delayed_ref_node *update, | 			 struct btrfs_delayed_ref_head *update, | ||||||
| 			 int *old_ref_mod_ret) | 			 int *old_ref_mod_ret) | ||||||
| { | { | ||||||
| 	struct btrfs_delayed_ref_head *existing_ref; |  | ||||||
| 	struct btrfs_delayed_ref_head *ref; |  | ||||||
| 	int old_ref_mod; | 	int old_ref_mod; | ||||||
| 
 | 
 | ||||||
| 	existing_ref = btrfs_delayed_node_to_head(existing); | 	BUG_ON(existing->is_data != update->is_data); | ||||||
| 	ref = btrfs_delayed_node_to_head(update); |  | ||||||
| 	BUG_ON(existing_ref->is_data != ref->is_data); |  | ||||||
| 
 | 
 | ||||||
| 	spin_lock(&existing_ref->lock); | 	spin_lock(&existing->lock); | ||||||
| 	if (ref->must_insert_reserved) { | 	if (update->must_insert_reserved) { | ||||||
| 		/* if the extent was freed and then
 | 		/* if the extent was freed and then
 | ||||||
| 		 * reallocated before the delayed ref | 		 * reallocated before the delayed ref | ||||||
| 		 * entries were processed, we can end up | 		 * entries were processed, we can end up | ||||||
|  | @ -490,7 +481,7 @@ update_existing_head_ref(struct btrfs_delayed_ref_root *delayed_refs, | ||||||
| 		 * the must_insert_reserved flag set. | 		 * the must_insert_reserved flag set. | ||||||
| 		 * Set it again here | 		 * Set it again here | ||||||
| 		 */ | 		 */ | ||||||
| 		existing_ref->must_insert_reserved = ref->must_insert_reserved; | 		existing->must_insert_reserved = update->must_insert_reserved; | ||||||
| 
 | 
 | ||||||
| 		/*
 | 		/*
 | ||||||
| 		 * update the num_bytes so we make sure the accounting | 		 * update the num_bytes so we make sure the accounting | ||||||
|  | @ -500,22 +491,22 @@ update_existing_head_ref(struct btrfs_delayed_ref_root *delayed_refs, | ||||||
| 
 | 
 | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (ref->extent_op) { | 	if (update->extent_op) { | ||||||
| 		if (!existing_ref->extent_op) { | 		if (!existing->extent_op) { | ||||||
| 			existing_ref->extent_op = ref->extent_op; | 			existing->extent_op = update->extent_op; | ||||||
| 		} else { | 		} else { | ||||||
| 			if (ref->extent_op->update_key) { | 			if (update->extent_op->update_key) { | ||||||
| 				memcpy(&existing_ref->extent_op->key, | 				memcpy(&existing->extent_op->key, | ||||||
| 				       &ref->extent_op->key, | 				       &update->extent_op->key, | ||||||
| 				       sizeof(ref->extent_op->key)); | 				       sizeof(update->extent_op->key)); | ||||||
| 				existing_ref->extent_op->update_key = true; | 				existing->extent_op->update_key = true; | ||||||
| 			} | 			} | ||||||
| 			if (ref->extent_op->update_flags) { | 			if (update->extent_op->update_flags) { | ||||||
| 				existing_ref->extent_op->flags_to_set |= | 				existing->extent_op->flags_to_set |= | ||||||
| 					ref->extent_op->flags_to_set; | 					update->extent_op->flags_to_set; | ||||||
| 				existing_ref->extent_op->update_flags = true; | 				existing->extent_op->update_flags = true; | ||||||
| 			} | 			} | ||||||
| 			btrfs_free_delayed_extent_op(ref->extent_op); | 			btrfs_free_delayed_extent_op(update->extent_op); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	/*
 | 	/*
 | ||||||
|  | @ -523,23 +514,23 @@ update_existing_head_ref(struct btrfs_delayed_ref_root *delayed_refs, | ||||||
| 	 * only need the lock for this case cause we could be processing it | 	 * only need the lock for this case cause we could be processing it | ||||||
| 	 * currently, for refs we just added we know we're a-ok. | 	 * currently, for refs we just added we know we're a-ok. | ||||||
| 	 */ | 	 */ | ||||||
| 	old_ref_mod = existing_ref->total_ref_mod; | 	old_ref_mod = existing->total_ref_mod; | ||||||
| 	if (old_ref_mod_ret) | 	if (old_ref_mod_ret) | ||||||
| 		*old_ref_mod_ret = old_ref_mod; | 		*old_ref_mod_ret = old_ref_mod; | ||||||
| 	existing->ref_mod += update->ref_mod; | 	existing->ref_mod += update->ref_mod; | ||||||
| 	existing_ref->total_ref_mod += update->ref_mod; | 	existing->total_ref_mod += update->ref_mod; | ||||||
| 
 | 
 | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * If we are going to from a positive ref mod to a negative or vice | 	 * If we are going to from a positive ref mod to a negative or vice | ||||||
| 	 * versa we need to make sure to adjust pending_csums accordingly. | 	 * versa we need to make sure to adjust pending_csums accordingly. | ||||||
| 	 */ | 	 */ | ||||||
| 	if (existing_ref->is_data) { | 	if (existing->is_data) { | ||||||
| 		if (existing_ref->total_ref_mod >= 0 && old_ref_mod < 0) | 		if (existing->total_ref_mod >= 0 && old_ref_mod < 0) | ||||||
| 			delayed_refs->pending_csums -= existing->num_bytes; | 			delayed_refs->pending_csums -= existing->num_bytes; | ||||||
| 		if (existing_ref->total_ref_mod < 0 && old_ref_mod >= 0) | 		if (existing->total_ref_mod < 0 && old_ref_mod >= 0) | ||||||
| 			delayed_refs->pending_csums += existing->num_bytes; | 			delayed_refs->pending_csums += existing->num_bytes; | ||||||
| 	} | 	} | ||||||
| 	spin_unlock(&existing_ref->lock); | 	spin_unlock(&existing->lock); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  | @ -550,14 +541,13 @@ update_existing_head_ref(struct btrfs_delayed_ref_root *delayed_refs, | ||||||
| static noinline struct btrfs_delayed_ref_head * | static noinline struct btrfs_delayed_ref_head * | ||||||
| add_delayed_ref_head(struct btrfs_fs_info *fs_info, | add_delayed_ref_head(struct btrfs_fs_info *fs_info, | ||||||
| 		     struct btrfs_trans_handle *trans, | 		     struct btrfs_trans_handle *trans, | ||||||
| 		     struct btrfs_delayed_ref_node *ref, | 		     struct btrfs_delayed_ref_head *head_ref, | ||||||
| 		     struct btrfs_qgroup_extent_record *qrecord, | 		     struct btrfs_qgroup_extent_record *qrecord, | ||||||
| 		     u64 bytenr, u64 num_bytes, u64 ref_root, u64 reserved, | 		     u64 bytenr, u64 num_bytes, u64 ref_root, u64 reserved, | ||||||
| 		     int action, int is_data, int *qrecord_inserted_ret, | 		     int action, int is_data, int *qrecord_inserted_ret, | ||||||
| 		     int *old_ref_mod, int *new_ref_mod) | 		     int *old_ref_mod, int *new_ref_mod) | ||||||
| { | { | ||||||
| 	struct btrfs_delayed_ref_head *existing; | 	struct btrfs_delayed_ref_head *existing; | ||||||
| 	struct btrfs_delayed_ref_head *head_ref = NULL; |  | ||||||
| 	struct btrfs_delayed_ref_root *delayed_refs; | 	struct btrfs_delayed_ref_root *delayed_refs; | ||||||
| 	int count_mod = 1; | 	int count_mod = 1; | ||||||
| 	int must_insert_reserved = 0; | 	int must_insert_reserved = 0; | ||||||
|  | @ -593,26 +583,21 @@ add_delayed_ref_head(struct btrfs_fs_info *fs_info, | ||||||
| 
 | 
 | ||||||
| 	delayed_refs = &trans->transaction->delayed_refs; | 	delayed_refs = &trans->transaction->delayed_refs; | ||||||
| 
 | 
 | ||||||
| 	/* first set the basic ref node struct up */ | 	refcount_set(&head_ref->refs, 1); | ||||||
| 	refcount_set(&ref->refs, 1); | 	head_ref->bytenr = bytenr; | ||||||
| 	ref->bytenr = bytenr; | 	head_ref->num_bytes = num_bytes; | ||||||
| 	ref->num_bytes = num_bytes; | 	head_ref->ref_mod = count_mod; | ||||||
| 	ref->ref_mod = count_mod; |  | ||||||
| 	ref->type  = 0; |  | ||||||
| 	ref->action  = 0; |  | ||||||
| 	ref->is_head = 1; |  | ||||||
| 	ref->in_tree = 1; |  | ||||||
| 	ref->seq = 0; |  | ||||||
| 
 |  | ||||||
| 	head_ref = btrfs_delayed_node_to_head(ref); |  | ||||||
| 	head_ref->must_insert_reserved = must_insert_reserved; | 	head_ref->must_insert_reserved = must_insert_reserved; | ||||||
| 	head_ref->is_data = is_data; | 	head_ref->is_data = is_data; | ||||||
| 	INIT_LIST_HEAD(&head_ref->ref_list); | 	INIT_LIST_HEAD(&head_ref->ref_list); | ||||||
| 	INIT_LIST_HEAD(&head_ref->ref_add_list); | 	INIT_LIST_HEAD(&head_ref->ref_add_list); | ||||||
|  | 	RB_CLEAR_NODE(&head_ref->href_node); | ||||||
| 	head_ref->processing = 0; | 	head_ref->processing = 0; | ||||||
| 	head_ref->total_ref_mod = count_mod; | 	head_ref->total_ref_mod = count_mod; | ||||||
| 	head_ref->qgroup_reserved = 0; | 	head_ref->qgroup_reserved = 0; | ||||||
| 	head_ref->qgroup_ref_root = 0; | 	head_ref->qgroup_ref_root = 0; | ||||||
|  | 	spin_lock_init(&head_ref->lock); | ||||||
|  | 	mutex_init(&head_ref->mutex); | ||||||
| 
 | 
 | ||||||
| 	/* Record qgroup extent info if provided */ | 	/* Record qgroup extent info if provided */ | ||||||
| 	if (qrecord) { | 	if (qrecord) { | ||||||
|  | @ -632,17 +617,14 @@ add_delayed_ref_head(struct btrfs_fs_info *fs_info, | ||||||
| 			qrecord_inserted = 1; | 			qrecord_inserted = 1; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	spin_lock_init(&head_ref->lock); | 	trace_add_delayed_ref_head(fs_info, head_ref, action); | ||||||
| 	mutex_init(&head_ref->mutex); |  | ||||||
| 
 |  | ||||||
| 	trace_add_delayed_ref_head(fs_info, ref, head_ref, action); |  | ||||||
| 
 | 
 | ||||||
| 	existing = htree_insert(&delayed_refs->href_root, | 	existing = htree_insert(&delayed_refs->href_root, | ||||||
| 				&head_ref->href_node); | 				&head_ref->href_node); | ||||||
| 	if (existing) { | 	if (existing) { | ||||||
| 		WARN_ON(ref_root && reserved && existing->qgroup_ref_root | 		WARN_ON(ref_root && reserved && existing->qgroup_ref_root | ||||||
| 			&& existing->qgroup_reserved); | 			&& existing->qgroup_reserved); | ||||||
| 		update_existing_head_ref(delayed_refs, &existing->node, ref, | 		update_existing_head_ref(delayed_refs, existing, head_ref, | ||||||
| 					 old_ref_mod); | 					 old_ref_mod); | ||||||
| 		/*
 | 		/*
 | ||||||
| 		 * we've updated the existing ref, free the newly | 		 * we've updated the existing ref, free the newly | ||||||
|  | @ -821,7 +803,7 @@ int btrfs_add_delayed_tree_ref(struct btrfs_fs_info *fs_info, | ||||||
| 	 * insert both the head node and the new ref without dropping | 	 * insert both the head node and the new ref without dropping | ||||||
| 	 * the spin lock | 	 * the spin lock | ||||||
| 	 */ | 	 */ | ||||||
| 	head_ref = add_delayed_ref_head(fs_info, trans, &head_ref->node, record, | 	head_ref = add_delayed_ref_head(fs_info, trans, head_ref, record, | ||||||
| 					bytenr, num_bytes, 0, 0, action, 0, | 					bytenr, num_bytes, 0, 0, action, 0, | ||||||
| 					&qrecord_inserted, old_ref_mod, | 					&qrecord_inserted, old_ref_mod, | ||||||
| 					new_ref_mod); | 					new_ref_mod); | ||||||
|  | @ -888,7 +870,7 @@ int btrfs_add_delayed_data_ref(struct btrfs_fs_info *fs_info, | ||||||
| 	 * insert both the head node and the new ref without dropping | 	 * insert both the head node and the new ref without dropping | ||||||
| 	 * the spin lock | 	 * the spin lock | ||||||
| 	 */ | 	 */ | ||||||
| 	head_ref = add_delayed_ref_head(fs_info, trans, &head_ref->node, record, | 	head_ref = add_delayed_ref_head(fs_info, trans, head_ref, record, | ||||||
| 					bytenr, num_bytes, ref_root, reserved, | 					bytenr, num_bytes, ref_root, reserved, | ||||||
| 					action, 1, &qrecord_inserted, | 					action, 1, &qrecord_inserted, | ||||||
| 					old_ref_mod, new_ref_mod); | 					old_ref_mod, new_ref_mod); | ||||||
|  | @ -920,7 +902,7 @@ int btrfs_add_delayed_extent_op(struct btrfs_fs_info *fs_info, | ||||||
| 	delayed_refs = &trans->transaction->delayed_refs; | 	delayed_refs = &trans->transaction->delayed_refs; | ||||||
| 	spin_lock(&delayed_refs->lock); | 	spin_lock(&delayed_refs->lock); | ||||||
| 
 | 
 | ||||||
| 	add_delayed_ref_head(fs_info, trans, &head_ref->node, NULL, bytenr, | 	add_delayed_ref_head(fs_info, trans, head_ref, NULL, bytenr, | ||||||
| 			     num_bytes, 0, 0, BTRFS_UPDATE_DELAYED_HEAD, | 			     num_bytes, 0, 0, BTRFS_UPDATE_DELAYED_HEAD, | ||||||
| 			     extent_op->is_data, NULL, NULL, NULL); | 			     extent_op->is_data, NULL, NULL, NULL); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -26,15 +26,6 @@ | ||||||
| #define BTRFS_ADD_DELAYED_EXTENT 3 /* record a full extent allocation */ | #define BTRFS_ADD_DELAYED_EXTENT 3 /* record a full extent allocation */ | ||||||
| #define BTRFS_UPDATE_DELAYED_HEAD 4 /* not changing ref count on head ref */ | #define BTRFS_UPDATE_DELAYED_HEAD 4 /* not changing ref count on head ref */ | ||||||
| 
 | 
 | ||||||
| /*
 |  | ||||||
|  * XXX: Qu: I really hate the design that ref_head and tree/data ref shares the |  | ||||||
|  * same ref_node structure. |  | ||||||
|  * Ref_head is in a higher logic level than tree/data ref, and duplicated |  | ||||||
|  * bytenr/num_bytes in ref_node is really a waste or memory, they should be |  | ||||||
|  * referred from ref_head. |  | ||||||
|  * This gets more disgusting after we use list to store tree/data ref in |  | ||||||
|  * ref_head. Must clean this mess up later. |  | ||||||
|  */ |  | ||||||
| struct btrfs_delayed_ref_node { | struct btrfs_delayed_ref_node { | ||||||
| 	/*data/tree ref use list, stored in ref_head->ref_list. */ | 	/*data/tree ref use list, stored in ref_head->ref_list. */ | ||||||
| 	struct list_head list; | 	struct list_head list; | ||||||
|  | @ -91,8 +82,9 @@ struct btrfs_delayed_extent_op { | ||||||
|  * reference count modifications we've queued up. |  * reference count modifications we've queued up. | ||||||
|  */ |  */ | ||||||
| struct btrfs_delayed_ref_head { | struct btrfs_delayed_ref_head { | ||||||
| 	struct btrfs_delayed_ref_node node; | 	u64 bytenr; | ||||||
| 
 | 	u64 num_bytes; | ||||||
|  | 	refcount_t refs; | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * the mutex is held while running the refs, and it is also | 	 * the mutex is held while running the refs, and it is also | ||||||
| 	 * held when checking the sum of reference modifications. | 	 * held when checking the sum of reference modifications. | ||||||
|  | @ -115,6 +107,14 @@ struct btrfs_delayed_ref_head { | ||||||
| 	 */ | 	 */ | ||||||
| 	int total_ref_mod; | 	int total_ref_mod; | ||||||
| 
 | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * This is the current outstanding mod references for this bytenr.  This | ||||||
|  | 	 * is used with lookup_extent_info to get an accurate reference count | ||||||
|  | 	 * for a bytenr, so it is adjusted as delayed refs are run so that any | ||||||
|  | 	 * on disk reference count + ref_mod is accurate. | ||||||
|  | 	 */ | ||||||
|  | 	int ref_mod; | ||||||
|  | 
 | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * For qgroup reserved space freeing. | 	 * For qgroup reserved space freeing. | ||||||
| 	 * | 	 * | ||||||
|  | @ -234,15 +234,18 @@ static inline void btrfs_put_delayed_ref(struct btrfs_delayed_ref_node *ref) | ||||||
| 		case BTRFS_SHARED_DATA_REF_KEY: | 		case BTRFS_SHARED_DATA_REF_KEY: | ||||||
| 			kmem_cache_free(btrfs_delayed_data_ref_cachep, ref); | 			kmem_cache_free(btrfs_delayed_data_ref_cachep, ref); | ||||||
| 			break; | 			break; | ||||||
| 		case 0: |  | ||||||
| 			kmem_cache_free(btrfs_delayed_ref_head_cachep, ref); |  | ||||||
| 			break; |  | ||||||
| 		default: | 		default: | ||||||
| 			BUG(); | 			BUG(); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static inline void btrfs_put_delayed_ref_head(struct btrfs_delayed_ref_head *head) | ||||||
|  | { | ||||||
|  | 	if (refcount_dec_and_test(&head->refs)) | ||||||
|  | 		kmem_cache_free(btrfs_delayed_ref_head_cachep, head); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| int btrfs_add_delayed_tree_ref(struct btrfs_fs_info *fs_info, | int btrfs_add_delayed_tree_ref(struct btrfs_fs_info *fs_info, | ||||||
| 			       struct btrfs_trans_handle *trans, | 			       struct btrfs_trans_handle *trans, | ||||||
| 			       u64 bytenr, u64 num_bytes, u64 parent, | 			       u64 bytenr, u64 num_bytes, u64 parent, | ||||||
|  | @ -282,36 +285,18 @@ int btrfs_check_delayed_seq(struct btrfs_fs_info *fs_info, | ||||||
| 			    struct btrfs_delayed_ref_root *delayed_refs, | 			    struct btrfs_delayed_ref_root *delayed_refs, | ||||||
| 			    u64 seq); | 			    u64 seq); | ||||||
| 
 | 
 | ||||||
| /*
 |  | ||||||
|  * a node might live in a head or a regular ref, this lets you |  | ||||||
|  * test for the proper type to use. |  | ||||||
|  */ |  | ||||||
| static int btrfs_delayed_ref_is_head(struct btrfs_delayed_ref_node *node) |  | ||||||
| { |  | ||||||
| 	return node->is_head; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /*
 | /*
 | ||||||
|  * helper functions to cast a node into its container |  * helper functions to cast a node into its container | ||||||
|  */ |  */ | ||||||
| static inline struct btrfs_delayed_tree_ref * | static inline struct btrfs_delayed_tree_ref * | ||||||
| btrfs_delayed_node_to_tree_ref(struct btrfs_delayed_ref_node *node) | btrfs_delayed_node_to_tree_ref(struct btrfs_delayed_ref_node *node) | ||||||
| { | { | ||||||
| 	WARN_ON(btrfs_delayed_ref_is_head(node)); |  | ||||||
| 	return container_of(node, struct btrfs_delayed_tree_ref, node); | 	return container_of(node, struct btrfs_delayed_tree_ref, node); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static inline struct btrfs_delayed_data_ref * | static inline struct btrfs_delayed_data_ref * | ||||||
| btrfs_delayed_node_to_data_ref(struct btrfs_delayed_ref_node *node) | btrfs_delayed_node_to_data_ref(struct btrfs_delayed_ref_node *node) | ||||||
| { | { | ||||||
| 	WARN_ON(btrfs_delayed_ref_is_head(node)); |  | ||||||
| 	return container_of(node, struct btrfs_delayed_data_ref, node); | 	return container_of(node, struct btrfs_delayed_data_ref, node); | ||||||
| } | } | ||||||
| 
 |  | ||||||
| static inline struct btrfs_delayed_ref_head * |  | ||||||
| btrfs_delayed_node_to_head(struct btrfs_delayed_ref_node *node) |  | ||||||
| { |  | ||||||
| 	WARN_ON(!btrfs_delayed_ref_is_head(node)); |  | ||||||
| 	return container_of(node, struct btrfs_delayed_ref_head, node); |  | ||||||
| } |  | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -4121,12 +4121,12 @@ static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans, | ||||||
| 		head = rb_entry(node, struct btrfs_delayed_ref_head, | 		head = rb_entry(node, struct btrfs_delayed_ref_head, | ||||||
| 				href_node); | 				href_node); | ||||||
| 		if (!mutex_trylock(&head->mutex)) { | 		if (!mutex_trylock(&head->mutex)) { | ||||||
| 			refcount_inc(&head->node.refs); | 			refcount_inc(&head->refs); | ||||||
| 			spin_unlock(&delayed_refs->lock); | 			spin_unlock(&delayed_refs->lock); | ||||||
| 
 | 
 | ||||||
| 			mutex_lock(&head->mutex); | 			mutex_lock(&head->mutex); | ||||||
| 			mutex_unlock(&head->mutex); | 			mutex_unlock(&head->mutex); | ||||||
| 			btrfs_put_delayed_ref(&head->node); | 			btrfs_put_delayed_ref_head(head); | ||||||
| 			spin_lock(&delayed_refs->lock); | 			spin_lock(&delayed_refs->lock); | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
|  | @ -4147,16 +4147,16 @@ static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans, | ||||||
| 		if (head->processing == 0) | 		if (head->processing == 0) | ||||||
| 			delayed_refs->num_heads_ready--; | 			delayed_refs->num_heads_ready--; | ||||||
| 		atomic_dec(&delayed_refs->num_entries); | 		atomic_dec(&delayed_refs->num_entries); | ||||||
| 		head->node.in_tree = 0; |  | ||||||
| 		rb_erase(&head->href_node, &delayed_refs->href_root); | 		rb_erase(&head->href_node, &delayed_refs->href_root); | ||||||
|  | 		RB_CLEAR_NODE(&head->href_node); | ||||||
| 		spin_unlock(&head->lock); | 		spin_unlock(&head->lock); | ||||||
| 		spin_unlock(&delayed_refs->lock); | 		spin_unlock(&delayed_refs->lock); | ||||||
| 		mutex_unlock(&head->mutex); | 		mutex_unlock(&head->mutex); | ||||||
| 
 | 
 | ||||||
| 		if (pin_bytes) | 		if (pin_bytes) | ||||||
| 			btrfs_pin_extent(fs_info, head->node.bytenr, | 			btrfs_pin_extent(fs_info, head->bytenr, | ||||||
| 					 head->node.num_bytes, 1); | 					 head->num_bytes, 1); | ||||||
| 		btrfs_put_delayed_ref(&head->node); | 		btrfs_put_delayed_ref_head(head); | ||||||
| 		cond_resched(); | 		cond_resched(); | ||||||
| 		spin_lock(&delayed_refs->lock); | 		spin_lock(&delayed_refs->lock); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -912,7 +912,7 @@ int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans, | ||||||
| 	head = btrfs_find_delayed_ref_head(delayed_refs, bytenr); | 	head = btrfs_find_delayed_ref_head(delayed_refs, bytenr); | ||||||
| 	if (head) { | 	if (head) { | ||||||
| 		if (!mutex_trylock(&head->mutex)) { | 		if (!mutex_trylock(&head->mutex)) { | ||||||
| 			refcount_inc(&head->node.refs); | 			refcount_inc(&head->refs); | ||||||
| 			spin_unlock(&delayed_refs->lock); | 			spin_unlock(&delayed_refs->lock); | ||||||
| 
 | 
 | ||||||
| 			btrfs_release_path(path); | 			btrfs_release_path(path); | ||||||
|  | @ -923,7 +923,7 @@ int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans, | ||||||
| 			 */ | 			 */ | ||||||
| 			mutex_lock(&head->mutex); | 			mutex_lock(&head->mutex); | ||||||
| 			mutex_unlock(&head->mutex); | 			mutex_unlock(&head->mutex); | ||||||
| 			btrfs_put_delayed_ref(&head->node); | 			btrfs_put_delayed_ref_head(head); | ||||||
| 			goto search_again; | 			goto search_again; | ||||||
| 		} | 		} | ||||||
| 		spin_lock(&head->lock); | 		spin_lock(&head->lock); | ||||||
|  | @ -932,7 +932,7 @@ int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans, | ||||||
| 		else | 		else | ||||||
| 			BUG_ON(num_refs == 0); | 			BUG_ON(num_refs == 0); | ||||||
| 
 | 
 | ||||||
| 		num_refs += head->node.ref_mod; | 		num_refs += head->ref_mod; | ||||||
| 		spin_unlock(&head->lock); | 		spin_unlock(&head->lock); | ||||||
| 		mutex_unlock(&head->mutex); | 		mutex_unlock(&head->mutex); | ||||||
| 	} | 	} | ||||||
|  | @ -2337,7 +2337,7 @@ static void __run_delayed_extent_op(struct btrfs_delayed_extent_op *extent_op, | ||||||
| 
 | 
 | ||||||
| static int run_delayed_extent_op(struct btrfs_trans_handle *trans, | static int run_delayed_extent_op(struct btrfs_trans_handle *trans, | ||||||
| 				 struct btrfs_fs_info *fs_info, | 				 struct btrfs_fs_info *fs_info, | ||||||
| 				 struct btrfs_delayed_ref_node *node, | 				 struct btrfs_delayed_ref_head *head, | ||||||
| 				 struct btrfs_delayed_extent_op *extent_op) | 				 struct btrfs_delayed_extent_op *extent_op) | ||||||
| { | { | ||||||
| 	struct btrfs_key key; | 	struct btrfs_key key; | ||||||
|  | @ -2359,14 +2359,14 @@ static int run_delayed_extent_op(struct btrfs_trans_handle *trans, | ||||||
| 	if (!path) | 	if (!path) | ||||||
| 		return -ENOMEM; | 		return -ENOMEM; | ||||||
| 
 | 
 | ||||||
| 	key.objectid = node->bytenr; | 	key.objectid = head->bytenr; | ||||||
| 
 | 
 | ||||||
| 	if (metadata) { | 	if (metadata) { | ||||||
| 		key.type = BTRFS_METADATA_ITEM_KEY; | 		key.type = BTRFS_METADATA_ITEM_KEY; | ||||||
| 		key.offset = extent_op->level; | 		key.offset = extent_op->level; | ||||||
| 	} else { | 	} else { | ||||||
| 		key.type = BTRFS_EXTENT_ITEM_KEY; | 		key.type = BTRFS_EXTENT_ITEM_KEY; | ||||||
| 		key.offset = node->num_bytes; | 		key.offset = head->num_bytes; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| again: | again: | ||||||
|  | @ -2383,17 +2383,17 @@ static int run_delayed_extent_op(struct btrfs_trans_handle *trans, | ||||||
| 				path->slots[0]--; | 				path->slots[0]--; | ||||||
| 				btrfs_item_key_to_cpu(path->nodes[0], &key, | 				btrfs_item_key_to_cpu(path->nodes[0], &key, | ||||||
| 						      path->slots[0]); | 						      path->slots[0]); | ||||||
| 				if (key.objectid == node->bytenr && | 				if (key.objectid == head->bytenr && | ||||||
| 				    key.type == BTRFS_EXTENT_ITEM_KEY && | 				    key.type == BTRFS_EXTENT_ITEM_KEY && | ||||||
| 				    key.offset == node->num_bytes) | 				    key.offset == head->num_bytes) | ||||||
| 					ret = 0; | 					ret = 0; | ||||||
| 			} | 			} | ||||||
| 			if (ret > 0) { | 			if (ret > 0) { | ||||||
| 				btrfs_release_path(path); | 				btrfs_release_path(path); | ||||||
| 				metadata = 0; | 				metadata = 0; | ||||||
| 
 | 
 | ||||||
| 				key.objectid = node->bytenr; | 				key.objectid = head->bytenr; | ||||||
| 				key.offset = node->num_bytes; | 				key.offset = head->num_bytes; | ||||||
| 				key.type = BTRFS_EXTENT_ITEM_KEY; | 				key.type = BTRFS_EXTENT_ITEM_KEY; | ||||||
| 				goto again; | 				goto again; | ||||||
| 			} | 			} | ||||||
|  | @ -2562,7 +2562,7 @@ static int cleanup_extent_op(struct btrfs_trans_handle *trans, | ||||||
| 		return 0; | 		return 0; | ||||||
| 	} | 	} | ||||||
| 	spin_unlock(&head->lock); | 	spin_unlock(&head->lock); | ||||||
| 	ret = run_delayed_extent_op(trans, fs_info, &head->node, extent_op); | 	ret = run_delayed_extent_op(trans, fs_info, head, extent_op); | ||||||
| 	btrfs_free_delayed_extent_op(extent_op); | 	btrfs_free_delayed_extent_op(extent_op); | ||||||
| 	return ret ? ret : 1; | 	return ret ? ret : 1; | ||||||
| } | } | ||||||
|  | @ -2597,39 +2597,37 @@ static int cleanup_ref_head(struct btrfs_trans_handle *trans, | ||||||
| 		spin_unlock(&delayed_refs->lock); | 		spin_unlock(&delayed_refs->lock); | ||||||
| 		return 1; | 		return 1; | ||||||
| 	} | 	} | ||||||
| 	head->node.in_tree = 0; |  | ||||||
| 	delayed_refs->num_heads--; | 	delayed_refs->num_heads--; | ||||||
| 	rb_erase(&head->href_node, &delayed_refs->href_root); | 	rb_erase(&head->href_node, &delayed_refs->href_root); | ||||||
|  | 	RB_CLEAR_NODE(&head->href_node); | ||||||
| 	spin_unlock(&delayed_refs->lock); | 	spin_unlock(&delayed_refs->lock); | ||||||
| 	spin_unlock(&head->lock); | 	spin_unlock(&head->lock); | ||||||
| 	atomic_dec(&delayed_refs->num_entries); | 	atomic_dec(&delayed_refs->num_entries); | ||||||
| 
 | 
 | ||||||
| 	trace_run_delayed_ref_head(fs_info, &head->node, head, | 	trace_run_delayed_ref_head(fs_info, head, 0); | ||||||
| 				   head->node.action); |  | ||||||
| 
 | 
 | ||||||
| 	if (head->total_ref_mod < 0) { | 	if (head->total_ref_mod < 0) { | ||||||
| 		struct btrfs_block_group_cache *cache; | 		struct btrfs_block_group_cache *cache; | ||||||
| 
 | 
 | ||||||
| 		cache = btrfs_lookup_block_group(fs_info, head->node.bytenr); | 		cache = btrfs_lookup_block_group(fs_info, head->bytenr); | ||||||
| 		ASSERT(cache); | 		ASSERT(cache); | ||||||
| 		percpu_counter_add(&cache->space_info->total_bytes_pinned, | 		percpu_counter_add(&cache->space_info->total_bytes_pinned, | ||||||
| 				   -head->node.num_bytes); | 				   -head->num_bytes); | ||||||
| 		btrfs_put_block_group(cache); | 		btrfs_put_block_group(cache); | ||||||
| 
 | 
 | ||||||
| 		if (head->is_data) { | 		if (head->is_data) { | ||||||
| 			spin_lock(&delayed_refs->lock); | 			spin_lock(&delayed_refs->lock); | ||||||
| 			delayed_refs->pending_csums -= head->node.num_bytes; | 			delayed_refs->pending_csums -= head->num_bytes; | ||||||
| 			spin_unlock(&delayed_refs->lock); | 			spin_unlock(&delayed_refs->lock); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (head->must_insert_reserved) { | 	if (head->must_insert_reserved) { | ||||||
| 		btrfs_pin_extent(fs_info, head->node.bytenr, | 		btrfs_pin_extent(fs_info, head->bytenr, | ||||||
| 				 head->node.num_bytes, 1); | 				 head->num_bytes, 1); | ||||||
| 		if (head->is_data) { | 		if (head->is_data) { | ||||||
| 			ret = btrfs_del_csums(trans, fs_info, | 			ret = btrfs_del_csums(trans, fs_info, head->bytenr, | ||||||
| 					      head->node.bytenr, | 					      head->num_bytes); | ||||||
| 					      head->node.num_bytes); |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -2637,7 +2635,7 @@ static int cleanup_ref_head(struct btrfs_trans_handle *trans, | ||||||
| 	btrfs_qgroup_free_delayed_ref(fs_info, head->qgroup_ref_root, | 	btrfs_qgroup_free_delayed_ref(fs_info, head->qgroup_ref_root, | ||||||
| 				      head->qgroup_reserved); | 				      head->qgroup_reserved); | ||||||
| 	btrfs_delayed_ref_unlock(head); | 	btrfs_delayed_ref_unlock(head); | ||||||
| 	btrfs_put_delayed_ref(&head->node); | 	btrfs_put_delayed_ref_head(head); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -2751,10 +2749,10 @@ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, | ||||||
| 		switch (ref->action) { | 		switch (ref->action) { | ||||||
| 		case BTRFS_ADD_DELAYED_REF: | 		case BTRFS_ADD_DELAYED_REF: | ||||||
| 		case BTRFS_ADD_DELAYED_EXTENT: | 		case BTRFS_ADD_DELAYED_EXTENT: | ||||||
| 			locked_ref->node.ref_mod -= ref->ref_mod; | 			locked_ref->ref_mod -= ref->ref_mod; | ||||||
| 			break; | 			break; | ||||||
| 		case BTRFS_DROP_DELAYED_REF: | 		case BTRFS_DROP_DELAYED_REF: | ||||||
| 			locked_ref->node.ref_mod += ref->ref_mod; | 			locked_ref->ref_mod += ref->ref_mod; | ||||||
| 			break; | 			break; | ||||||
| 		default: | 		default: | ||||||
| 			WARN_ON(1); | 			WARN_ON(1); | ||||||
|  | @ -3087,33 +3085,16 @@ int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, | ||||||
| 			spin_unlock(&delayed_refs->lock); | 			spin_unlock(&delayed_refs->lock); | ||||||
| 			goto out; | 			goto out; | ||||||
| 		} | 		} | ||||||
| 
 |  | ||||||
| 		while (node) { |  | ||||||
| 		head = rb_entry(node, struct btrfs_delayed_ref_head, | 		head = rb_entry(node, struct btrfs_delayed_ref_head, | ||||||
| 				href_node); | 				href_node); | ||||||
| 			if (btrfs_delayed_ref_is_head(&head->node)) { | 		refcount_inc(&head->refs); | ||||||
| 				struct btrfs_delayed_ref_node *ref; |  | ||||||
| 
 |  | ||||||
| 				ref = &head->node; |  | ||||||
| 				refcount_inc(&ref->refs); |  | ||||||
| 
 |  | ||||||
| 		spin_unlock(&delayed_refs->lock); | 		spin_unlock(&delayed_refs->lock); | ||||||
| 				/*
 | 
 | ||||||
| 				 * Mutex was contended, block until it's | 		/* Mutex was contended, block until it's released and retry. */ | ||||||
| 				 * released and try again |  | ||||||
| 				 */ |  | ||||||
| 		mutex_lock(&head->mutex); | 		mutex_lock(&head->mutex); | ||||||
| 		mutex_unlock(&head->mutex); | 		mutex_unlock(&head->mutex); | ||||||
| 
 | 
 | ||||||
| 				btrfs_put_delayed_ref(ref); | 		btrfs_put_delayed_ref_head(head); | ||||||
| 				cond_resched(); |  | ||||||
| 				goto again; |  | ||||||
| 			} else { |  | ||||||
| 				WARN_ON(1); |  | ||||||
| 			} |  | ||||||
| 			node = rb_next(node); |  | ||||||
| 		} |  | ||||||
| 		spin_unlock(&delayed_refs->lock); |  | ||||||
| 		cond_resched(); | 		cond_resched(); | ||||||
| 		goto again; | 		goto again; | ||||||
| 	} | 	} | ||||||
|  | @ -3171,7 +3152,7 @@ static noinline int check_delayed_ref(struct btrfs_root *root, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (!mutex_trylock(&head->mutex)) { | 	if (!mutex_trylock(&head->mutex)) { | ||||||
| 		refcount_inc(&head->node.refs); | 		refcount_inc(&head->refs); | ||||||
| 		spin_unlock(&delayed_refs->lock); | 		spin_unlock(&delayed_refs->lock); | ||||||
| 
 | 
 | ||||||
| 		btrfs_release_path(path); | 		btrfs_release_path(path); | ||||||
|  | @ -3182,7 +3163,7 @@ static noinline int check_delayed_ref(struct btrfs_root *root, | ||||||
| 		 */ | 		 */ | ||||||
| 		mutex_lock(&head->mutex); | 		mutex_lock(&head->mutex); | ||||||
| 		mutex_unlock(&head->mutex); | 		mutex_unlock(&head->mutex); | ||||||
| 		btrfs_put_delayed_ref(&head->node); | 		btrfs_put_delayed_ref_head(head); | ||||||
| 		return -EAGAIN; | 		return -EAGAIN; | ||||||
| 	} | 	} | ||||||
| 	spin_unlock(&delayed_refs->lock); | 	spin_unlock(&delayed_refs->lock); | ||||||
|  | @ -7235,9 +7216,8 @@ static noinline int check_ref_cleanup(struct btrfs_trans_handle *trans, | ||||||
| 	 * at this point we have a head with no other entries.  Go | 	 * at this point we have a head with no other entries.  Go | ||||||
| 	 * ahead and process it. | 	 * ahead and process it. | ||||||
| 	 */ | 	 */ | ||||||
| 	head->node.in_tree = 0; |  | ||||||
| 	rb_erase(&head->href_node, &delayed_refs->href_root); | 	rb_erase(&head->href_node, &delayed_refs->href_root); | ||||||
| 
 | 	RB_CLEAR_NODE(&head->href_node); | ||||||
| 	atomic_dec(&delayed_refs->num_entries); | 	atomic_dec(&delayed_refs->num_entries); | ||||||
| 
 | 
 | ||||||
| 	/*
 | 	/*
 | ||||||
|  | @ -7256,7 +7236,7 @@ static noinline int check_ref_cleanup(struct btrfs_trans_handle *trans, | ||||||
| 		ret = 1; | 		ret = 1; | ||||||
| 
 | 
 | ||||||
| 	mutex_unlock(&head->mutex); | 	mutex_unlock(&head->mutex); | ||||||
| 	btrfs_put_delayed_ref(&head->node); | 	btrfs_put_delayed_ref_head(head); | ||||||
| 	return ret; | 	return ret; | ||||||
| out: | out: | ||||||
| 	spin_unlock(&head->lock); | 	spin_unlock(&head->lock); | ||||||
|  |  | ||||||
|  | @ -798,11 +798,10 @@ DEFINE_EVENT(btrfs_delayed_data_ref,  run_delayed_data_ref, | ||||||
| DECLARE_EVENT_CLASS(btrfs_delayed_ref_head, | DECLARE_EVENT_CLASS(btrfs_delayed_ref_head, | ||||||
| 
 | 
 | ||||||
| 	TP_PROTO(const struct btrfs_fs_info *fs_info, | 	TP_PROTO(const struct btrfs_fs_info *fs_info, | ||||||
| 		 const struct btrfs_delayed_ref_node *ref, |  | ||||||
| 		 const struct btrfs_delayed_ref_head *head_ref, | 		 const struct btrfs_delayed_ref_head *head_ref, | ||||||
| 		 int action), | 		 int action), | ||||||
| 
 | 
 | ||||||
| 	TP_ARGS(fs_info, ref, head_ref, action), | 	TP_ARGS(fs_info, head_ref, action), | ||||||
| 
 | 
 | ||||||
| 	TP_STRUCT__entry_btrfs( | 	TP_STRUCT__entry_btrfs( | ||||||
| 		__field(	u64,  bytenr		) | 		__field(	u64,  bytenr		) | ||||||
|  | @ -812,8 +811,8 @@ DECLARE_EVENT_CLASS(btrfs_delayed_ref_head, | ||||||
| 	), | 	), | ||||||
| 
 | 
 | ||||||
| 	TP_fast_assign_btrfs(fs_info, | 	TP_fast_assign_btrfs(fs_info, | ||||||
| 		__entry->bytenr		= ref->bytenr; | 		__entry->bytenr		= head_ref->bytenr; | ||||||
| 		__entry->num_bytes	= ref->num_bytes; | 		__entry->num_bytes	= head_ref->num_bytes; | ||||||
| 		__entry->action		= action; | 		__entry->action		= action; | ||||||
| 		__entry->is_data	= head_ref->is_data; | 		__entry->is_data	= head_ref->is_data; | ||||||
| 	), | 	), | ||||||
|  | @ -828,21 +827,19 @@ DECLARE_EVENT_CLASS(btrfs_delayed_ref_head, | ||||||
| DEFINE_EVENT(btrfs_delayed_ref_head,  add_delayed_ref_head, | DEFINE_EVENT(btrfs_delayed_ref_head,  add_delayed_ref_head, | ||||||
| 
 | 
 | ||||||
| 	TP_PROTO(const struct btrfs_fs_info *fs_info, | 	TP_PROTO(const struct btrfs_fs_info *fs_info, | ||||||
| 		 const struct btrfs_delayed_ref_node *ref, |  | ||||||
| 		 const struct btrfs_delayed_ref_head *head_ref, | 		 const struct btrfs_delayed_ref_head *head_ref, | ||||||
| 		 int action), | 		 int action), | ||||||
| 
 | 
 | ||||||
| 	TP_ARGS(fs_info, ref, head_ref, action) | 	TP_ARGS(fs_info, head_ref, action) | ||||||
| ); | ); | ||||||
| 
 | 
 | ||||||
| DEFINE_EVENT(btrfs_delayed_ref_head,  run_delayed_ref_head, | DEFINE_EVENT(btrfs_delayed_ref_head,  run_delayed_ref_head, | ||||||
| 
 | 
 | ||||||
| 	TP_PROTO(const struct btrfs_fs_info *fs_info, | 	TP_PROTO(const struct btrfs_fs_info *fs_info, | ||||||
| 		 const struct btrfs_delayed_ref_node *ref, |  | ||||||
| 		 const struct btrfs_delayed_ref_head *head_ref, | 		 const struct btrfs_delayed_ref_head *head_ref, | ||||||
| 		 int action), | 		 int action), | ||||||
| 
 | 
 | ||||||
| 	TP_ARGS(fs_info, ref, head_ref, action) | 	TP_ARGS(fs_info, head_ref, action) | ||||||
| ); | ); | ||||||
| 
 | 
 | ||||||
| #define show_chunk_type(type)					\ | #define show_chunk_type(type)					\ | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Josef Bacik
						Josef Bacik