Re: [PATCH] Btrfs: take into account total references when doing backref lookup V2

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

 



On Wed, Mar 19, 2014 at 01:35:14PM -0400, Josef Bacik wrote:
> I added an optimization for large files where we would stop searching for
> backrefs once we had looked at the number of references we currently had for
> this extent.  This works great most of the time, but for snapshots that point to
> this extent and has changes in the original root this assumption falls on it
> face.  So keep track of any delayed ref mods made and add in the actual ref
> count as reported by the extent item and use that to limit how far down an inode
> we'll search for extents.  Thanks,
> 
> Reported-by: Hugo Mills <hugo@xxxxxxxxxxxxx>

Reported-by: Hugo Mills <hugo@xxxxxxxxxxxxx>

> Signed-off-by: Josef Bacik <jbacik@xxxxxx>

Tested-by: Hugo Mills <hugo@xxxxxxxxxxxxx>

   Looks like it's worked. (Modulo the above typo in the metadata ;) )
I'll do a more complete test overnight.

   Hugo.

> ---
> V1->V2: Just use the extent ref count and any delayed ref counts, this will work
> out right, whereas the shared thing doesn't work out in some cases.
> 
>  fs/btrfs/backref.c | 29 ++++++++++++++++++-----------
>  1 file changed, 18 insertions(+), 11 deletions(-)
> 
> diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
> index 0be0e94..10db21f 100644
> --- a/fs/btrfs/backref.c
> +++ b/fs/btrfs/backref.c
> @@ -220,7 +220,8 @@ static int __add_prelim_ref(struct list_head *head, u64 root_id,
>  
>  static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path,
>  			   struct ulist *parents, struct __prelim_ref *ref,
> -			   int level, u64 time_seq, const u64 *extent_item_pos)
> +			   int level, u64 time_seq, const u64 *extent_item_pos,
> +			   u64 total_refs)
>  {
>  	int ret = 0;
>  	int slot;
> @@ -249,7 +250,7 @@ static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path,
>  	if (path->slots[0] >= btrfs_header_nritems(path->nodes[0]))
>  		ret = btrfs_next_old_leaf(root, path, time_seq);
>  
> -	while (!ret && count < ref->count) {
> +	while (!ret && count < total_refs) {
>  		eb = path->nodes[0];
>  		slot = path->slots[0];
>  
> @@ -306,7 +307,7 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info,
>  				  struct btrfs_path *path, u64 time_seq,
>  				  struct __prelim_ref *ref,
>  				  struct ulist *parents,
> -				  const u64 *extent_item_pos)
> +				  const u64 *extent_item_pos, u64 total_refs)
>  {
>  	struct btrfs_root *root;
>  	struct btrfs_key root_key;
> @@ -364,7 +365,7 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info,
>  	}
>  
>  	ret = add_all_parents(root, path, parents, ref, level, time_seq,
> -			      extent_item_pos);
> +			      extent_item_pos, total_refs);
>  out:
>  	path->lowest_level = 0;
>  	btrfs_release_path(path);
> @@ -377,7 +378,7 @@ out:
>  static int __resolve_indirect_refs(struct btrfs_fs_info *fs_info,
>  				   struct btrfs_path *path, u64 time_seq,
>  				   struct list_head *head,
> -				   const u64 *extent_item_pos)
> +				   const u64 *extent_item_pos, u64 total_refs)
>  {
>  	int err;
>  	int ret = 0;
> @@ -403,7 +404,8 @@ static int __resolve_indirect_refs(struct btrfs_fs_info *fs_info,
>  		if (ref->count == 0)
>  			continue;
>  		err = __resolve_indirect_ref(fs_info, path, time_seq, ref,
> -					     parents, extent_item_pos);
> +					     parents, extent_item_pos,
> +					     total_refs);
>  		/*
>  		 * we can only tolerate ENOENT,otherwise,we should catch error
>  		 * and return directly.
> @@ -560,7 +562,7 @@ static void __merge_refs(struct list_head *head, int mode)
>   * smaller or equal that seq to the list
>   */
>  static int __add_delayed_refs(struct btrfs_delayed_ref_head *head, u64 seq,
> -			      struct list_head *prefs)
> +			      struct list_head *prefs, u64 *total_refs)
>  {
>  	struct btrfs_delayed_extent_op *extent_op = head->extent_op;
>  	struct rb_node *n = &head->node.rb_node;
> @@ -596,6 +598,7 @@ static int __add_delayed_refs(struct btrfs_delayed_ref_head *head, u64 seq,
>  		default:
>  			BUG_ON(1);
>  		}
> +		*total_refs += (node->ref_mod * sgn);
>  		switch (node->type) {
>  		case BTRFS_TREE_BLOCK_REF_KEY: {
>  			struct btrfs_delayed_tree_ref *ref;
> @@ -656,7 +659,8 @@ static int __add_delayed_refs(struct btrfs_delayed_ref_head *head, u64 seq,
>   */
>  static int __add_inline_refs(struct btrfs_fs_info *fs_info,
>  			     struct btrfs_path *path, u64 bytenr,
> -			     int *info_level, struct list_head *prefs)
> +			     int *info_level, struct list_head *prefs,
> +			     u64 *total_refs)
>  {
>  	int ret = 0;
>  	int slot;
> @@ -680,6 +684,7 @@ static int __add_inline_refs(struct btrfs_fs_info *fs_info,
>  
>  	ei = btrfs_item_ptr(leaf, slot, struct btrfs_extent_item);
>  	flags = btrfs_extent_flags(leaf, ei);
> +	*total_refs += btrfs_extent_refs(leaf, ei);
>  	btrfs_item_key_to_cpu(leaf, &found_key, slot);
>  
>  	ptr = (unsigned long)(ei + 1);
> @@ -862,6 +867,7 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
>  	struct list_head prefs;
>  	struct __prelim_ref *ref;
>  	struct extent_inode_elem *eie = NULL;
> +	u64 total_refs = 0;
>  
>  	INIT_LIST_HEAD(&prefs);
>  	INIT_LIST_HEAD(&prefs_delayed);
> @@ -920,7 +926,7 @@ again:
>  			}
>  			spin_unlock(&delayed_refs->lock);
>  			ret = __add_delayed_refs(head, time_seq,
> -						 &prefs_delayed);
> +						 &prefs_delayed, &total_refs);
>  			mutex_unlock(&head->mutex);
>  			if (ret)
>  				goto out;
> @@ -941,7 +947,8 @@ again:
>  		    (key.type == BTRFS_EXTENT_ITEM_KEY ||
>  		     key.type == BTRFS_METADATA_ITEM_KEY)) {
>  			ret = __add_inline_refs(fs_info, path, bytenr,
> -						&info_level, &prefs);
> +						&info_level, &prefs,
> +						&total_refs);
>  			if (ret)
>  				goto out;
>  			ret = __add_keyed_refs(fs_info, path, bytenr,
> @@ -961,7 +968,7 @@ again:
>  	__merge_refs(&prefs, 1);
>  
>  	ret = __resolve_indirect_refs(fs_info, path, time_seq, &prefs,
> -				      extent_item_pos);
> +				      extent_item_pos, total_refs);
>  	if (ret)
>  		goto out;
>  

-- 
=== Hugo Mills: hugo@... carfax.org.uk | darksatanic.net | lug.org.uk ===
  PGP key: 65E74AC0 from wwwkeys.eu.pgp.net or http://www.carfax.org.uk
      --- What's a Nazgûl like you doing in a place like this? ---      

Attachment: signature.asc
Description: Digital signature


[Index of Archives]     [Linux Filesystem Development]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux