Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Christoph Hellwig and committed by
Darrick J. Wong
d8d11fc7 537dabcf

+42 -58
+1 -13
fs/xfs/libxfs/xfs_da_btree.c
··· 12 12 #include "xfs_trans_resv.h" 13 13 #include "xfs_bit.h" 14 14 #include "xfs_mount.h" 15 + #include "xfs_inode.h" 15 16 #include "xfs_dir2.h" 16 17 #include "xfs_dir2_priv.h" 17 - #include "xfs_inode.h" 18 18 #include "xfs_trans.h" 19 19 #include "xfs_bmap.h" 20 20 #include "xfs_attr_leaf.h" ··· 2092 2092 return (args->namelen == len && memcmp(args->name, name, len) == 0) ? 2093 2093 XFS_CMP_EXACT : XFS_CMP_DIFFERENT; 2094 2094 } 2095 - 2096 - static xfs_dahash_t 2097 - xfs_default_hashname( 2098 - struct xfs_name *name) 2099 - { 2100 - return xfs_da_hashname(name->name, name->len); 2101 - } 2102 - 2103 - const struct xfs_nameops xfs_default_nameops = { 2104 - .hashname = xfs_default_hashname, 2105 - .compname = xfs_da_compname 2106 - }; 2107 2095 2108 2096 int 2109 2097 xfs_da_grow_inode_int(
-11
fs/xfs/libxfs/xfs_da_btree.h
··· 158 158 (uint)(XFS_DA_LOGOFF(BASE, ADDR)), \ 159 159 (uint)(XFS_DA_LOGOFF(BASE, ADDR)+(SIZE)-1) 160 160 161 - /* 162 - * Name ops for directory and/or attr name operations 163 - */ 164 - struct xfs_nameops { 165 - xfs_dahash_t (*hashname)(struct xfs_name *); 166 - enum xfs_dacmp (*compname)(struct xfs_da_args *, 167 - const unsigned char *, int); 168 - }; 169 - 170 - 171 161 /*======================================================================== 172 162 * Function prototypes. 173 163 *========================================================================*/ ··· 224 234 struct xfs_da_intnode *to, struct xfs_da3_icnode_hdr *from); 225 235 226 236 extern struct kmem_zone *xfs_da_state_zone; 227 - extern const struct xfs_nameops xfs_default_nameops; 228 237 229 238 #endif /* __XFS_DA_BTREE_H__ */
+11 -22
fs/xfs/libxfs/xfs_dir2.c
··· 52 52 * ASCII case-insensitive (ie. A-Z) support for directories that was 53 53 * used in IRIX. 54 54 */ 55 - STATIC xfs_dahash_t 55 + xfs_dahash_t 56 56 xfs_ascii_ci_hashname( 57 57 struct xfs_name *name) 58 58 { ··· 65 65 return hash; 66 66 } 67 67 68 - STATIC enum xfs_dacmp 68 + enum xfs_dacmp 69 69 xfs_ascii_ci_compname( 70 - struct xfs_da_args *args, 71 - const unsigned char *name, 72 - int len) 70 + struct xfs_da_args *args, 71 + const unsigned char *name, 72 + int len) 73 73 { 74 - enum xfs_dacmp result; 75 - int i; 74 + enum xfs_dacmp result; 75 + int i; 76 76 77 77 if (args->namelen != len) 78 78 return XFS_CMP_DIFFERENT; ··· 88 88 89 89 return result; 90 90 } 91 - 92 - static const struct xfs_nameops xfs_ascii_ci_nameops = { 93 - .hashname = xfs_ascii_ci_hashname, 94 - .compname = xfs_ascii_ci_compname, 95 - }; 96 91 97 92 int 98 93 xfs_da_mount( ··· 158 163 dageo->node_ents = (dageo->blksize - dageo->node_hdr_size) / 159 164 (uint)sizeof(xfs_da_node_entry_t); 160 165 dageo->magicpct = (dageo->blksize * 37) / 100; 161 - 162 - if (xfs_sb_version_hasasciici(&mp->m_sb)) 163 - mp->m_dirnameops = &xfs_ascii_ci_nameops; 164 - else 165 - mp->m_dirnameops = &xfs_default_nameops; 166 - 167 166 return 0; 168 167 } 169 168 ··· 268 279 args->name = name->name; 269 280 args->namelen = name->len; 270 281 args->filetype = name->type; 271 - args->hashval = dp->i_mount->m_dirnameops->hashname(name); 282 + args->hashval = xfs_dir2_hashname(dp->i_mount, name); 272 283 args->inumber = inum; 273 284 args->dp = dp; 274 285 args->total = total; ··· 364 375 args->name = name->name; 365 376 args->namelen = name->len; 366 377 args->filetype = name->type; 367 - args->hashval = dp->i_mount->m_dirnameops->hashname(name); 378 + args->hashval = xfs_dir2_hashname(dp->i_mount, name); 368 379 args->dp = dp; 369 380 args->whichfork = XFS_DATA_FORK; 370 381 args->trans = tp; ··· 436 447 args->name = name->name; 437 448 args->namelen = name->len; 438 449 args->filetype = name->type; 439 - args->hashval = dp->i_mount->m_dirnameops->hashname(name); 450 + args->hashval = xfs_dir2_hashname(dp->i_mount, name); 440 451 args->inumber = ino; 441 452 args->dp = dp; 442 453 args->total = total; ··· 497 508 args->name = name->name; 498 509 args->namelen = name->len; 499 510 args->filetype = name->type; 500 - args->hashval = dp->i_mount->m_dirnameops->hashname(name); 511 + args->hashval = xfs_dir2_hashname(dp->i_mount, name); 501 512 args->inumber = inum; 502 513 args->dp = dp; 503 514 args->total = total;
+2 -5
fs/xfs/libxfs/xfs_dir2_block.c
··· 660 660 int high; /* binary search high index */ 661 661 int low; /* binary search low index */ 662 662 int mid; /* binary search current idx */ 663 - xfs_mount_t *mp; /* filesystem mount point */ 664 663 xfs_trans_t *tp; /* transaction pointer */ 665 664 enum xfs_dacmp cmp; /* comparison result */ 666 665 667 666 dp = args->dp; 668 667 tp = args->trans; 669 - mp = dp->i_mount; 670 668 671 669 error = xfs_dir3_block_read(tp, dp, &bp); 672 670 if (error) ··· 716 718 * and buffer. If it's the first case-insensitive match, store 717 719 * the index and buffer and continue looking for an exact match. 718 720 */ 719 - cmp = mp->m_dirnameops->compname(args, dep->name, dep->namelen); 721 + cmp = xfs_dir2_compname(args, dep->name, dep->namelen); 720 722 if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) { 721 723 args->cmpresult = cmp; 722 724 *bpp = bp; ··· 1216 1218 xfs_dir2_data_log_entry(args, bp, dep); 1217 1219 name.name = sfep->name; 1218 1220 name.len = sfep->namelen; 1219 - blp[2 + i].hashval = 1220 - cpu_to_be32(mp->m_dirnameops->hashname(&name)); 1221 + blp[2 + i].hashval = cpu_to_be32(xfs_dir2_hashname(mp, &name)); 1221 1222 blp[2 + i].address = 1222 1223 cpu_to_be32(xfs_dir2_byte_to_dataptr(newoffset)); 1223 1224 offset = (int)((char *)(tagp + 1) - (char *)hdr);
+1 -1
fs/xfs/libxfs/xfs_dir2_data.c
··· 236 236 ((char *)dep - (char *)hdr)); 237 237 name.name = dep->name; 238 238 name.len = dep->namelen; 239 - hash = mp->m_dirnameops->hashname(&name); 239 + hash = xfs_dir2_hashname(mp, &name); 240 240 for (i = 0; i < be32_to_cpu(btp->count); i++) { 241 241 if (be32_to_cpu(lep[i].address) == addr && 242 242 be32_to_cpu(lep[i].hashval) == hash)
+1 -1
fs/xfs/libxfs/xfs_dir2_leaf.c
··· 1288 1288 * and buffer. If it's the first case-insensitive match, store 1289 1289 * the index and buffer and continue looking for an exact match. 1290 1290 */ 1291 - cmp = mp->m_dirnameops->compname(args, dep->name, dep->namelen); 1291 + cmp = xfs_dir2_compname(args, dep->name, dep->namelen); 1292 1292 if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) { 1293 1293 args->cmpresult = cmp; 1294 1294 *indexp = index;
+1 -1
fs/xfs/libxfs/xfs_dir2_node.c
··· 875 875 * EEXIST immediately. If it's the first case-insensitive 876 876 * match, store the block & inode number and continue looking. 877 877 */ 878 - cmp = mp->m_dirnameops->compname(args, dep->name, dep->namelen); 878 + cmp = xfs_dir2_compname(args, dep->name, dep->namelen); 879 879 if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) { 880 880 /* If there is a CI match block, drop it */ 881 881 if (args->cmpresult != XFS_CMP_DIFFERENT &&
+24
fs/xfs/libxfs/xfs_dir2_priv.h
··· 40 40 }; 41 41 42 42 /* xfs_dir2.c */ 43 + xfs_dahash_t xfs_ascii_ci_hashname(struct xfs_name *name); 44 + enum xfs_dacmp xfs_ascii_ci_compname(struct xfs_da_args *args, 45 + const unsigned char *name, int len); 43 46 extern int xfs_dir2_grow_inode(struct xfs_da_args *args, int space, 44 47 xfs_dir2_db_t *dbp); 45 48 extern int xfs_dir_cilookup_result(struct xfs_da_args *args, ··· 192 189 if (xfs_sb_version_hasftype(&mp->m_sb)) 193 190 len += sizeof(uint8_t); 194 191 return round_up(len, XFS_DIR2_DATA_ALIGN); 192 + } 193 + 194 + static inline xfs_dahash_t 195 + xfs_dir2_hashname( 196 + struct xfs_mount *mp, 197 + struct xfs_name *name) 198 + { 199 + if (unlikely(xfs_sb_version_hasasciici(&mp->m_sb))) 200 + return xfs_ascii_ci_hashname(name); 201 + return xfs_da_hashname(name->name, name->len); 202 + } 203 + 204 + static inline enum xfs_dacmp 205 + xfs_dir2_compname( 206 + struct xfs_da_args *args, 207 + const unsigned char *name, 208 + int len) 209 + { 210 + if (unlikely(xfs_sb_version_hasasciici(&args->dp->i_mount->m_sb))) 211 + return xfs_ascii_ci_compname(args, name, len); 212 + return xfs_da_compname(args, name, len); 195 213 } 196 214 197 215 #endif /* __XFS_DIR2_PRIV_H__ */
+1 -2
fs/xfs/libxfs/xfs_dir2_sf.c
··· 914 914 * number. If it's the first case-insensitive match, store the 915 915 * inode number and continue looking for an exact match. 916 916 */ 917 - cmp = dp->i_mount->m_dirnameops->compname(args, sfep->name, 918 - sfep->namelen); 917 + cmp = xfs_dir2_compname(args, sfep->name, sfep->namelen); 919 918 if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) { 920 919 args->cmpresult = cmp; 921 920 args->inumber = xfs_dir2_sf_get_ino(mp, sfp, sfep);
-2
fs/xfs/xfs_mount.h
··· 9 9 struct xlog; 10 10 struct xfs_inode; 11 11 struct xfs_mru_cache; 12 - struct xfs_nameops; 13 12 struct xfs_ail; 14 13 struct xfs_quotainfo; 15 14 struct xfs_da_geometry; ··· 153 154 int m_dalign; /* stripe unit */ 154 155 int m_swidth; /* stripe width */ 155 156 uint8_t m_sectbb_log; /* sectlog - BBSHIFT */ 156 - const struct xfs_nameops *m_dirnameops; /* vector of dir name ops */ 157 157 atomic_t m_active_trans; /* number trans frozen */ 158 158 struct xfs_mru_cache *m_filestream; /* per-mount filestream data */ 159 159 struct delayed_work m_reclaim_work; /* background inode reclaim */