Re: FAILED: patch "[PATCH] Btrfs: fix regression running delayed references when using" failed to apply to 4.2-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




On 12/11/2015 04:54 PM, gregkh@xxxxxxxxxxxxxxxxxxx wrote:
> 
> The patch below does not apply to the 4.2-stable tree.
> If someone wants it applied there, or to any other stable or longterm
> tree, then please email the backport, including the original git commit
> id to <stable@xxxxxxxxxxxxxxx>.

Greg, please find attached a version of the patch that applies against
4.2.7.
Thanks.

> 
> thanks,
> 
> greg k-h
> 
> ------------------ original commit in Linus's tree ------------------
> 
> From b06c4bf5c874a57254b197f53ddf588e7a24a2bf Mon Sep 17 00:00:00 2001
> From: Filipe Manana <fdmanana@xxxxxxxx>
> Date: Fri, 23 Oct 2015 07:52:54 +0100
> Subject: [PATCH] Btrfs: fix regression running delayed references when using
>  qgroups
> MIME-Version: 1.0
> Content-Type: text/plain; charset=UTF-8
> Content-Transfer-Encoding: 8bit
> 
> In the kernel 4.2 merge window we had a big changes to the implementation
> of delayed references and qgroups which made the no_quota field of delayed
> references not used anymore. More specifically the no_quota field is not
> used anymore as of:
> 
>   commit 0ed4792af0e8 ("btrfs: qgroup: Switch to new extent-oriented qgroup mechanism.")
> 
> Leaving the no_quota field actually prevents delayed references from
> getting merged, which in turn cause the following BUG_ON(), at
> fs/btrfs/extent-tree.c, to be hit when qgroups are enabled:
> 
>   static int run_delayed_tree_ref(...)
>   {
>      (...)
>      BUG_ON(node->ref_mod != 1);
>      (...)
>   }
> 
> This happens on a scenario like the following:
> 
>   1) Ref1 bytenr X, action = BTRFS_ADD_DELAYED_REF, no_quota = 1, added.
> 
>   2) Ref2 bytenr X, action = BTRFS_DROP_DELAYED_REF, no_quota = 0, added.
>      It's not merged with Ref1 because Ref1->no_quota != Ref2->no_quota.
> 
>   3) Ref3 bytenr X, action = BTRFS_ADD_DELAYED_REF, no_quota = 1, added.
>      It's not merged with the reference at the tail of the list of refs
>      for bytenr X because the reference at the tail, Ref2 is incompatible
>      due to Ref2->no_quota != Ref3->no_quota.
> 
>   4) Ref4 bytenr X, action = BTRFS_DROP_DELAYED_REF, no_quota = 0, added.
>      It's not merged with the reference at the tail of the list of refs
>      for bytenr X because the reference at the tail, Ref3 is incompatible
>      due to Ref3->no_quota != Ref4->no_quota.
> 
>   5) We run delayed references, trigger merging of delayed references,
>      through __btrfs_run_delayed_refs() -> btrfs_merge_delayed_refs().
> 
>   6) Ref1 and Ref3 are merged as Ref1->no_quota = Ref3->no_quota and
>      all other conditions are satisfied too. So Ref1 gets a ref_mod
>      value of 2.
> 
>   7) Ref2 and Ref4 are merged as Ref2->no_quota = Ref4->no_quota and
>      all other conditions are satisfied too. So Ref2 gets a ref_mod
>      value of 2.
> 
>   8) Ref1 and Ref2 aren't merged, because they have different values
>      for their no_quota field.
> 
>   9) Delayed reference Ref1 is picked for running (select_delayed_ref()
>      always prefers references with an action == BTRFS_ADD_DELAYED_REF).
>      So run_delayed_tree_ref() is called for Ref1 which triggers the
>      BUG_ON because Ref1->red_mod != 1 (equals 2).
> 
> So fix this by removing the no_quota field, as it's not used anymore as
> of commit 0ed4792af0e8 ("btrfs: qgroup: Switch to new extent-oriented
> qgroup mechanism.").
> 
> The use of no_quota was also buggy in at least two places:
> 
> 1) At delayed-refs.c:btrfs_add_delayed_tree_ref() - we were setting
>    no_quota to 0 instead of 1 when the following condition was true:
>    is_fstree(ref_root) || !fs_info->quota_enabled
> 
> 2) At extent-tree.c:__btrfs_inc_extent_ref() - we were attempting to
>    reset a node's no_quota when the condition "!is_fstree(root_objectid)
>    || !root->fs_info->quota_enabled" was true but we did it only in
>    an unused local stack variable, that is, we never reset the no_quota
>    value in the node itself.
> 
> This fixes the remainder of problems several people have been having when
> running delayed references, mostly while a balance is running in parallel,
> on a 4.2+ kernel.
> 
> Very special thanks to Stéphane Lesimple for helping debugging this issue
> and testing this fix on his multi terabyte filesystem (which took more
> than one day to balance alone, plus fsck, etc).
> 
> Also, this fixes deadlock issue when using the clone ioctl with qgroups
> enabled, as reported by Elias Probst in the mailing list. The deadlock
> happens because after calling btrfs_insert_empty_item we have our path
> holding a write lock on a leaf of the fs/subvol tree and then before
> releasing the path we called check_ref() which did backref walking, when
> qgroups are enabled, and tried to read lock the same leaf. The trace for
> this case is the following:
> 
>   INFO: task systemd-nspawn:6095 blocked for more than 120 seconds.
>   (...)
>   Call Trace:
>     [<ffffffff86999201>] schedule+0x74/0x83
>     [<ffffffff863ef64c>] btrfs_tree_read_lock+0xc0/0xea
>     [<ffffffff86137ed7>] ? wait_woken+0x74/0x74
>     [<ffffffff8639f0a7>] btrfs_search_old_slot+0x51a/0x810
>     [<ffffffff863a129b>] btrfs_next_old_leaf+0xdf/0x3ce
>     [<ffffffff86413a00>] ? ulist_add_merge+0x1b/0x127
>     [<ffffffff86411688>] __resolve_indirect_refs+0x62a/0x667
>     [<ffffffff863ef546>] ? btrfs_clear_lock_blocking_rw+0x78/0xbe
>     [<ffffffff864122d3>] find_parent_nodes+0xaf3/0xfc6
>     [<ffffffff86412838>] __btrfs_find_all_roots+0x92/0xf0
>     [<ffffffff864128f2>] btrfs_find_all_roots+0x45/0x65
>     [<ffffffff8639a75b>] ? btrfs_get_tree_mod_seq+0x2b/0x88
>     [<ffffffff863e852e>] check_ref+0x64/0xc4
>     [<ffffffff863e9e01>] btrfs_clone+0x66e/0xb5d
>     [<ffffffff863ea77f>] btrfs_ioctl_clone+0x48f/0x5bb
>     [<ffffffff86048a68>] ? native_sched_clock+0x28/0x77
>     [<ffffffff863ed9b0>] btrfs_ioctl+0xabc/0x25cb
>   (...)
> 
> The problem goes away by eleminating check_ref(), which no longer is
> needed as its purpose was to get a value for the no_quota field of
> a delayed reference (this patch removes the no_quota field as mentioned
> earlier).
> 
> Reported-by: Stéphane Lesimple <stephane_btrfs@xxxxxxxxxxx>
> Tested-by: Stéphane Lesimple <stephane_btrfs@xxxxxxxxxxx>
> Reported-by: Elias Probst <mail@xxxxxxxxxxxxxx>
> Reported-by: Peter Becker <floyd.net@xxxxxxxxx>
> Reported-by: Malte Schröder <malte@xxxxxxxx>
> Reported-by: Derek Dongray <derek@xxxxxxxxxxxxx>
> Reported-by: Erkki Seppala <flux-btrfs@xxxxxxxxxx>
> Cc: stable@xxxxxxxxxxxxxxx  # 4.2+
> Signed-off-by: Filipe Manana <fdmanana@xxxxxxxx>
> Reviewed-by: Qu Wenruo <quwenruo@xxxxxxxxxxxxxx>
> 
> diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
> index bc3c711e82f2..3fa3c3b7bb66 100644
> --- a/fs/btrfs/ctree.h
> +++ b/fs/btrfs/ctree.h
> @@ -3422,7 +3422,7 @@ int btrfs_set_disk_extent_flags(struct btrfs_trans_handle *trans,
>  int btrfs_free_extent(struct btrfs_trans_handle *trans,
>  		      struct btrfs_root *root,
>  		      u64 bytenr, u64 num_bytes, u64 parent, u64 root_objectid,
> -		      u64 owner, u64 offset, int no_quota);
> +		      u64 owner, u64 offset);
>  
>  int btrfs_free_reserved_extent(struct btrfs_root *root, u64 start, u64 len,
>  			       int delalloc);
> @@ -3435,7 +3435,7 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans,
>  int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
>  			 struct btrfs_root *root,
>  			 u64 bytenr, u64 num_bytes, u64 parent,
> -			 u64 root_objectid, u64 owner, u64 offset, int no_quota);
> +			 u64 root_objectid, u64 owner, u64 offset);
>  
>  int btrfs_start_dirty_block_groups(struct btrfs_trans_handle *trans,
>  				   struct btrfs_root *root);
> diff --git a/fs/btrfs/delayed-ref.c b/fs/btrfs/delayed-ref.c
> index 2f4158034c24..1c3588a70ce6 100644
> --- a/fs/btrfs/delayed-ref.c
> +++ b/fs/btrfs/delayed-ref.c
> @@ -220,7 +220,7 @@ static bool merge_ref(struct btrfs_trans_handle *trans,
>  		if (seq && next->seq >= seq)
>  			goto next;
>  
> -		if (next->type != ref->type || next->no_quota != ref->no_quota)
> +		if (next->type != ref->type)
>  			goto next;
>  
>  		if ((ref->type == BTRFS_TREE_BLOCK_REF_KEY ||
> @@ -405,8 +405,7 @@ add_delayed_ref_tail_merge(struct btrfs_trans_handle *trans,
>  	exist = list_entry(href->ref_list.prev, struct btrfs_delayed_ref_node,
>  			   list);
>  	/* No need to compare bytenr nor is_head */
> -	if (exist->type != ref->type || exist->no_quota != ref->no_quota ||
> -	    exist->seq != ref->seq)
> +	if (exist->type != ref->type || exist->seq != ref->seq)
>  		goto add_tail;
>  
>  	if ((exist->type == BTRFS_TREE_BLOCK_REF_KEY ||
> @@ -639,7 +638,7 @@ add_delayed_tree_ref(struct btrfs_fs_info *fs_info,
>  		     struct btrfs_delayed_ref_head *head_ref,
>  		     struct btrfs_delayed_ref_node *ref, u64 bytenr,
>  		     u64 num_bytes, u64 parent, u64 ref_root, int level,
> -		     int action, int no_quota)
> +		     int action)
>  {
>  	struct btrfs_delayed_tree_ref *full_ref;
>  	struct btrfs_delayed_ref_root *delayed_refs;
> @@ -661,7 +660,6 @@ add_delayed_tree_ref(struct btrfs_fs_info *fs_info,
>  	ref->action = action;
>  	ref->is_head = 0;
>  	ref->in_tree = 1;
> -	ref->no_quota = no_quota;
>  	ref->seq = seq;
>  
>  	full_ref = btrfs_delayed_node_to_tree_ref(ref);
> @@ -694,7 +692,7 @@ add_delayed_data_ref(struct btrfs_fs_info *fs_info,
>  		     struct btrfs_delayed_ref_head *head_ref,
>  		     struct btrfs_delayed_ref_node *ref, u64 bytenr,
>  		     u64 num_bytes, u64 parent, u64 ref_root, u64 owner,
> -		     u64 offset, int action, int no_quota)
> +		     u64 offset, int action)
>  {
>  	struct btrfs_delayed_data_ref *full_ref;
>  	struct btrfs_delayed_ref_root *delayed_refs;
> @@ -717,7 +715,6 @@ add_delayed_data_ref(struct btrfs_fs_info *fs_info,
>  	ref->action = action;
>  	ref->is_head = 0;
>  	ref->in_tree = 1;
> -	ref->no_quota = no_quota;
>  	ref->seq = seq;
>  
>  	full_ref = btrfs_delayed_node_to_data_ref(ref);
> @@ -748,17 +745,13 @@ int btrfs_add_delayed_tree_ref(struct btrfs_fs_info *fs_info,
>  			       struct btrfs_trans_handle *trans,
>  			       u64 bytenr, u64 num_bytes, u64 parent,
>  			       u64 ref_root,  int level, int action,
> -			       struct btrfs_delayed_extent_op *extent_op,
> -			       int no_quota)
> +			       struct btrfs_delayed_extent_op *extent_op)
>  {
>  	struct btrfs_delayed_tree_ref *ref;
>  	struct btrfs_delayed_ref_head *head_ref;
>  	struct btrfs_delayed_ref_root *delayed_refs;
>  	struct btrfs_qgroup_extent_record *record = NULL;
>  
> -	if (!is_fstree(ref_root) || !fs_info->quota_enabled)
> -		no_quota = 0;
> -
>  	BUG_ON(extent_op && extent_op->is_data);
>  	ref = kmem_cache_alloc(btrfs_delayed_tree_ref_cachep, GFP_NOFS);
>  	if (!ref)
> @@ -787,8 +780,7 @@ int btrfs_add_delayed_tree_ref(struct btrfs_fs_info *fs_info,
>  					bytenr, num_bytes, action, 0);
>  
>  	add_delayed_tree_ref(fs_info, trans, head_ref, &ref->node, bytenr,
> -				   num_bytes, parent, ref_root, level, action,
> -				   no_quota);
> +			     num_bytes, parent, ref_root, level, action);
>  	spin_unlock(&delayed_refs->lock);
>  
>  	return 0;
> @@ -809,17 +801,13 @@ int btrfs_add_delayed_data_ref(struct btrfs_fs_info *fs_info,
>  			       u64 bytenr, u64 num_bytes,
>  			       u64 parent, u64 ref_root,
>  			       u64 owner, u64 offset, int action,
> -			       struct btrfs_delayed_extent_op *extent_op,
> -			       int no_quota)
> +			       struct btrfs_delayed_extent_op *extent_op)
>  {
>  	struct btrfs_delayed_data_ref *ref;
>  	struct btrfs_delayed_ref_head *head_ref;
>  	struct btrfs_delayed_ref_root *delayed_refs;
>  	struct btrfs_qgroup_extent_record *record = NULL;
>  
> -	if (!is_fstree(ref_root) || !fs_info->quota_enabled)
> -		no_quota = 0;
> -
>  	BUG_ON(extent_op && !extent_op->is_data);
>  	ref = kmem_cache_alloc(btrfs_delayed_data_ref_cachep, GFP_NOFS);
>  	if (!ref)
> @@ -855,7 +843,7 @@ int btrfs_add_delayed_data_ref(struct btrfs_fs_info *fs_info,
>  
>  	add_delayed_data_ref(fs_info, trans, head_ref, &ref->node, bytenr,
>  				   num_bytes, parent, ref_root, owner, offset,
> -				   action, no_quota);
> +				   action);
>  	spin_unlock(&delayed_refs->lock);
>  
>  	return 0;
> diff --git a/fs/btrfs/delayed-ref.h b/fs/btrfs/delayed-ref.h
> index d4c41e26101c..f9cf2345b864 100644
> --- a/fs/btrfs/delayed-ref.h
> +++ b/fs/btrfs/delayed-ref.h
> @@ -68,7 +68,6 @@ struct btrfs_delayed_ref_node {
>  
>  	unsigned int action:8;
>  	unsigned int type:8;
> -	unsigned int no_quota:1;
>  	/* is this node still in the rbtree? */
>  	unsigned int is_head:1;
>  	unsigned int in_tree:1;
> @@ -244,15 +243,13 @@ int btrfs_add_delayed_tree_ref(struct btrfs_fs_info *fs_info,
>  			       struct btrfs_trans_handle *trans,
>  			       u64 bytenr, u64 num_bytes, u64 parent,
>  			       u64 ref_root, int level, int action,
> -			       struct btrfs_delayed_extent_op *extent_op,
> -			       int no_quota);
> +			       struct btrfs_delayed_extent_op *extent_op);
>  int btrfs_add_delayed_data_ref(struct btrfs_fs_info *fs_info,
>  			       struct btrfs_trans_handle *trans,
>  			       u64 bytenr, u64 num_bytes,
>  			       u64 parent, u64 ref_root,
>  			       u64 owner, u64 offset, int action,
> -			       struct btrfs_delayed_extent_op *extent_op,
> -			       int no_quota);
> +			       struct btrfs_delayed_extent_op *extent_op);
>  int btrfs_add_delayed_qgroup_reserve(struct btrfs_fs_info *fs_info,
>  				     struct btrfs_trans_handle *trans,
>  				     u64 ref_root, u64 bytenr, u64 num_bytes);
> diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
> index c0f30f5d8a41..c1f8c7e27a6d 100644
> --- a/fs/btrfs/extent-tree.c
> +++ b/fs/btrfs/extent-tree.c
> @@ -95,8 +95,7 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans,
>  				     struct btrfs_root *root,
>  				     u64 parent, u64 root_objectid,
>  				     u64 flags, struct btrfs_disk_key *key,
> -				     int level, struct btrfs_key *ins,
> -				     int no_quota);
> +				     int level, struct btrfs_key *ins);
>  static int do_chunk_alloc(struct btrfs_trans_handle *trans,
>  			  struct btrfs_root *extent_root, u64 flags,
>  			  int force);
> @@ -2073,8 +2072,7 @@ int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr,
>  int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
>  			 struct btrfs_root *root,
>  			 u64 bytenr, u64 num_bytes, u64 parent,
> -			 u64 root_objectid, u64 owner, u64 offset,
> -			 int no_quota)
> +			 u64 root_objectid, u64 owner, u64 offset)
>  {
>  	int ret;
>  	struct btrfs_fs_info *fs_info = root->fs_info;
> @@ -2086,12 +2084,12 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
>  		ret = btrfs_add_delayed_tree_ref(fs_info, trans, bytenr,
>  					num_bytes,
>  					parent, root_objectid, (int)owner,
> -					BTRFS_ADD_DELAYED_REF, NULL, no_quota);
> +					BTRFS_ADD_DELAYED_REF, NULL);
>  	} else {
>  		ret = btrfs_add_delayed_data_ref(fs_info, trans, bytenr,
>  					num_bytes,
>  					parent, root_objectid, owner, offset,
> -					BTRFS_ADD_DELAYED_REF, NULL, no_quota);
> +					BTRFS_ADD_DELAYED_REF, NULL);
>  	}
>  	return ret;
>  }
> @@ -2112,15 +2110,11 @@ static int __btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
>  	u64 num_bytes = node->num_bytes;
>  	u64 refs;
>  	int ret;
> -	int no_quota = node->no_quota;
>  
>  	path = btrfs_alloc_path();
>  	if (!path)
>  		return -ENOMEM;
>  
> -	if (!is_fstree(root_objectid) || !root->fs_info->quota_enabled)
> -		no_quota = 1;
> -
>  	path->reada = 1;
>  	path->leave_spinning = 1;
>  	/* this will setup the path even if it fails to insert the back ref */
> @@ -2355,8 +2349,7 @@ static int run_delayed_tree_ref(struct btrfs_trans_handle *trans,
>  						parent, ref_root,
>  						extent_op->flags_to_set,
>  						&extent_op->key,
> -						ref->level, &ins,
> -						node->no_quota);
> +						ref->level, &ins);
>  	} else if (node->action == BTRFS_ADD_DELAYED_REF) {
>  		ret = __btrfs_inc_extent_ref(trans, root, node,
>  					     parent, ref_root,
> @@ -3192,7 +3185,7 @@ static int __btrfs_mod_ref(struct btrfs_trans_handle *trans,
>  	int level;
>  	int ret = 0;
>  	int (*process_func)(struct btrfs_trans_handle *, struct btrfs_root *,
> -			    u64, u64, u64, u64, u64, u64, int);
> +			    u64, u64, u64, u64, u64, u64);
>  
>  
>  	if (btrfs_test_is_dummy_root(root))
> @@ -3233,15 +3226,14 @@ static int __btrfs_mod_ref(struct btrfs_trans_handle *trans,
>  			key.offset -= btrfs_file_extent_offset(buf, fi);
>  			ret = process_func(trans, root, bytenr, num_bytes,
>  					   parent, ref_root, key.objectid,
> -					   key.offset, 1);
> +					   key.offset);
>  			if (ret)
>  				goto fail;
>  		} else {
>  			bytenr = btrfs_node_blockptr(buf, i);
>  			num_bytes = root->nodesize;
>  			ret = process_func(trans, root, bytenr, num_bytes,
> -					   parent, ref_root, level - 1, 0,
> -					   1);
> +					   parent, ref_root, level - 1, 0);
>  			if (ret)
>  				goto fail;
>  		}
> @@ -6431,7 +6423,6 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
>  	int extent_slot = 0;
>  	int found_extent = 0;
>  	int num_to_del = 1;
> -	int no_quota = node->no_quota;
>  	u32 item_size;
>  	u64 refs;
>  	u64 bytenr = node->bytenr;
> @@ -6440,9 +6431,6 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
>  	bool skinny_metadata = btrfs_fs_incompat(root->fs_info,
>  						 SKINNY_METADATA);
>  
> -	if (!info->quota_enabled || !is_fstree(root_objectid))
> -		no_quota = 1;
> -
>  	path = btrfs_alloc_path();
>  	if (!path)
>  		return -ENOMEM;
> @@ -6768,7 +6756,7 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
>  					buf->start, buf->len,
>  					parent, root->root_key.objectid,
>  					btrfs_header_level(buf),
> -					BTRFS_DROP_DELAYED_REF, NULL, 0);
> +					BTRFS_DROP_DELAYED_REF, NULL);
>  		BUG_ON(ret); /* -ENOMEM */
>  	}
>  
> @@ -6816,7 +6804,7 @@ out:
>  /* Can return -ENOMEM */
>  int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root *root,
>  		      u64 bytenr, u64 num_bytes, u64 parent, u64 root_objectid,
> -		      u64 owner, u64 offset, int no_quota)
> +		      u64 owner, u64 offset)
>  {
>  	int ret;
>  	struct btrfs_fs_info *fs_info = root->fs_info;
> @@ -6839,13 +6827,13 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root *root,
>  		ret = btrfs_add_delayed_tree_ref(fs_info, trans, bytenr,
>  					num_bytes,
>  					parent, root_objectid, (int)owner,
> -					BTRFS_DROP_DELAYED_REF, NULL, no_quota);
> +					BTRFS_DROP_DELAYED_REF, NULL);
>  	} else {
>  		ret = btrfs_add_delayed_data_ref(fs_info, trans, bytenr,
>  						num_bytes,
>  						parent, root_objectid, owner,
>  						offset, BTRFS_DROP_DELAYED_REF,
> -						NULL, no_quota);
> +						NULL);
>  	}
>  	return ret;
>  }
> @@ -7690,8 +7678,7 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans,
>  				     struct btrfs_root *root,
>  				     u64 parent, u64 root_objectid,
>  				     u64 flags, struct btrfs_disk_key *key,
> -				     int level, struct btrfs_key *ins,
> -				     int no_quota)
> +				     int level, struct btrfs_key *ins)
>  {
>  	int ret;
>  	struct btrfs_fs_info *fs_info = root->fs_info;
> @@ -7781,7 +7768,7 @@ int btrfs_alloc_reserved_file_extent(struct btrfs_trans_handle *trans,
>  	ret = btrfs_add_delayed_data_ref(root->fs_info, trans, ins->objectid,
>  					 ins->offset, 0,
>  					 root_objectid, owner, offset,
> -					 BTRFS_ADD_DELAYED_EXTENT, NULL, 0);
> +					 BTRFS_ADD_DELAYED_EXTENT, NULL);
>  	return ret;
>  }
>  
> @@ -7995,7 +7982,7 @@ struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans,
>  						 ins.objectid, ins.offset,
>  						 parent, root_objectid, level,
>  						 BTRFS_ADD_DELAYED_EXTENT,
> -						 extent_op, 0);
> +						 extent_op);
>  		if (ret)
>  			goto out_free_delayed;
>  	}
> @@ -8544,7 +8531,7 @@ skip:
>  			}
>  		}
>  		ret = btrfs_free_extent(trans, root, bytenr, blocksize, parent,
> -				root->root_key.objectid, level - 1, 0, 0);
> +				root->root_key.objectid, level - 1, 0);
>  		BUG_ON(ret); /* -ENOMEM */
>  	}
>  	btrfs_tree_unlock(next);
> diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
> index 12432057a12e..381be79f779a 100644
> --- a/fs/btrfs/file.c
> +++ b/fs/btrfs/file.c
> @@ -847,7 +847,7 @@ next_slot:
>  						disk_bytenr, num_bytes, 0,
>  						root->root_key.objectid,
>  						new_key.objectid,
> -						start - extent_offset, 1);
> +						start - extent_offset);
>  				BUG_ON(ret); /* -ENOMEM */
>  			}
>  			key.offset = start;
> @@ -925,7 +925,7 @@ delete_extent_item:
>  						disk_bytenr, num_bytes, 0,
>  						root->root_key.objectid,
>  						key.objectid, key.offset -
> -						extent_offset, 0);
> +						extent_offset);
>  				BUG_ON(ret); /* -ENOMEM */
>  				inode_sub_bytes(inode,
>  						extent_end - key.offset);
> @@ -1204,7 +1204,7 @@ again:
>  
>  		ret = btrfs_inc_extent_ref(trans, root, bytenr, num_bytes, 0,
>  					   root->root_key.objectid,
> -					   ino, orig_offset, 1);
> +					   ino, orig_offset);
>  		BUG_ON(ret); /* -ENOMEM */
>  
>  		if (split == start) {
> @@ -1231,7 +1231,7 @@ again:
>  		del_nr++;
>  		ret = btrfs_free_extent(trans, root, bytenr, num_bytes,
>  					0, root->root_key.objectid,
> -					ino, orig_offset, 0);
> +					ino, orig_offset);
>  		BUG_ON(ret); /* -ENOMEM */
>  	}
>  	other_start = 0;
> @@ -1248,7 +1248,7 @@ again:
>  		del_nr++;
>  		ret = btrfs_free_extent(trans, root, bytenr, num_bytes,
>  					0, root->root_key.objectid,
> -					ino, orig_offset, 0);
> +					ino, orig_offset);
>  		BUG_ON(ret); /* -ENOMEM */
>  	}
>  	if (del_nr == 0) {
> diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
> index a018e4707dac..6f030c299de8 100644
> --- a/fs/btrfs/inode.c
> +++ b/fs/btrfs/inode.c
> @@ -2595,7 +2595,7 @@ again:
>  	ret = btrfs_inc_extent_ref(trans, root, new->bytenr,
>  			new->disk_len, 0,
>  			backref->root_id, backref->inum,
> -			new->file_pos, 0);	/* start - extent_offset */
> +			new->file_pos);	/* start - extent_offset */
>  	if (ret) {
>  		btrfs_abort_transaction(trans, root, ret);
>  		goto out_free_path;
> @@ -4541,7 +4541,7 @@ delete:
>  			ret = btrfs_free_extent(trans, root, extent_start,
>  						extent_num_bytes, 0,
>  						btrfs_header_owner(leaf),
> -						ino, extent_offset, 0);
> +						ino, extent_offset);
>  			BUG_ON(ret);
>  			if (btrfs_should_throttle_delayed_refs(trans, root))
>  				btrfs_async_run_delayed_refs(root,
> diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
> index 7ed033a84212..4df0f2bd9af7 100644
> --- a/fs/btrfs/ioctl.c
> +++ b/fs/btrfs/ioctl.c
> @@ -3206,41 +3206,6 @@ out:
>  	return ret;
>  }
>  
> -/* Helper to check and see if this root currently has a ref on the given disk
> - * bytenr.  If it does then we need to update the quota for this root.  This
> - * doesn't do anything if quotas aren't enabled.
> - */
> -static int check_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
> -		     u64 disko)
> -{
> -	struct seq_list tree_mod_seq_elem = SEQ_LIST_INIT(tree_mod_seq_elem);
> -	struct ulist *roots;
> -	struct ulist_iterator uiter;
> -	struct ulist_node *root_node = NULL;
> -	int ret;
> -
> -	if (!root->fs_info->quota_enabled)
> -		return 1;
> -
> -	btrfs_get_tree_mod_seq(root->fs_info, &tree_mod_seq_elem);
> -	ret = btrfs_find_all_roots(trans, root->fs_info, disko,
> -				   tree_mod_seq_elem.seq, &roots);
> -	if (ret < 0)
> -		goto out;
> -	ret = 0;
> -	ULIST_ITER_INIT(&uiter);
> -	while ((root_node = ulist_next(roots, &uiter))) {
> -		if (root_node->val == root->objectid) {
> -			ret = 1;
> -			break;
> -		}
> -	}
> -	ulist_free(roots);
> -out:
> -	btrfs_put_tree_mod_seq(root->fs_info, &tree_mod_seq_elem);
> -	return ret;
> -}
> -
>  static int clone_finish_inode_update(struct btrfs_trans_handle *trans,
>  				     struct inode *inode,
>  				     u64 endoff,
> @@ -3499,9 +3464,7 @@ static int btrfs_clone(struct inode *src, struct inode *inode,
>  	u32 nritems;
>  	int slot;
>  	int ret;
> -	int no_quota;
>  	const u64 len = olen_aligned;
> -	u64 last_disko = 0;
>  	u64 last_dest_end = destoff;
>  
>  	ret = -ENOMEM;
> @@ -3547,7 +3510,6 @@ static int btrfs_clone(struct inode *src, struct inode *inode,
>  
>  		nritems = btrfs_header_nritems(path->nodes[0]);
>  process_slot:
> -		no_quota = 1;
>  		if (path->slots[0] >= nritems) {
>  			ret = btrfs_next_leaf(BTRFS_I(src)->root, path);
>  			if (ret < 0)
> @@ -3699,35 +3661,13 @@ process_slot:
>  				btrfs_set_file_extent_num_bytes(leaf, extent,
>  								datal);
>  
> -				/*
> -				 * We need to look up the roots that point at
> -				 * this bytenr and see if the new root does.  If
> -				 * it does not we need to make sure we update
> -				 * quotas appropriately.
> -				 */
> -				if (disko && root != BTRFS_I(src)->root &&
> -				    disko != last_disko) {
> -					no_quota = check_ref(trans, root,
> -							     disko);
> -					if (no_quota < 0) {
> -						btrfs_abort_transaction(trans,
> -									root,
> -									ret);
> -						btrfs_end_transaction(trans,
> -								      root);
> -						ret = no_quota;
> -						goto out;
> -					}
> -				}
> -
>  				if (disko) {
>  					inode_add_bytes(inode, datal);
>  					ret = btrfs_inc_extent_ref(trans, root,
>  							disko, diskl, 0,
>  							root->root_key.objectid,
>  							btrfs_ino(inode),
> -							new_key.offset - datao,
> -							no_quota);
> +							new_key.offset - datao);
>  					if (ret) {
>  						btrfs_abort_transaction(trans,
>  									root,
> diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
> index a7dc45622e90..b4ca5454ef1a 100644
> --- a/fs/btrfs/relocation.c
> +++ b/fs/btrfs/relocation.c
> @@ -1716,7 +1716,7 @@ int replace_file_extents(struct btrfs_trans_handle *trans,
>  		ret = btrfs_inc_extent_ref(trans, root, new_bytenr,
>  					   num_bytes, parent,
>  					   btrfs_header_owner(leaf),
> -					   key.objectid, key.offset, 1);
> +					   key.objectid, key.offset);
>  		if (ret) {
>  			btrfs_abort_transaction(trans, root, ret);
>  			break;
> @@ -1724,7 +1724,7 @@ int replace_file_extents(struct btrfs_trans_handle *trans,
>  
>  		ret = btrfs_free_extent(trans, root, bytenr, num_bytes,
>  					parent, btrfs_header_owner(leaf),
> -					key.objectid, key.offset, 1);
> +					key.objectid, key.offset);
>  		if (ret) {
>  			btrfs_abort_transaction(trans, root, ret);
>  			break;
> @@ -1900,23 +1900,21 @@ again:
>  
>  		ret = btrfs_inc_extent_ref(trans, src, old_bytenr, blocksize,
>  					path->nodes[level]->start,
> -					src->root_key.objectid, level - 1, 0,
> -					1);
> +					src->root_key.objectid, level - 1, 0);
>  		BUG_ON(ret);
>  		ret = btrfs_inc_extent_ref(trans, dest, new_bytenr, blocksize,
>  					0, dest->root_key.objectid, level - 1,
> -					0, 1);
> +					0);
>  		BUG_ON(ret);
>  
>  		ret = btrfs_free_extent(trans, src, new_bytenr, blocksize,
>  					path->nodes[level]->start,
> -					src->root_key.objectid, level - 1, 0,
> -					1);
> +					src->root_key.objectid, level - 1, 0);
>  		BUG_ON(ret);
>  
>  		ret = btrfs_free_extent(trans, dest, old_bytenr, blocksize,
>  					0, dest->root_key.objectid, level - 1,
> -					0, 1);
> +					0);
>  		BUG_ON(ret);
>  
>  		btrfs_unlock_up_safe(path, 0);
> @@ -2745,7 +2743,7 @@ static int do_relocation(struct btrfs_trans_handle *trans,
>  						node->eb->start, blocksize,
>  						upper->eb->start,
>  						btrfs_header_owner(upper->eb),
> -						node->level, 0, 1);
> +						node->level, 0);
>  			BUG_ON(ret);
>  
>  			ret = btrfs_drop_subtree(trans, root, eb, upper->eb);
> diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
> index 1fffe8845c09..323e12cc9d2f 100644
> --- a/fs/btrfs/tree-log.c
> +++ b/fs/btrfs/tree-log.c
> @@ -693,7 +693,7 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans,
>  				ret = btrfs_inc_extent_ref(trans, root,
>  						ins.objectid, ins.offset,
>  						0, root->root_key.objectid,
> -						key->objectid, offset, 0);
> +						key->objectid, offset);
>  				if (ret)
>  					goto out;
>  			} else {
> 
> 
From 0b569598ffffbc3219de978f9ed65f64e3ac01cb Mon Sep 17 00:00:00 2001
From: Filipe Manana <fdmanana@xxxxxxxx>
Date: Fri, 23 Oct 2015 07:52:54 +0100
Subject: [PATCH 4.2.7] Btrfs: fix regression running delayed references when using
 qgroups
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

In the kernel 4.2 merge window we had a big changes to the implementation
of delayed references and qgroups which made the no_quota field of delayed
references not used anymore. More specifically the no_quota field is not
used anymore as of:

  commit 0ed4792af0e8 ("btrfs: qgroup: Switch to new extent-oriented qgroup mechanism.")

Leaving the no_quota field actually prevents delayed references from
getting merged, which in turn cause the following BUG_ON(), at
fs/btrfs/extent-tree.c, to be hit when qgroups are enabled:

  static int run_delayed_tree_ref(...)
  {
     (...)
     BUG_ON(node->ref_mod != 1);
     (...)
  }

This happens on a scenario like the following:

  1) Ref1 bytenr X, action = BTRFS_ADD_DELAYED_REF, no_quota = 1, added.

  2) Ref2 bytenr X, action = BTRFS_DROP_DELAYED_REF, no_quota = 0, added.
     It's not merged with Ref1 because Ref1->no_quota != Ref2->no_quota.

  3) Ref3 bytenr X, action = BTRFS_ADD_DELAYED_REF, no_quota = 1, added.
     It's not merged with the reference at the tail of the list of refs
     for bytenr X because the reference at the tail, Ref2 is incompatible
     due to Ref2->no_quota != Ref3->no_quota.

  4) Ref4 bytenr X, action = BTRFS_DROP_DELAYED_REF, no_quota = 0, added.
     It's not merged with the reference at the tail of the list of refs
     for bytenr X because the reference at the tail, Ref3 is incompatible
     due to Ref3->no_quota != Ref4->no_quota.

  5) We run delayed references, trigger merging of delayed references,
     through __btrfs_run_delayed_refs() -> btrfs_merge_delayed_refs().

  6) Ref1 and Ref3 are merged as Ref1->no_quota = Ref3->no_quota and
     all other conditions are satisfied too. So Ref1 gets a ref_mod
     value of 2.

  7) Ref2 and Ref4 are merged as Ref2->no_quota = Ref4->no_quota and
     all other conditions are satisfied too. So Ref2 gets a ref_mod
     value of 2.

  8) Ref1 and Ref2 aren't merged, because they have different values
     for their no_quota field.

  9) Delayed reference Ref1 is picked for running (select_delayed_ref()
     always prefers references with an action == BTRFS_ADD_DELAYED_REF).
     So run_delayed_tree_ref() is called for Ref1 which triggers the
     BUG_ON because Ref1->red_mod != 1 (equals 2).

