Re: [PATCH] xfs: devirtualize ->m_dirnameops

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

 



On Mon, Nov 11, 2019 at 07:04:15PM +0100, Christoph Hellwig wrote:
> Instead of causing a relatively expensive indirect call for each
> hashing and comparism of a file name in a directory just use an
> inline function and a simple branch on the ASCII CI bit.
> 
> Signed-off-by: Christoph Hellwig <hch@xxxxxx>
> ---
>  fs/xfs/libxfs/xfs_da_btree.c   | 14 +-------------
>  fs/xfs/libxfs/xfs_da_btree.h   | 11 -----------
>  fs/xfs/libxfs/xfs_dir2.c       | 33 +++++++++++----------------------
>  fs/xfs/libxfs/xfs_dir2_block.c |  5 ++---
>  fs/xfs/libxfs/xfs_dir2_data.c  |  2 +-
>  fs/xfs/libxfs/xfs_dir2_leaf.c  |  2 +-
>  fs/xfs/libxfs/xfs_dir2_node.c  |  2 +-
>  fs/xfs/libxfs/xfs_dir2_priv.h  | 24 ++++++++++++++++++++++++
>  fs/xfs/libxfs/xfs_dir2_sf.c    |  3 +--
>  fs/xfs/xfs_mount.h             |  2 --
>  10 files changed, 42 insertions(+), 56 deletions(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_da_btree.c b/fs/xfs/libxfs/xfs_da_btree.c
> index 46b1c3fb305c..bbe883f04bda 100644
> --- a/fs/xfs/libxfs/xfs_da_btree.c
> +++ b/fs/xfs/libxfs/xfs_da_btree.c
> @@ -12,9 +12,9 @@
>  #include "xfs_trans_resv.h"
>  #include "xfs_bit.h"
>  #include "xfs_mount.h"
> +#include "xfs_inode.h"
>  #include "xfs_dir2.h"
>  #include "xfs_dir2_priv.h"
> -#include "xfs_inode.h"
>  #include "xfs_trans.h"
>  #include "xfs_bmap.h"
>  #include "xfs_attr_leaf.h"
> @@ -2098,18 +2098,6 @@ xfs_da_compname(
>  					XFS_CMP_EXACT : XFS_CMP_DIFFERENT;
>  }
>  
> -static xfs_dahash_t
> -xfs_default_hashname(
> -	struct xfs_name	*name)
> -{
> -	return xfs_da_hashname(name->name, name->len);
> -}
> -
> -const struct xfs_nameops xfs_default_nameops = {
> -	.hashname	= xfs_default_hashname,
> -	.compname	= xfs_da_compname
> -};
> -
>  int
>  xfs_da_grow_inode_int(
>  	struct xfs_da_args	*args,
> diff --git a/fs/xfs/libxfs/xfs_da_btree.h b/fs/xfs/libxfs/xfs_da_btree.h
> index 5af4df71e92b..ed3b558a9c1a 100644
> --- a/fs/xfs/libxfs/xfs_da_btree.h
> +++ b/fs/xfs/libxfs/xfs_da_btree.h
> @@ -158,16 +158,6 @@ struct xfs_da3_icnode_hdr {
>  		(uint)(XFS_DA_LOGOFF(BASE, ADDR)), \
>  		(uint)(XFS_DA_LOGOFF(BASE, ADDR)+(SIZE)-1)
>  
> -/*
> - * Name ops for directory and/or attr name operations
> - */
> -struct xfs_nameops {
> -	xfs_dahash_t	(*hashname)(struct xfs_name *);
> -	enum xfs_dacmp	(*compname)(struct xfs_da_args *,
> -					const unsigned char *, int);
> -};
> -
> -
>  /*========================================================================
>   * Function prototypes.
>   *========================================================================*/
> @@ -234,6 +224,5 @@ void	xfs_da3_node_hdr_to_disk(struct xfs_mount *mp,
>  		struct xfs_da_intnode *to, struct xfs_da3_icnode_hdr *from);
>  
>  extern struct kmem_zone *xfs_da_state_zone;
> -extern const struct xfs_nameops xfs_default_nameops;
>  
>  #endif	/* __XFS_DA_BTREE_H__ */
> diff --git a/fs/xfs/libxfs/xfs_dir2.c b/fs/xfs/libxfs/xfs_dir2.c
> index 624c05e77ab4..05182f2ebef4 100644
> --- a/fs/xfs/libxfs/xfs_dir2.c
> +++ b/fs/xfs/libxfs/xfs_dir2.c
> @@ -52,7 +52,7 @@ xfs_mode_to_ftype(
>   * ASCII case-insensitive (ie. A-Z) support for directories that was
>   * used in IRIX.
>   */
> -STATIC xfs_dahash_t
> +xfs_dahash_t
>  xfs_ascii_ci_hashname(
>  	struct xfs_name	*name)
>  {
> @@ -65,14 +65,14 @@ xfs_ascii_ci_hashname(
>  	return hash;
>  }
>  
> -STATIC enum xfs_dacmp
> +enum xfs_dacmp
>  xfs_ascii_ci_compname(
> -	struct xfs_da_args *args,
> -	const unsigned char *name,
> -	int		len)
> +	struct xfs_da_args	*args,
> +	const unsigned char	*name,
> +	int			len)
>  {
> -	enum xfs_dacmp	result;
> -	int		i;
> +	enum xfs_dacmp		result;
> +	int			i;
>  
>  	if (args->namelen != len)
>  		return XFS_CMP_DIFFERENT;
> @@ -89,11 +89,6 @@ xfs_ascii_ci_compname(
>  	return result;
>  }
>  
> -static const struct xfs_nameops xfs_ascii_ci_nameops = {
> -	.hashname	= xfs_ascii_ci_hashname,
> -	.compname	= xfs_ascii_ci_compname,
> -};
> -
>  int
>  xfs_da_mount(
>  	struct xfs_mount	*mp)
> @@ -163,12 +158,6 @@ xfs_da_mount(
>  	dageo->node_ents = (dageo->blksize - dageo->node_hdr_size) /
>  				(uint)sizeof(xfs_da_node_entry_t);
>  	dageo->magicpct = (dageo->blksize * 37) / 100;
> -
> -	if (xfs_sb_version_hasasciici(&mp->m_sb))
> -		mp->m_dirnameops = &xfs_ascii_ci_nameops;
> -	else
> -		mp->m_dirnameops = &xfs_default_nameops;
> -
>  	return 0;
>  }
>  
> @@ -279,7 +268,7 @@ xfs_dir_createname(
>  	args->name = name->name;
>  	args->namelen = name->len;
>  	args->filetype = name->type;
> -	args->hashval = dp->i_mount->m_dirnameops->hashname(name);
> +	args->hashval = xfs_dir2_hashname(dp->i_mount, name);
>  	args->inumber = inum;
>  	args->dp = dp;
>  	args->total = total;
> @@ -375,7 +364,7 @@ xfs_dir_lookup(
>  	args->name = name->name;
>  	args->namelen = name->len;
>  	args->filetype = name->type;
> -	args->hashval = dp->i_mount->m_dirnameops->hashname(name);
> +	args->hashval = xfs_dir2_hashname(dp->i_mount, name);
>  	args->dp = dp;
>  	args->whichfork = XFS_DATA_FORK;
>  	args->trans = tp;
> @@ -447,7 +436,7 @@ xfs_dir_removename(
>  	args->name = name->name;
>  	args->namelen = name->len;
>  	args->filetype = name->type;
> -	args->hashval = dp->i_mount->m_dirnameops->hashname(name);
> +	args->hashval = xfs_dir2_hashname(dp->i_mount, name);
>  	args->inumber = ino;
>  	args->dp = dp;
>  	args->total = total;
> @@ -508,7 +497,7 @@ xfs_dir_replace(
>  	args->name = name->name;
>  	args->namelen = name->len;
>  	args->filetype = name->type;
> -	args->hashval = dp->i_mount->m_dirnameops->hashname(name);
> +	args->hashval = xfs_dir2_hashname(dp->i_mount, name);
>  	args->inumber = inum;
>  	args->dp = dp;
>  	args->total = total;
> diff --git a/fs/xfs/libxfs/xfs_dir2_block.c b/fs/xfs/libxfs/xfs_dir2_block.c
> index 358151ddfa75..f9d83205659e 100644
> --- a/fs/xfs/libxfs/xfs_dir2_block.c
> +++ b/fs/xfs/libxfs/xfs_dir2_block.c
> @@ -718,7 +718,7 @@ xfs_dir2_block_lookup_int(
>  		 * and buffer. If it's the first case-insensitive match, store
>  		 * the index and buffer and continue looking for an exact match.
>  		 */
> -		cmp = mp->m_dirnameops->compname(args, dep->name, dep->namelen);
> +		cmp = xfs_dir2_compname(args, dep->name, dep->namelen);

gcc complains about the unused @mp variable here.  With that fixed the
rest looks ok, so:

Reviewed-by: Darrick J. Wong <darrick.wong@xxxxxxxxxx>

--D

>  		if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) {
>  			args->cmpresult = cmp;
>  			*bpp = bp;
> @@ -1218,8 +1218,7 @@ xfs_dir2_sf_to_block(
>  		xfs_dir2_data_log_entry(args, bp, dep);
>  		name.name = sfep->name;
>  		name.len = sfep->namelen;
> -		blp[2 + i].hashval =
> -			cpu_to_be32(mp->m_dirnameops->hashname(&name));
> +		blp[2 + i].hashval = cpu_to_be32(xfs_dir2_hashname(mp, &name));
>  		blp[2 + i].address =
>  			cpu_to_be32(xfs_dir2_byte_to_dataptr(newoffset));
>  		offset = (int)((char *)(tagp + 1) - (char *)hdr);
> diff --git a/fs/xfs/libxfs/xfs_dir2_data.c b/fs/xfs/libxfs/xfs_dir2_data.c
> index 9e471a28b6c6..11b1f3021e66 100644
> --- a/fs/xfs/libxfs/xfs_dir2_data.c
> +++ b/fs/xfs/libxfs/xfs_dir2_data.c
> @@ -236,7 +236,7 @@ __xfs_dir3_data_check(
>  						((char *)dep - (char *)hdr));
>  			name.name = dep->name;
>  			name.len = dep->namelen;
> -			hash = mp->m_dirnameops->hashname(&name);
> +			hash = xfs_dir2_hashname(mp, &name);
>  			for (i = 0; i < be32_to_cpu(btp->count); i++) {
>  				if (be32_to_cpu(lep[i].address) == addr &&
>  				    be32_to_cpu(lep[i].hashval) == hash)
> diff --git a/fs/xfs/libxfs/xfs_dir2_leaf.c b/fs/xfs/libxfs/xfs_dir2_leaf.c
> index e2e4b2c6d6c2..73edd96ce0ac 100644
> --- a/fs/xfs/libxfs/xfs_dir2_leaf.c
> +++ b/fs/xfs/libxfs/xfs_dir2_leaf.c
> @@ -1288,7 +1288,7 @@ xfs_dir2_leaf_lookup_int(
>  		 * and buffer. If it's the first case-insensitive match, store
>  		 * the index and buffer and continue looking for an exact match.
>  		 */
> -		cmp = mp->m_dirnameops->compname(args, dep->name, dep->namelen);
> +		cmp = xfs_dir2_compname(args, dep->name, dep->namelen);
>  		if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) {
>  			args->cmpresult = cmp;
>  			*indexp = index;
> diff --git a/fs/xfs/libxfs/xfs_dir2_node.c b/fs/xfs/libxfs/xfs_dir2_node.c
> index 5f30a1953a52..f0f67b7eb171 100644
> --- a/fs/xfs/libxfs/xfs_dir2_node.c
> +++ b/fs/xfs/libxfs/xfs_dir2_node.c
> @@ -876,7 +876,7 @@ xfs_dir2_leafn_lookup_for_entry(
>  		 * EEXIST immediately. If it's the first case-insensitive
>  		 * match, store the block & inode number and continue looking.
>  		 */
> -		cmp = mp->m_dirnameops->compname(args, dep->name, dep->namelen);
> +		cmp = xfs_dir2_compname(args, dep->name, dep->namelen);
>  		if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) {
>  			/* If there is a CI match block, drop it */
>  			if (args->cmpresult != XFS_CMP_DIFFERENT &&
> diff --git a/fs/xfs/libxfs/xfs_dir2_priv.h b/fs/xfs/libxfs/xfs_dir2_priv.h
> index a22222df4bf2..eb6af7daf803 100644
> --- a/fs/xfs/libxfs/xfs_dir2_priv.h
> +++ b/fs/xfs/libxfs/xfs_dir2_priv.h
> @@ -40,6 +40,9 @@ struct xfs_dir3_icfree_hdr {
>  };
>  
>  /* xfs_dir2.c */
> +xfs_dahash_t xfs_ascii_ci_hashname(struct xfs_name *name);
> +enum xfs_dacmp xfs_ascii_ci_compname(struct xfs_da_args *args,
> +		const unsigned char *name, int len);
>  extern int xfs_dir2_grow_inode(struct xfs_da_args *args, int space,
>  				xfs_dir2_db_t *dbp);
>  extern int xfs_dir_cilookup_result(struct xfs_da_args *args,
> @@ -191,4 +194,25 @@ xfs_dir2_data_entsize(
>  	return round_up(len, XFS_DIR2_DATA_ALIGN);
>  }
>  
> +static inline xfs_dahash_t
> +xfs_dir2_hashname(
> +	struct xfs_mount	*mp,
> +	struct xfs_name		*name)
> +{
> +	if (unlikely(xfs_sb_version_hasasciici(&mp->m_sb)))
> +		return xfs_ascii_ci_hashname(name);
> +	return xfs_da_hashname(name->name, name->len);
> +}
> +
> +static inline enum xfs_dacmp
> +xfs_dir2_compname(
> +	struct xfs_da_args	*args,
> +	const unsigned char	*name,
> +	int			len)
> +{
> +	if (unlikely(xfs_sb_version_hasasciici(&args->dp->i_mount->m_sb)))
> +		return xfs_ascii_ci_compname(args, name, len);
> +	return xfs_da_compname(args, name, len);
> +}
> +
>  #endif /* __XFS_DIR2_PRIV_H__ */
> diff --git a/fs/xfs/libxfs/xfs_dir2_sf.c b/fs/xfs/libxfs/xfs_dir2_sf.c
> index db1a82972d9e..41eb8a676bf3 100644
> --- a/fs/xfs/libxfs/xfs_dir2_sf.c
> +++ b/fs/xfs/libxfs/xfs_dir2_sf.c
> @@ -914,8 +914,7 @@ xfs_dir2_sf_lookup(
>  		 * number. If it's the first case-insensitive match, store the
>  		 * inode number and continue looking for an exact match.
>  		 */
> -		cmp = dp->i_mount->m_dirnameops->compname(args, sfep->name,
> -								sfep->namelen);
> +		cmp = xfs_dir2_compname(args, sfep->name, sfep->namelen);
>  		if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) {
>  			args->cmpresult = cmp;
>  			args->inumber = xfs_dir2_sf_get_ino(mp, sfp, sfep);
> diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
> index 43145a4ab690..247c2b15a22c 100644
> --- a/fs/xfs/xfs_mount.h
> +++ b/fs/xfs/xfs_mount.h
> @@ -9,7 +9,6 @@
>  struct xlog;
>  struct xfs_inode;
>  struct xfs_mru_cache;
> -struct xfs_nameops;
>  struct xfs_ail;
>  struct xfs_quotainfo;
>  struct xfs_da_geometry;
> @@ -154,7 +153,6 @@ typedef struct xfs_mount {
>  	int			m_dalign;	/* stripe unit */
>  	int			m_swidth;	/* stripe width */
>  	uint8_t			m_sectbb_log;	/* sectlog - BBSHIFT */
> -	const struct xfs_nameops *m_dirnameops;	/* vector of dir name ops */
>  	atomic_t		m_active_trans;	/* number trans frozen */
>  	struct xfs_mru_cache	*m_filestream;  /* per-mount filestream data */
>  	struct delayed_work	m_reclaim_work;	/* background inode reclaim */
> -- 
> 2.20.1
> 



[Index of Archives]     [XFS Filesystem Development (older mail)]     [Linux Filesystem Development]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux RAID]     [Linux SCSI]


  Powered by Linux