xfs: devirtualize ->m_dirnameops
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@lst.de> Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com> [darrick: fix unused variable warning] Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
This commit is contained in:
		
							parent
							
								
									537dabcfdb
								
							
						
					
					
						commit
						d8d11fc703
					
				| @ -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" | ||||
| @ -2093,18 +2093,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, | ||||
|  | ||||
| @ -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__ */ | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
| @ -660,13 +660,11 @@ xfs_dir2_block_lookup_int( | ||||
| 	int			high;		/* binary search high index */ | ||||
| 	int			low;		/* binary search low index */ | ||||
| 	int			mid;		/* binary search current idx */ | ||||
| 	xfs_mount_t		*mp;		/* filesystem mount point */ | ||||
| 	xfs_trans_t		*tp;		/* transaction pointer */ | ||||
| 	enum xfs_dacmp		cmp;		/* comparison result */ | ||||
| 
 | ||||
| 	dp = args->dp; | ||||
| 	tp = args->trans; | ||||
| 	mp = dp->i_mount; | ||||
| 
 | ||||
| 	error = xfs_dir3_block_read(tp, dp, &bp); | ||||
| 	if (error) | ||||
| @ -718,7 +716,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); | ||||
| 		if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) { | ||||
| 			args->cmpresult = cmp; | ||||
| 			*bpp = bp; | ||||
| @ -1218,8 +1216,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); | ||||
|  | ||||
| @ -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) | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
| @ -875,7 +875,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 && | ||||
|  | ||||
| @ -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__ */ | ||||
|  | ||||
| @ -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); | ||||
|  | ||||
| @ -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 */ | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user