So fix this by removing the no_quota field, as it's not used anymore as
of commit 0ed4792af0e8 ("btrfs: qgroup: Switch to new extent-oriented
qgroup mechanism.").

The use of no_quota was also buggy in at least two places:

1) At delayed-refs.c:btrfs_add_delayed_tree_ref() - we were setting
   no_quota to 0 instead of 1 when the following condition was true:
   is_fstree(ref_root) || !fs_info->quota_enabled

2) At extent-tree.c:__btrfs_inc_extent_ref() - we were attempting to
   reset a node's no_quota when the condition "!is_fstree(root_objectid)
   || !root->fs_info->quota_enabled" was true but we did it only in
   an unused local stack variable, that is, we never reset the no_quota
   value in the node itself.

This fixes the remainder of problems several people have been having when
running delayed references, mostly while a balance is running in parallel,
on a 4.2+ kernel.

Very special thanks to Stéphane Lesimple for helping debugging this issue
and testing this fix on his multi terabyte filesystem (which took more
than one day to balance alone, plus fsck, etc).

Also, this fixes deadlock issue when using the clone ioctl with qgroups
enabled, as reported by Elias Probst in the mailing list. The deadlock
happens because after calling btrfs_insert_empty_item we have our path
holding a write lock on a leaf of the fs/subvol tree and then before
releasing the path we called check_ref() which did backref walking, when
qgroups are enabled, and tried to read lock the same leaf. The trace for
this case is the following:

  INFO: task systemd-nspawn:6095 blocked for more than 120 seconds.
  (...)
  Call Trace:
    [<ffffffff86999201>] schedule+0x74/0x83
    [<ffffffff863ef64c>] btrfs_tree_read_lock+0xc0/0xea
    [<ffffffff86137ed7>] ? wait_woken+0x74/0x74
    [<ffffffff8639f0a7>] btrfs_search_old_slot+0x51a/0x810
    [<ffffffff863a129b>] btrfs_next_old_leaf+0xdf/0x3ce
    [<ffffffff86413a00>] ? ulist_add_merge+0x1b/0x127
    [<ffffffff86411688>] __resolve_indirect_refs+0x62a/0x667
    [<ffffffff863ef546>] ? btrfs_clear_lock_blocking_rw+0x78/0xbe
    [<ffffffff864122d3>] find_parent_nodes+0xaf3/0xfc6
    [<ffffffff86412838>] __btrfs_find_all_roots+0x92/0xf0
    [<ffffffff864128f2>] btrfs_find_all_roots+0x45/0x65
    [<ffffffff8639a75b>] ? btrfs_get_tree_mod_seq+0x2b/0x88
    [<ffffffff863e852e>] check_ref+0x64/0xc4
    [<ffffffff863e9e01>] btrfs_clone+0x66e/0xb5d
    [<ffffffff863ea77f>] btrfs_ioctl_clone+0x48f/0x5bb
    [<ffffffff86048a68>] ? native_sched_clock+0x28/0x77
    [<ffffffff863ed9b0>] btrfs_ioctl+0xabc/0x25cb
  (...)

