Commit d8d11fc7 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Darrick J. Wong

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: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
[darrick: fix unused variable warning]
Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
parent 537dabcf
...@@ -12,9 +12,9 @@ ...@@ -12,9 +12,9 @@
#include "xfs_trans_resv.h" #include "xfs_trans_resv.h"
#include "xfs_bit.h" #include "xfs_bit.h"
#include "xfs_mount.h" #include "xfs_mount.h"
#include "xfs_inode.h"
#include "xfs_dir2.h" #include "xfs_dir2.h"
#include "xfs_dir2_priv.h" #include "xfs_dir2_priv.h"
#include "xfs_inode.h"
#include "xfs_trans.h" #include "xfs_trans.h"
#include "xfs_bmap.h" #include "xfs_bmap.h"
#include "xfs_attr_leaf.h" #include "xfs_attr_leaf.h"
...@@ -2093,18 +2093,6 @@ xfs_da_compname( ...@@ -2093,18 +2093,6 @@ xfs_da_compname(
XFS_CMP_EXACT : XFS_CMP_DIFFERENT; 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 int
xfs_da_grow_inode_int( xfs_da_grow_inode_int(
struct xfs_da_args *args, struct xfs_da_args *args,
......
...@@ -158,16 +158,6 @@ struct xfs_da3_icnode_hdr { ...@@ -158,16 +158,6 @@ struct xfs_da3_icnode_hdr {
(uint)(XFS_DA_LOGOFF(BASE, ADDR)), \ (uint)(XFS_DA_LOGOFF(BASE, ADDR)), \
(uint)(XFS_DA_LOGOFF(BASE, ADDR)+(SIZE)-1) (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. * Function prototypes.
*========================================================================*/ *========================================================================*/
...@@ -234,6 +224,5 @@ void xfs_da3_node_hdr_to_disk(struct xfs_mount *mp, ...@@ -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); struct xfs_da_intnode *to, struct xfs_da3_icnode_hdr *from);
extern struct kmem_zone *xfs_da_state_zone; extern struct kmem_zone *xfs_da_state_zone;
extern const struct xfs_nameops xfs_default_nameops;
#endif /* __XFS_DA_BTREE_H__ */ #endif /* __XFS_DA_BTREE_H__ */
...@@ -52,7 +52,7 @@ xfs_mode_to_ftype( ...@@ -52,7 +52,7 @@ xfs_mode_to_ftype(
* ASCII case-insensitive (ie. A-Z) support for directories that was * ASCII case-insensitive (ie. A-Z) support for directories that was
* used in IRIX. * used in IRIX.
*/ */
STATIC xfs_dahash_t xfs_dahash_t
xfs_ascii_ci_hashname( xfs_ascii_ci_hashname(
struct xfs_name *name) struct xfs_name *name)
{ {
...@@ -65,14 +65,14 @@ xfs_ascii_ci_hashname( ...@@ -65,14 +65,14 @@ xfs_ascii_ci_hashname(
return hash; return hash;
} }
STATIC enum xfs_dacmp enum xfs_dacmp
xfs_ascii_ci_compname( xfs_ascii_ci_compname(
struct xfs_da_args *args, struct xfs_da_args *args,
const unsigned char *name, const unsigned char *name,
int len) int len)
{ {
enum xfs_dacmp result; enum xfs_dacmp result;
int i; int i;
if (args->namelen != len) if (args->namelen != len)
return XFS_CMP_DIFFERENT; return XFS_CMP_DIFFERENT;
...@@ -89,11 +89,6 @@ xfs_ascii_ci_compname( ...@@ -89,11 +89,6 @@ xfs_ascii_ci_compname(
return result; return result;
} }
static const struct xfs_nameops xfs_ascii_ci_nameops = {
.hashname = xfs_ascii_ci_hashname,
.compname = xfs_ascii_ci_compname,
};
int int
xfs_da_mount( xfs_da_mount(
struct xfs_mount *mp) struct xfs_mount *mp)
...@@ -163,12 +158,6 @@ xfs_da_mount( ...@@ -163,12 +158,6 @@ xfs_da_mount(
dageo->node_ents = (dageo->blksize - dageo->node_hdr_size) / dageo->node_ents = (dageo->blksize - dageo->node_hdr_size) /
(uint)sizeof(xfs_da_node_entry_t); (uint)sizeof(xfs_da_node_entry_t);
dageo->magicpct = (dageo->blksize * 37) / 100; 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; return 0;
} }
...@@ -279,7 +268,7 @@ xfs_dir_createname( ...@@ -279,7 +268,7 @@ xfs_dir_createname(
args->name = name->name; args->name = name->name;
args->namelen = name->len; args->namelen = name->len;
args->filetype = name->type; 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->inumber = inum;
args->dp = dp; args->dp = dp;
args->total = total; args->total = total;
...@@ -375,7 +364,7 @@ xfs_dir_lookup( ...@@ -375,7 +364,7 @@ xfs_dir_lookup(
args->name = name->name; args->name = name->name;
args->namelen = name->len; args->namelen = name->len;
args->filetype = name->type; 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->dp = dp;
args->whichfork = XFS_DATA_FORK; args->whichfork = XFS_DATA_FORK;
args->trans = tp; args->trans = tp;
...@@ -447,7 +436,7 @@ xfs_dir_removename( ...@@ -447,7 +436,7 @@ xfs_dir_removename(
args->name = name->name; args->name = name->name;
args->namelen = name->len; args->namelen = name->len;
args->filetype = name->type; 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->inumber = ino;
args->dp = dp; args->dp = dp;
args->total = total; args->total = total;
...@@ -508,7 +497,7 @@ xfs_dir_replace( ...@@ -508,7 +497,7 @@ xfs_dir_replace(
args->name = name->name; args->name = name->name;
args->namelen = name->len; args->namelen = name->len;
args->filetype = name->type; 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->inumber = inum;
args->dp = dp; args->dp = dp;
args->total = total; args->total = total;
......
...@@ -660,13 +660,11 @@ xfs_dir2_block_lookup_int( ...@@ -660,13 +660,11 @@ xfs_dir2_block_lookup_int(
int high; /* binary search high index */ int high; /* binary search high index */
int low; /* binary search low index */ int low; /* binary search low index */
int mid; /* binary search current idx */ int mid; /* binary search current idx */
xfs_mount_t *mp; /* filesystem mount point */
xfs_trans_t *tp; /* transaction pointer */ xfs_trans_t *tp; /* transaction pointer */
enum xfs_dacmp cmp; /* comparison result */ enum xfs_dacmp cmp; /* comparison result */
dp = args->dp; dp = args->dp;
tp = args->trans; tp = args->trans;
mp = dp->i_mount;
error = xfs_dir3_block_read(tp, dp, &bp); error = xfs_dir3_block_read(tp, dp, &bp);
if (error) if (error)
...@@ -718,7 +716,7 @@ xfs_dir2_block_lookup_int( ...@@ -718,7 +716,7 @@ xfs_dir2_block_lookup_int(
* and buffer. If it's the first case-insensitive match, store * and buffer. If it's the first case-insensitive match, store
* the index and buffer and continue looking for an exact match. * 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) { if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) {
args->cmpresult = cmp; args->cmpresult = cmp;
*bpp = bp; *bpp = bp;
...@@ -1218,8 +1216,7 @@ xfs_dir2_sf_to_block( ...@@ -1218,8 +1216,7 @@ xfs_dir2_sf_to_block(
xfs_dir2_data_log_entry(args, bp, dep); xfs_dir2_data_log_entry(args, bp, dep);
name.name = sfep->name; name.name = sfep->name;
name.len = sfep->namelen; name.len = sfep->namelen;
blp[2 + i].hashval = blp[2 + i].hashval = cpu_to_be32(xfs_dir2_hashname(mp, &name));
cpu_to_be32(mp->m_dirnameops->hashname(&name));
blp[2 + i].address = blp[2 + i].address =
cpu_to_be32(xfs_dir2_byte_to_dataptr(newoffset)); cpu_to_be32(xfs_dir2_byte_to_dataptr(newoffset));
offset = (int)((char *)(tagp + 1) - (char *)hdr); offset = (int)((char *)(tagp + 1) - (char *)hdr);
......
...@@ -236,7 +236,7 @@ __xfs_dir3_data_check( ...@@ -236,7 +236,7 @@ __xfs_dir3_data_check(
((char *)dep - (char *)hdr)); ((char *)dep - (char *)hdr));
name.name = dep->name; name.name = dep->name;
name.len = dep->namelen; 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++) { for (i = 0; i < be32_to_cpu(btp->count); i++) {
if (be32_to_cpu(lep[i].address) == addr && if (be32_to_cpu(lep[i].address) == addr &&
be32_to_cpu(lep[i].hashval) == hash) be32_to_cpu(lep[i].hashval) == hash)
......
...@@ -1288,7 +1288,7 @@ xfs_dir2_leaf_lookup_int( ...@@ -1288,7 +1288,7 @@ xfs_dir2_leaf_lookup_int(
* and buffer. If it's the first case-insensitive match, store * and buffer. If it's the first case-insensitive match, store
* the index and buffer and continue looking for an exact match. * 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) { if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) {
args->cmpresult = cmp; args->cmpresult = cmp;
*indexp = index; *indexp = index;
......
...@@ -875,7 +875,7 @@ xfs_dir2_leafn_lookup_for_entry( ...@@ -875,7 +875,7 @@ xfs_dir2_leafn_lookup_for_entry(
* EEXIST immediately. If it's the first case-insensitive * EEXIST immediately. If it's the first case-insensitive
* match, store the block & inode number and continue looking. * 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 (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) {
/* If there is a CI match block, drop it */ /* If there is a CI match block, drop it */
if (args->cmpresult != XFS_CMP_DIFFERENT && if (args->cmpresult != XFS_CMP_DIFFERENT &&
......
...@@ -40,6 +40,9 @@ struct xfs_dir3_icfree_hdr { ...@@ -40,6 +40,9 @@ struct xfs_dir3_icfree_hdr {
}; };
/* xfs_dir2.c */ /* 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, extern int xfs_dir2_grow_inode(struct xfs_da_args *args, int space,
xfs_dir2_db_t *dbp); xfs_dir2_db_t *dbp);
extern int xfs_dir_cilookup_result(struct xfs_da_args *args, extern int xfs_dir_cilookup_result(struct xfs_da_args *args,
...@@ -191,4 +194,25 @@ xfs_dir2_data_entsize( ...@@ -191,4 +194,25 @@ xfs_dir2_data_entsize(
return round_up(len, XFS_DIR2_DATA_ALIGN); 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__ */ #endif /* __XFS_DIR2_PRIV_H__ */
...@@ -914,8 +914,7 @@ xfs_dir2_sf_lookup( ...@@ -914,8 +914,7 @@ xfs_dir2_sf_lookup(
* number. If it's the first case-insensitive match, store the * number. If it's the first case-insensitive match, store the
* inode number and continue looking for an exact match. * inode number and continue looking for an exact match.
*/ */
cmp = dp->i_mount->m_dirnameops->compname(args, sfep->name, cmp = xfs_dir2_compname(args, sfep->name, sfep->namelen);
sfep->namelen);
if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) { if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) {
args->cmpresult = cmp; args->cmpresult = cmp;
args->inumber = xfs_dir2_sf_get_ino(mp, sfp, sfep); args->inumber = xfs_dir2_sf_get_ino(mp, sfp, sfep);
......
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
struct xlog; struct xlog;
struct xfs_inode; struct xfs_inode;
struct xfs_mru_cache; struct xfs_mru_cache;
struct xfs_nameops;
struct xfs_ail; struct xfs_ail;
struct xfs_quotainfo; struct xfs_quotainfo;
struct xfs_da_geometry; struct xfs_da_geometry;
...@@ -154,7 +153,6 @@ typedef struct xfs_mount { ...@@ -154,7 +153,6 @@ typedef struct xfs_mount {
int m_dalign; /* stripe unit */ int m_dalign; /* stripe unit */
int m_swidth; /* stripe width */ int m_swidth; /* stripe width */
uint8_t m_sectbb_log; /* sectlog - BBSHIFT */ 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 */ atomic_t m_active_trans; /* number trans frozen */
struct xfs_mru_cache *m_filestream; /* per-mount filestream data */ struct xfs_mru_cache *m_filestream; /* per-mount filestream data */
struct delayed_work m_reclaim_work; /* background inode reclaim */ struct delayed_work m_reclaim_work; /* background inode reclaim */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment