From: Eric W. Biederman It is very common to hash a dentry and then to call lookup. If we take fs specific hash functions into account the full hash logic can get ugly. Further full_name_hash as an inline function is almost 100 bytes on x86 so having a non-inline choice in some cases can measurably decrease code size. Signed-off-by: Eric W. Biederman Signed-off-by: Andrew Morton --- fs/dcache.c | 44 ++++++++++++++++++++++++--------------- include/linux/dcache.h | 1 2 files changed, 29 insertions(+), 16 deletions(-) diff -puN fs/dcache.c~dcache-add-helper-d_hash_and_lookup fs/dcache.c --- devel/fs/dcache.c~dcache-add-helper-d_hash_and_lookup 2006-02-27 20:58:56.000000000 -0800 +++ devel-akpm/fs/dcache.c 2006-02-27 20:58:56.000000000 -0800 @@ -1106,6 +1106,32 @@ next: } /** + * d_hash_and_lookup - hash the qstr then search for a dentry + * @dir: Directory to search in + * @name: qstr of name we wish to find + * + * On hash failure or on lookup failure NULL is returned. + */ +struct dentry *d_hash_and_lookup(struct dentry *dir, struct qstr *name) +{ + struct dentry *dentry = NULL; + + /* + * Check for a fs-specific hash function. Note that we must + * calculate the standard hash first, as the d_op->d_hash() + * routine may choose to leave the hash value unchanged. + */ + name->hash = full_name_hash(name->name, name->len); + if (dir->d_op && dir->d_op->d_hash) { + if (dir->d_op->d_hash(dir, name) < 0) + goto out; + } + dentry = d_lookup(dir, name); +out: + return dentry; +} + +/** * d_validate - verify dentry provided from insecure source * @dentry: The dentry alleged to be valid child of @dparent * @dparent: The parent dentry (known to be valid) @@ -1618,26 +1644,12 @@ ino_t find_inode_number(struct dentry *d struct dentry * dentry; ino_t ino = 0; - /* - * Check for a fs-specific hash function. Note that we must - * calculate the standard hash first, as the d_op->d_hash() - * routine may choose to leave the hash value unchanged. - */ - name->hash = full_name_hash(name->name, name->len); - if (dir->d_op && dir->d_op->d_hash) - { - if (dir->d_op->d_hash(dir, name) != 0) - goto out; - } - - dentry = d_lookup(dir, name); - if (dentry) - { + dentry = d_hash_and_lookup(dir, name); + if (dentry) { if (dentry->d_inode) ino = dentry->d_inode->i_ino; dput(dentry); } -out: return ino; } diff -puN include/linux/dcache.h~dcache-add-helper-d_hash_and_lookup include/linux/dcache.h --- devel/include/linux/dcache.h~dcache-add-helper-d_hash_and_lookup 2006-02-27 20:58:56.000000000 -0800 +++ devel-akpm/include/linux/dcache.h 2006-02-27 20:58:56.000000000 -0800 @@ -275,6 +275,7 @@ extern void d_move(struct dentry *, stru /* appendix may either be NULL or be used for transname suffixes */ extern struct dentry * d_lookup(struct dentry *, struct qstr *); extern struct dentry * __d_lookup(struct dentry *, struct qstr *); +extern struct dentry * d_hash_and_lookup(struct dentry *, struct qstr *); /* validate "insecure" dentry pointer */ extern int d_validate(struct dentry *, struct dentry *); _