The problem goes away by eleminating check_ref(), which no longer is
needed as its purpose was to get a value for the no_quota field of
a delayed reference (this patch removes the no_quota field as mentioned
earlier).

Reported-by: Stéphane Lesimple <stephane_btrfs@xxxxxxxxxxx>
Tested-by: Stéphane Lesimple <stephane_btrfs@xxxxxxxxxxx>
Reported-by: Elias Probst <mail@xxxxxxxxxxxxxx>
Reported-by: Peter Becker <floyd.net@xxxxxxxxx>
Reported-by: Malte Schröder <malte@xxxxxxxx>
Reported-by: Derek Dongray <derek@xxxxxxxxxxxxx>
Reported-by: Erkki Seppala <flux-btrfs@xxxxxxxxxx>
Cc: stable@xxxxxxxxxxxxxxx  # 4.2+
Signed-off-by: Filipe Manana <fdmanana@xxxxxxxx>
Reviewed-by: Qu Wenruo <quwenruo@xxxxxxxxxxxxxx>
---
 fs/btrfs/ctree.h       |   4 +-
 fs/btrfs/delayed-ref.c | 139 ++++++++++++++++++++++++++++++++++++++++++-------
 fs/btrfs/delayed-ref.h |   7 +--
 fs/btrfs/extent-tree.c |  45 ++++++----------
 fs/btrfs/file.c        |  10 ++--
 fs/btrfs/inode.c       |   4 +-
 fs/btrfs/ioctl.c       |  62 +---------------------
 fs/btrfs/relocation.c  |  16 +++---
 fs/btrfs/tree-log.c    |   2 +-
 9 files changed, 156 insertions(+), 133 deletions(-)

diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index aac314e..bb25b8d 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -3404,7 +3404,7 @@ int btrfs_set_disk_extent_flags(struct btrfs_trans_handle *trans,
 int btrfs_free_extent(struct btrfs_trans_handle *trans,
 		      struct btrfs_root *root,
 		      u64 bytenr, u64 num_bytes, u64 parent, u64 root_objectid,
-		      u64 owner, u64 offset, int no_quota);
+		      u64 owner, u64 offset);
 
 int btrfs_free_reserved_extent(struct btrfs_root *root, u64 start, u64 len,
 			       int delalloc);
@@ -3417,7 +3417,7 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans,
 int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
 			 struct btrfs_root *root,
 			 u64 bytenr, u64 num_bytes, u64 parent,
-			 u64 root_objectid, u64 owner, u64 offset, int no_quota);
+			 u64 root_objectid, u64 owner, u64 offset);
 
 int btrfs_start_dirty_block_groups(struct btrfs_trans_handle *trans,
 				   struct btrfs_root *root);
diff --git a/fs/btrfs/delayed-ref.c b/fs/btrfs/delayed-ref.c
index ac3e81d..7832031 100644
--- a/fs/btrfs/delayed-ref.c
+++ b/fs/btrfs/delayed-ref.c
@@ -197,6 +197,119 @@ static inline void drop_delayed_ref(struct btrfs_trans_handle *trans,
 		trans->delayed_ref_updates--;
 }
 
