All of lore.kernel.org
 help / color / mirror / Atom feed
From: Marcos Paulo de Souza <mpdesouza@suse.de>
To: Johannes Thumshirn <Johannes.Thumshirn@wdc.com>,
	"linux-btrfs@vger.kernel.org" <linux-btrfs@vger.kernel.org>
Cc: "dsterba@suse.com" <dsterba@suse.com>,
	"nborisov@suse.com" <nborisov@suse.com>
Subject: Re: [PATCH 1/7] fs: btrfs: Introduce btrfs_for_each_slot
Date: Wed, 25 Aug 2021 10:32:13 -0300	[thread overview]
Message-ID: <824cf659f83d3714a32ba99c951909e1f4aaff64.camel@suse.de> (raw)
In-Reply-To: <PH0PR04MB74165AAE8DA3D7BA81C2A0AC9BC69@PH0PR04MB7416.namprd04.prod.outlook.com>

On Wed, 2021-08-25 at 07:42 +0000, Johannes Thumshirn wrote:
> On 24/08/2021 19:13, Marcos Paulo de Souza wrote:
> > There is a common pattern when search for a key in btrfs:
> > 
> >  * Call btrfs_search_slot
> >  * Endless loop
> > 	 * If the found slot is bigger than the current items in the
> > leaf, check the
> > 	   next one
> > 	 * If still not found in the next leaf, return 1
> > 	 * Do something with the code
> > 	 * Increment current slot, and continue
> > 
> > This pattern can be improved by creating an iterator macro, similar
> > to
> > those for_each_X already existing in the linux kernel. Using this
> > approach means to reduce significantly boilerplate code, along
> > making it
> > easier to newcomers to understand how to code works.
> > 
> > Signed-off-by: Marcos Paulo de Souza <mpdesouza@suse.com>
> > ---
> >  fs/btrfs/ctree.c | 28 ++++++++++++++++++++++++++++
> >  fs/btrfs/ctree.h | 25 +++++++++++++++++++++++++
> >  fs/btrfs/xattr.c | 40 ++++++++++++----------------------------
> >  3 files changed, 65 insertions(+), 28 deletions(-)
> > 
> > diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
> > index 84627cbd5b5b..b1aa6e3987d0 100644
> > --- a/fs/btrfs/ctree.c
> > +++ b/fs/btrfs/ctree.c
> > @@ -2122,6 +2122,34 @@ int btrfs_search_backwards(struct btrfs_root
> > *root, struct btrfs_key *key,
> >  	return ret;
> >  }
> >  
> > +/* Search for a valid slot for the given path.
> > + * @root: The root node of the tree.
> > + * @key: Will contain a valid item if found.
> > + * @path: The start point to validate the slot.
> > + *
> > + * Return 0 if the item is valid, 1 if not found and < 0 if error.
> > + */
> > +int btrfs_valid_slot(struct btrfs_root *root, struct btrfs_key
> > *key,
> > +		     struct btrfs_path *path)
> > +{
> > +	while (1) {
> > +		int ret;
> > +		const int slot = path->slots[0];
> > +		const struct extent_buffer *leaf = path->nodes[0];
> > +
> > +		if (slot >= btrfs_header_nritems(leaf)) {
> > +			ret = btrfs_next_leaf(root, path);
> > +			if (ret)
> > +				return ret;
> > +			continue;
> > +		}
> > +		btrfs_item_key_to_cpu(leaf, key, slot);
> > +		break;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> >  /*
> >   * adjust the pointers going up the tree, starting at level
> >   * making sure the right key of each node is points to 'key'.
> > diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
> > index f07c82fafa04..1e3c4a7741ca 100644
> > --- a/fs/btrfs/ctree.h
> > +++ b/fs/btrfs/ctree.h
> > @@ -2912,6 +2912,31 @@ int btrfs_next_old_leaf(struct btrfs_root
> > *root, struct btrfs_path *path,
> >  int btrfs_search_backwards(struct btrfs_root *root, struct
> > btrfs_key *key,
> >  			   struct btrfs_path *path);
> >  
> > +int btrfs_valid_slot(struct btrfs_root *root, struct btrfs_key
> > *key,
> > +		     struct btrfs_path *path);
> > +
> > +/* Search in @root for a given @key, and store the slot found in
> > @found_key.
> > + * @root: The root node of the tree.
> > + * @key: The key we are looking for.
> > + * @found_key: Will hold the found item.
> > + * @path: Holds the current slot/leaf.
> > + * @iter_ret: Contains the returned value from btrfs_search_slot
> > and
> > + *            btrfs_valid_slot, whatever is executed later.
> > + *
> > + * The iter_ret is an output variable that will contain the result
> > of the
> > + * btrfs_search_slot if it returns an error, or the value returned
> > from
> > + * btrfs_valid_slot otherwise. The return value can be 0 if the
> > something was
> > + * found, 1 if there weren't bigger leaves, and <0 if error.
> > + */
> > +#define btrfs_for_each_slot(root, key, found_key, path, iter_ret)	
> > 	\
> > +	for (iter_ret = btrfs_search_slot(NULL, root, key, path, 0, 0);
> > 		\
> > +		(								
> > \
> > +			iter_ret >= 0 &&					
> > \
> > +			(iter_ret = btrfs_valid_slot(root, found_key,
> > path)) == 0 \
> > +		);								
> >   \
> > +		path->slots[0]++						
> >   \
> > +	)
> > +
> >  static inline int btrfs_next_old_item(struct btrfs_root *root,
> >  				      struct btrfs_path *p, u64
> > time_seq)
> >  {
> 
> Shouldn't below xattr code be in a separate patch? Just like the
> block-group,
> dev-replace, etc changes?

You're right, this was a leftover of my RFC patches. I'll send a new
version as soon.

> 
> > diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c
> > index 8a4514283a4b..f85febba1891 100644
> > --- a/fs/btrfs/xattr.c
> > +++ b/fs/btrfs/xattr.c
> > @@ -274,10 +274,12 @@ int btrfs_setxattr_trans(struct inode *inode,
> > const char *name,
> >  ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer,
> > size_t size)
> >  {
> >  	struct btrfs_key key;
> > +	struct btrfs_key found_key;
> >  	struct inode *inode = d_inode(dentry);
> >  	struct btrfs_root *root = BTRFS_I(inode)->root;
> >  	struct btrfs_path *path;
> >  	int ret = 0;
> > +	int iter_ret = 0;
> >  	size_t total_size = 0, size_left = size;
> >  
> >  	/*
> > @@ -295,44 +297,22 @@ ssize_t btrfs_listxattr(struct dentry
> > *dentry, char *buffer, size_t size)
> >  	path->reada = READA_FORWARD;
> >  
> >  	/* search for our xattrs */
> > -	ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
> > -	if (ret < 0)
> > -		goto err;
> > -
> > -	while (1) {
> > +	btrfs_for_each_slot(root, &key, &found_key, path, iter_ret) {
> >  		struct extent_buffer *leaf;
> >  		int slot;
> >  		struct btrfs_dir_item *di;
> > -		struct btrfs_key found_key;
> >  		u32 item_size;
> >  		u32 cur;
> >  
> >  		leaf = path->nodes[0];
> >  		slot = path->slots[0];
> >  
> > -		/* this is where we start walking through the path */
> > -		if (slot >= btrfs_header_nritems(leaf)) {
> > -			/*
> > -			 * if we've reached the last slot in this leaf
> > we need
> > -			 * to go to the next leaf and reset everything
> > -			 */
> > -			ret = btrfs_next_leaf(root, path);
> > -			if (ret < 0)
> > -				goto err;
> > -			else if (ret > 0)
> > -				break;
> > -			continue;
> > -		}
> > -
> > -		btrfs_item_key_to_cpu(leaf, &found_key, slot);
> > -
> >  		/* check to make sure this item is what we want */
> > -		if (found_key.objectid != key.objectid)
> > -			break;
> > -		if (found_key.type > BTRFS_XATTR_ITEM_KEY)
> > +		if (found_key.objectid != key.objectid ||
> > +		    found_key.type > BTRFS_XATTR_ITEM_KEY)
> >  			break;
> >  		if (found_key.type < BTRFS_XATTR_ITEM_KEY)
> > -			goto next_item;
> > +			continue;
> >  
> >  		di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item);
> >  		item_size = btrfs_item_size_nr(leaf, slot);
> > @@ -365,9 +345,13 @@ ssize_t btrfs_listxattr(struct dentry *dentry,
> > char *buffer, size_t size)
> >  			cur += this_len;
> >  			di = (struct btrfs_dir_item *)((char *)di +
> > this_len);
> >  		}
> > -next_item:
> > -		path->slots[0]++;
> >  	}
> > +
> > +	if (iter_ret < 0) {
> > +		ret = iter_ret;
> > +		goto err;
> > +	}
> > +
> >  	ret = total_size;
> >  
> >  err:
> > 


  parent reply	other threads:[~2021-08-25 13:33 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-08-24 17:06 [PATCH 0/7] btrfs: Create macro to iterate slots Marcos Paulo de Souza
2021-08-24 17:06 ` [PATCH 1/7] fs: btrfs: Introduce btrfs_for_each_slot Marcos Paulo de Souza
2021-08-25  7:42   ` Johannes Thumshirn
2021-08-25 13:05     ` David Sterba
2021-08-25 13:32     ` Marcos Paulo de Souza [this message]
2021-08-24 17:06 ` [PATCH 2/7] btrfs: block-group: use btrfs_for_each_slot in find_first_block_group Marcos Paulo de Souza
2021-08-24 17:06 ` [PATCH 3/7] btrfs: dev-replace: Use btrfs_for_each_slot in mark_block_group_to_copy Marcos Paulo de Souza
2021-08-24 17:06 ` [PATCH 4/7] btrfs: dir-item: use btrfs_for_each_slot in btrfs_search_dir_index_item Marcos Paulo de Souza
2021-08-24 17:06 ` [PATCH 5/7] btrfs: inode: use btrfs_for_each_slot in btrfs_read_readdir Marcos Paulo de Souza
2021-08-24 17:06 ` [PATCH 6/7] btrfs: send: Use btrfs_for_each_slot macro Marcos Paulo de Souza
2021-08-24 17:06 ` [PATCH 7/7] btrfs: volumes: use btrfs_for_each_slot in btrfs_read_chunk_tree Marcos Paulo de Souza

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=824cf659f83d3714a32ba99c951909e1f4aaff64.camel@suse.de \
    --to=mpdesouza@suse.de \
    --cc=Johannes.Thumshirn@wdc.com \
    --cc=dsterba@suse.com \
    --cc=linux-btrfs@vger.kernel.org \
    --cc=nborisov@suse.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.