+static bool merge_ref(struct btrfs_trans_handle *trans,
+		      struct btrfs_delayed_ref_root *delayed_refs,
+		      struct btrfs_delayed_ref_head *head,
+		      struct btrfs_delayed_ref_node *ref,
+		      u64 seq)
+{
+	struct btrfs_delayed_ref_node *next;
+	bool done = false;
+
+	next = list_first_entry(&head->ref_list, struct btrfs_delayed_ref_node,
+				list);
+	while (!done && &next->list != &head->ref_list) {
+		int mod;
+		struct btrfs_delayed_ref_node *next2;
+
+		next2 = list_next_entry(next, list);
+
+		if (next == ref)
+			goto next;
+
+		if (seq && next->seq >= seq)
+			goto next;
+
+		if (next->type != ref->type)
+			goto next;
+
+		if ((ref->type == BTRFS_TREE_BLOCK_REF_KEY ||
+		     ref->type == BTRFS_SHARED_BLOCK_REF_KEY) &&
+		    comp_tree_refs(btrfs_delayed_node_to_tree_ref(ref),
+				   btrfs_delayed_node_to_tree_ref(next),
+				   ref->type))
+			goto next;
+		if ((ref->type == BTRFS_EXTENT_DATA_REF_KEY ||
+		     ref->type == BTRFS_SHARED_DATA_REF_KEY) &&
+		    comp_data_refs(btrfs_delayed_node_to_data_ref(ref),
+				   btrfs_delayed_node_to_data_ref(next)))
+			goto next;
+
+		if (ref->action == next->action) {
+			mod = next->ref_mod;
+		} else {
+			if (ref->ref_mod < next->ref_mod) {
+				swap(ref, next);
+				done = true;
+			}
+			mod = -next->ref_mod;
+		}
+
+		drop_delayed_ref(trans, delayed_refs, head, next);
+		ref->ref_mod += mod;
+		if (ref->ref_mod == 0) {
+			drop_delayed_ref(trans, delayed_refs, head, ref);
+			done = true;
+		} else {
+			/*
+			 * Can't have multiples of the same ref on a tree block.
+			 */
+			WARN_ON(ref->type == BTRFS_TREE_BLOCK_REF_KEY ||
+				ref->type == BTRFS_SHARED_BLOCK_REF_KEY);
+		}
+next:
+		next = next2;
+	}
+
+	return done;
+}
+
+void btrfs_merge_delayed_refs(struct btrfs_trans_handle *trans,
+			      struct btrfs_fs_info *fs_info,
+			      struct btrfs_delayed_ref_root *delayed_refs,
+			      struct btrfs_delayed_ref_head *head)
+{
+	struct btrfs_delayed_ref_node *ref;
+	u64 seq = 0;
+
+	assert_spin_locked(&head->lock);
+
+	if (list_empty(&head->ref_list))
+		return;
+
+	/* We don't have too many refs to merge for data. */
+	if (head->is_data)
+		return;
+
+	spin_lock(&fs_info->tree_mod_seq_lock);
+	if (!list_empty(&fs_info->tree_mod_seq_list)) {
+		struct seq_list *elem;
+
+		elem = list_first_entry(&fs_info->tree_mod_seq_list,
+					struct seq_list, list);
+		seq = elem->seq;
+	}
+	spin_unlock(&fs_info->tree_mod_seq_lock);
+
+	ref = list_first_entry(&head->ref_list, struct btrfs_delayed_ref_node,
+			       list);
+	while (&ref->list != &head->ref_list) {
+		if (seq && ref->seq >= seq)
+			goto next;
+
+		if (merge_ref(trans, delayed_refs, head, ref, seq)) {
+			if (list_empty(&head->ref_list))
+				break;
+			ref = list_first_entry(&head->ref_list,
+					       struct btrfs_delayed_ref_node,
+					       list);
+			continue;
+		}
+next:
+		ref = list_next_entry(ref, list);
+	}
+}
+
 int btrfs_check_delayed_seq(struct btrfs_fs_info *fs_info,
 			    struct btrfs_delayed_ref_root *delayed_refs,
 			    u64 seq)
@@ -292,8 +405,7 @@ add_delayed_ref_tail_merge(struct btrfs_trans_handle *trans,
 	exist = list_entry(href->ref_list.prev, struct btrfs_delayed_ref_node,
 			   list);
 	/* No need to compare bytenr nor is_head */
-	if (exist->type != ref->type || exist->no_quota != ref->no_quota ||
-	    exist->seq != ref->seq)
+	if (exist->type != ref->type || exist->seq != ref->seq)
 		goto add_tail;
 
 	if ((exist->type == BTRFS_TREE_BLOCK_REF_KEY ||
@@ -524,7 +636,7 @@ add_delayed_tree_ref(struct btrfs_fs_info *fs_info,
 		     struct btrfs_delayed_ref_head *head_ref,
 		     struct btrfs_delayed_ref_node *ref, u64 bytenr,
 		     u64 num_bytes, u64 parent, u64 ref_root, int level,
-		     int action, int no_quota)
+		     int action)
 {
 	struct btrfs_delayed_tree_ref *full_ref;
 	struct btrfs_delayed_ref_root *delayed_refs;
@@ -546,7 +658,6 @@ add_delayed_tree_ref(struct btrfs_fs_info *fs_info,
 	ref->action = action;
 	ref->is_head = 0;
 	ref->in_tree = 1;
-	ref->no_quota = no_quota;
 	ref->seq = seq;
 
 	full_ref = btrfs_delayed_node_to_tree_ref(ref);
@@ -579,7 +690,7 @@ add_delayed_data_ref(struct btrfs_fs_info *fs_info,
 		     struct btrfs_delayed_ref_head *head_ref,
 		     struct btrfs_delayed_ref_node *ref, u64 bytenr,
 		     u64 num_bytes, u64 parent, u64 ref_root, u64 owner,
-		     u64 offset, int action, int no_quota)
+		     u64 offset, int action)
 {
 	struct btrfs_delayed_data_ref *full_ref;
 	struct btrfs_delayed_ref_root *delayed_refs;
@@ -602,7 +713,6 @@ add_delayed_data_ref(struct btrfs_fs_info *fs_info,
 	ref->action = action;
 	ref->is_head = 0;
 	ref->in_tree = 1;
-	ref->no_quota = no_quota;
 	ref->seq = seq;
 
 	full_ref = btrfs_delayed_node_to_data_ref(ref);
@@ -633,17 +743,13 @@ int btrfs_add_delayed_tree_ref(struct btrfs_fs_info *fs_info,
 			       struct btrfs_trans_handle *trans,
 			       u64 bytenr, u64 num_bytes, u64 parent,
 			       u64 ref_root,  int level, int action,
-			       struct btrfs_delayed_extent_op *extent_op,
-			       int no_quota)
+			       struct btrfs_delayed_extent_op *extent_op)
 {
 	struct btrfs_delayed_tree_ref *ref;
 	struct btrfs_delayed_ref_head *head_ref;
 	struct btrfs_delayed_ref_root *delayed_refs;
 	struct btrfs_qgroup_extent_record *record = NULL;
 
-	if (!is_fstree(ref_root) || !fs_info->quota_enabled)
-		no_quota = 0;
-
 	BUG_ON(extent_op && extent_op->is_data);
 	ref = kmem_cache_alloc(btrfs_delayed_tree_ref_cachep, GFP_NOFS);
 	if (!ref)
@@ -672,8 +778,7 @@ int btrfs_add_delayed_tree_ref(struct btrfs_fs_info *fs_info,
 					bytenr, num_bytes, action, 0);
 
 	add_delayed_tree_ref(fs_info, trans, head_ref, &ref->node, bytenr,
-				   num_bytes, parent, ref_root, level, action,
-				   no_quota);
+			     num_bytes, parent, ref_root, level, action);
 	spin_unlock(&delayed_refs->lock);
 
 	return 0;
@@ -694,17 +799,13 @@ int btrfs_add_delayed_data_ref(struct btrfs_fs_info *fs_info,
 			       u64 bytenr, u64 num_bytes,
 			       u64 parent, u64 ref_root,
 			       u64 owner, u64 offset, int action,
-			       struct btrfs_delayed_extent_op *extent_op,
-			       int no_quota)
+			       struct btrfs_delayed_extent_op *extent_op)
 {
 	struct btrfs_delayed_data_ref *ref;
 	struct btrfs_delayed_ref_head *head_ref;
 	struct btrfs_delayed_ref_root *delayed_refs;
 	struct btrfs_qgroup_extent_record *record = NULL;
 
-	if (!is_fstree(ref_root) || !fs_info->quota_enabled)
-		no_quota = 0;
-
 	BUG_ON(extent_op && !extent_op->is_data);
 	ref = kmem_cache_alloc(btrfs_delayed_data_ref_cachep, GFP_NOFS);
 	if (!ref)
@@ -740,7 +841,7 @@ int btrfs_add_delayed_data_ref(struct btrfs_fs_info *fs_info,
 
 	add_delayed_data_ref(fs_info, trans, head_ref, &ref->node, bytenr,
 				   num_bytes, parent, ref_root, owner, offset,
-				   action, no_quota);
+				   action);
 	spin_unlock(&delayed_refs->lock);
 
 	return 0;
diff --git a/fs/btrfs/delayed-ref.h b/fs/btrfs/delayed-ref.h
index 13fb5e6..930887a 100644
--- a/fs/btrfs/delayed-ref.h
+++ b/fs/btrfs/delayed-ref.h
@@ -68,7 +68,6 @@ struct btrfs_delayed_ref_node {
 
 	unsigned int action:8;
 	unsigned int type:8;
-	unsigned int no_quota:1;
 	/* is this node still in the rbtree? */
 	unsigned int is_head:1;
 	unsigned int in_tree:1;
@@ -233,15 +232,13 @@ int btrfs_add_delayed_tree_ref(struct btrfs_fs_info *fs_info,
 			       struct btrfs_trans_handle *trans,
 			       u64 bytenr, u64 num_bytes, u64 parent,
 			       u64 ref_root, int level, int action,
-			       struct btrfs_delayed_extent_op *extent_op,
-			       int no_quota);
+			       struct btrfs_delayed_extent_op *extent_op);
 int btrfs_add_delayed_data_ref(struct btrfs_fs_info *fs_info,
 			       struct btrfs_trans_handle *trans,
 			       u64 bytenr, u64 num_bytes,
 			       u64 parent, u64 ref_root,
 			       u64 owner, u64 offset, int action,
-			       struct btrfs_delayed_extent_op *extent_op,
-			       int no_quota);
+			       struct btrfs_delayed_extent_op *extent_op);
 int btrfs_add_delayed_extent_op(struct btrfs_fs_info *fs_info,
 				struct btrfs_trans_handle *trans,
 				u64 bytenr, u64 num_bytes,
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 07204bf..fd16964 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -95,8 +95,7 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans,
 				     struct btrfs_root *root,
 				     u64 parent, u64 root_objectid,
 				     u64 flags, struct btrfs_disk_key *key,
-				     int level, struct btrfs_key *ins,
-				     int no_quota);
+				     int level, struct btrfs_key *ins);
 static int do_chunk_alloc(struct btrfs_trans_handle *trans,
 			  struct btrfs_root *extent_root, u64 flags,
 			  int force);
@@ -1941,8 +1940,7 @@ int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr,
 int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
 			 struct btrfs_root *root,
 			 u64 bytenr, u64 num_bytes, u64 parent,
-			 u64 root_objectid, u64 owner, u64 offset,
-			 int no_quota)
+			 u64 root_objectid, u64 owner, u64 offset)
 {
 	int ret;
 	struct btrfs_fs_info *fs_info = root->fs_info;
@@ -1954,12 +1952,12 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
 		ret = btrfs_add_delayed_tree_ref(fs_info, trans, bytenr,
 					num_bytes,
 					parent, root_objectid, (int)owner,
-					BTRFS_ADD_DELAYED_REF, NULL, no_quota);
+					BTRFS_ADD_DELAYED_REF, NULL);
 	} else {
 		ret = btrfs_add_delayed_data_ref(fs_info, trans, bytenr,
 					num_bytes,
 					parent, root_objectid, owner, offset,
-					BTRFS_ADD_DELAYED_REF, NULL, no_quota);
+					BTRFS_ADD_DELAYED_REF, NULL);
 	}
 	return ret;
 }
@@ -1980,15 +1978,11 @@ static int __btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
 	u64 num_bytes = node->num_bytes;
 	u64 refs;
 	int ret;
-	int no_quota = node->no_quota;
 
 	path = btrfs_alloc_path();
 	if (!path)
 		return -ENOMEM;
 
-	if (!is_fstree(root_objectid) || !root->fs_info->quota_enabled)
-		no_quota = 1;
-
 	path->reada = 1;
 	path->leave_spinning = 1;
 	/* this will setup the path even if it fails to insert the back ref */
@@ -2223,8 +2217,7 @@ static int run_delayed_tree_ref(struct btrfs_trans_handle *trans,
 						parent, ref_root,
 						extent_op->flags_to_set,
 						&extent_op->key,
-						ref->level, &ins,
-						node->no_quota);
+						ref->level, &ins);
 	} else if (node->action == BTRFS_ADD_DELAYED_REF) {
 		ret = __btrfs_inc_extent_ref(trans, root, node,
 					     parent, ref_root,
@@ -3038,7 +3031,7 @@ static int __btrfs_mod_ref(struct btrfs_trans_handle *trans,
 	int level;
 	int ret = 0;
 	int (*process_func)(struct btrfs_trans_handle *, struct btrfs_root *,
-			    u64, u64, u64, u64, u64, u64, int);
+			    u64, u64, u64, u64, u64, u64);
 
 
 	if (btrfs_test_is_dummy_root(root))
@@ -3079,15 +3072,14 @@ static int __btrfs_mod_ref(struct btrfs_trans_handle *trans,
 			key.offset -= btrfs_file_extent_offset(buf, fi);
 			ret = process_func(trans, root, bytenr, num_bytes,
 					   parent, ref_root, key.objectid,
-					   key.offset, 1);
+					   key.offset);
 			if (ret)
 				goto fail;
 		} else {
 			bytenr = btrfs_node_blockptr(buf, i);
 			num_bytes = root->nodesize;
 			ret = process_func(trans, root, bytenr, num_bytes,
-					   parent, ref_root, level - 1, 0,
-					   1);
+					   parent, ref_root, level - 1, 0);
 			if (ret)
 				goto fail;
 		}
@@ -6137,7 +6129,6 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
 	int extent_slot = 0;
 	int found_extent = 0;
 	int num_to_del = 1;
-	int no_quota = node->no_quota;
 	u32 item_size;
 	u64 refs;
 	u64 bytenr = node->bytenr;
@@ -6146,9 +6137,6 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
 	bool skinny_metadata = btrfs_fs_incompat(root->fs_info,
 						 SKINNY_METADATA);
 
-	if (!info->quota_enabled || !is_fstree(root_objectid))
-		no_quota = 1;
-
 	path = btrfs_alloc_path();
 	if (!path)
 		return -ENOMEM;
@@ -6474,7 +6462,7 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
 					buf->start, buf->len,
 					parent, root->root_key.objectid,
 					btrfs_header_level(buf),
-					BTRFS_DROP_DELAYED_REF, NULL, 0);
+					BTRFS_DROP_DELAYED_REF, NULL);
 		BUG_ON(ret); /* -ENOMEM */
 	}
 
@@ -6522,7 +6510,7 @@ out:
 /* Can return -ENOMEM */
 int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 		      u64 bytenr, u64 num_bytes, u64 parent, u64 root_objectid,
-		      u64 owner, u64 offset, int no_quota)
+		      u64 owner, u64 offset)
 {
 	int ret;
 	struct btrfs_fs_info *fs_info = root->fs_info;
@@ -6545,13 +6533,13 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 		ret = btrfs_add_delayed_tree_ref(fs_info, trans, bytenr,
 					num_bytes,
 					parent, root_objectid, (int)owner,
-					BTRFS_DROP_DELAYED_REF, NULL, no_quota);
+					BTRFS_DROP_DELAYED_REF, NULL);
 	} else {
 		ret = btrfs_add_delayed_data_ref(fs_info, trans, bytenr,
 						num_bytes,
 						parent, root_objectid, owner,
 						offset, BTRFS_DROP_DELAYED_REF,
-						NULL, no_quota);
+						NULL);
 	}
 	return ret;
 }
@@ -7333,8 +7321,7 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans,
 				     struct btrfs_root *root,
 				     u64 parent, u64 root_objectid,
 				     u64 flags, struct btrfs_disk_key *key,
-				     int level, struct btrfs_key *ins,
-				     int no_quota)
+				     int level, struct btrfs_key *ins)
 {
 	int ret;
 	struct btrfs_fs_info *fs_info = root->fs_info;
@@ -7424,7 +7411,7 @@ int btrfs_alloc_reserved_file_extent(struct btrfs_trans_handle *trans,
 	ret = btrfs_add_delayed_data_ref(root->fs_info, trans, ins->objectid,
 					 ins->offset, 0,
 					 root_objectid, owner, offset,
-					 BTRFS_ADD_DELAYED_EXTENT, NULL, 0);
+					 BTRFS_ADD_DELAYED_EXTENT, NULL);
 	return ret;
 }
 
@@ -7641,7 +7628,7 @@ struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans,
 						 ins.objectid, ins.offset,
 						 parent, root_objectid, level,
 						 BTRFS_ADD_DELAYED_EXTENT,
-						 extent_op, 0);
+						 extent_op);
 		if (ret)
 			goto out_free_delayed;
 	}
@@ -8189,7 +8176,7 @@ skip:
 			}
 		}
 		ret = btrfs_free_extent(trans, root, bytenr, blocksize, parent,
-				root->root_key.objectid, level - 1, 0, 0);
+				root->root_key.objectid, level - 1, 0);
 		BUG_ON(ret); /* -ENOMEM */
 	}
 	btrfs_tree_unlock(next);
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index b823fac..7e55001 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -847,7 +847,7 @@ next_slot:
 						disk_bytenr, num_bytes, 0,
 						root->root_key.objectid,
 						new_key.objectid,
-						start - extent_offset, 1);
+						start - extent_offset);
 				BUG_ON(ret); /* -ENOMEM */
 			}
 			key.offset = start;
@@ -925,7 +925,7 @@ delete_extent_item:
 						disk_bytenr, num_bytes, 0,
 						root->root_key.objectid,
 						key.objectid, key.offset -
-						extent_offset, 0);
+						extent_offset);
 				BUG_ON(ret); /* -ENOMEM */
 				inode_sub_bytes(inode,
 						extent_end - key.offset);
@@ -1204,7 +1204,7 @@ again:
 
 		ret = btrfs_inc_extent_ref(trans, root, bytenr, num_bytes, 0,
 					   root->root_key.objectid,
-					   ino, orig_offset, 1);
+					   ino, orig_offset);
 		BUG_ON(ret); /* -ENOMEM */
 
 		if (split == start) {
@@ -1231,7 +1231,7 @@ again:
 		del_nr++;
 		ret = btrfs_free_extent(trans, root, bytenr, num_bytes,
 					0, root->root_key.objectid,
-					ino, orig_offset, 0);
+					ino, orig_offset);
 		BUG_ON(ret); /* -ENOMEM */
 	}
 	other_start = 0;
@@ -1248,7 +1248,7 @@ again:
 		del_nr++;
 		ret = btrfs_free_extent(trans, root, bytenr, num_bytes,
 					0, root->root_key.objectid,
-					ino, orig_offset, 0);
+					ino, orig_offset);
 		BUG_ON(ret); /* -ENOMEM */
 	}
 	if (del_nr == 0) {
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index b54e630..2a6e24a 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -2569,7 +2569,7 @@ again:
 	ret = btrfs_inc_extent_ref(trans, root, new->bytenr,
 			new->disk_len, 0,
 			backref->root_id, backref->inum,
-			new->file_pos, 0);	/* start - extent_offset */
+			new->file_pos);	/* start - extent_offset */
 	if (ret) {
 		btrfs_abort_transaction(trans, root, ret);
 		goto out_free_path;
@@ -4428,7 +4428,7 @@ delete:
 			ret = btrfs_free_extent(trans, root, extent_start,
 						extent_num_bytes, 0,
 						btrfs_header_owner(leaf),
-						ino, extent_offset, 0);
+						ino, extent_offset);
 			BUG_ON(ret);
 			if (btrfs_should_throttle_delayed_refs(trans, root))
 				btrfs_async_run_delayed_refs(root,
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 641d3dc..abf3e9b 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -3195,41 +3195,6 @@ out:
 	return ret;
 }
 
-/* Helper to check and see if this root currently has a ref on the given disk
- * bytenr.  If it does then we need to update the quota for this root.  This
- * doesn't do anything if quotas aren't enabled.
- */
-static int check_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
-		     u64 disko)
-{
-	struct seq_list tree_mod_seq_elem = SEQ_LIST_INIT(tree_mod_seq_elem);
-	struct ulist *roots;
-	struct ulist_iterator uiter;
-	struct ulist_node *root_node = NULL;
-	int ret;
-
-	if (!root->fs_info->quota_enabled)
-		return 1;
-
-	btrfs_get_tree_mod_seq(root->fs_info, &tree_mod_seq_elem);
-	ret = btrfs_find_all_roots(trans, root->fs_info, disko,
-				   tree_mod_seq_elem.seq, &roots);
-	if (ret < 0)
-		goto out;
-	ret = 0;
-	ULIST_ITER_INIT(&uiter);
-	while ((root_node = ulist_next(roots, &uiter))) {
-		if (root_node->val == root->objectid) {
-			ret = 1;
-			break;
-		}
-	}
-	ulist_free(roots);
-out:
-	btrfs_put_tree_mod_seq(root->fs_info, &tree_mod_seq_elem);
-	return ret;
-}
-
 static int clone_finish_inode_update(struct btrfs_trans_handle *trans,
 				     struct inode *inode,
 				     u64 endoff,
@@ -3344,9 +3309,7 @@ static int btrfs_clone(struct inode *src, struct inode *inode,
 	u32 nritems;
 	int slot;
 	int ret;
-	int no_quota;
 	const u64 len = olen_aligned;
-	u64 last_disko = 0;
 	u64 last_dest_end = destoff;
 
 	ret = -ENOMEM;
@@ -3392,7 +3355,6 @@ static int btrfs_clone(struct inode *src, struct inode *inode,
 
 		nritems = btrfs_header_nritems(path->nodes[0]);
 process_slot:
-		no_quota = 1;
 		if (path->slots[0] >= nritems) {
 			ret = btrfs_next_leaf(BTRFS_I(src)->root, path);
 			if (ret < 0)
@@ -3544,35 +3506,13 @@ process_slot:
 				btrfs_set_file_extent_num_bytes(leaf, extent,
 								datal);
 
-				/*
-				 * We need to look up the roots that point at
-				 * this bytenr and see if the new root does.  If
-				 * it does not we need to make sure we update
-				 * quotas appropriately.
-				 */
-				if (disko && root != BTRFS_I(src)->root &&
-				    disko != last_disko) {
-					no_quota = check_ref(trans, root,
-							     disko);
-					if (no_quota < 0) {
-						btrfs_abort_transaction(trans,
-									root,
-									ret);
-						btrfs_end_transaction(trans,
-								      root);
-						ret = no_quota;
-						goto out;
-					}
-				}
-
 				if (disko) {
 					inode_add_bytes(inode, datal);
 					ret = btrfs_inc_extent_ref(trans, root,
 							disko, diskl, 0,
 							root->root_key.objectid,
 							btrfs_ino(inode),
-							new_key.offset - datao,
-							no_quota);
+							new_key.offset - datao);
 					if (ret) {
 						btrfs_abort_transaction(trans,
 									root,
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index 88cbb59..3a828a3 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -1716,7 +1716,7 @@ int replace_file_extents(struct btrfs_trans_handle *trans,
 		ret = btrfs_inc_extent_ref(trans, root, new_bytenr,
 					   num_bytes, parent,
 					   btrfs_header_owner(leaf),
-					   key.objectid, key.offset, 1);
+					   key.objectid, key.offset);
 		if (ret) {
 			btrfs_abort_transaction(trans, root, ret);
 			break;
@@ -1724,7 +1724,7 @@ int replace_file_extents(struct btrfs_trans_handle *trans,
 
 		ret = btrfs_free_extent(trans, root, bytenr, num_bytes,
 					parent, btrfs_header_owner(leaf),
-					key.objectid, key.offset, 1);
+					key.objectid, key.offset);
 		if (ret) {
 			btrfs_abort_transaction(trans, root, ret);
 			break;
@@ -1900,23 +1900,21 @@ again:
 
 		ret = btrfs_inc_extent_ref(trans, src, old_bytenr, blocksize,
 					path->nodes[level]->start,
-					src->root_key.objectid, level - 1, 0,
-					1);
+					src->root_key.objectid, level - 1, 0);
 		BUG_ON(ret);
 		ret = btrfs_inc_extent_ref(trans, dest, new_bytenr, blocksize,
 					0, dest->root_key.objectid, level - 1,
-					0, 1);
+					0);
 		BUG_ON(ret);
 
 		ret = btrfs_free_extent(trans, src, new_bytenr, blocksize,
 					path->nodes[level]->start,
-					src->root_key.objectid, level - 1, 0,
-					1);
+					src->root_key.objectid, level - 1, 0);
 		BUG_ON(ret);
 
 		ret = btrfs_free_extent(trans, dest, old_bytenr, blocksize,
 					0, dest->root_key.objectid, level - 1,
-					0, 1);
+					0);
 		BUG_ON(ret);
 
 		btrfs_unlock_up_safe(path, 0);
@@ -2746,7 +2744,7 @@ static int do_relocation(struct btrfs_trans_handle *trans,
 						node->eb->start, blocksize,
 						upper->eb->start,
 						btrfs_header_owner(upper->eb),
-						node->level, 0, 1);
+						node->level, 0);
 			BUG_ON(ret);
 
 			ret = btrfs_drop_subtree(trans, root, eb, upper->eb);
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 9c45431..7639695 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -700,7 +700,7 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans,
 				ret = btrfs_inc_extent_ref(trans, root,
 						ins.objectid, ins.offset,
 						0, root->root_key.objectid,
-						key->objectid, offset, 0);
+						key->objectid, offset);
 				if (ret)
 					goto out;
 			} else {
-- 
2.1.3


[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]