[PATCH] dcache: Add helper d_hash_and_lookup
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 <ebiederm@xmission.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
92476d7fc0
commit
3e7e241f8c
2 changed files with 29 additions and 16 deletions
44
fs/dcache.c
44
fs/dcache.c
|
@ -1100,6 +1100,32 @@ struct dentry * __d_lookup(struct dentry * parent, struct qstr * name)
|
|||
return found;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
@ -1616,26 +1642,12 @@ ino_t find_inode_number(struct dentry *dir, struct qstr *name)
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -275,6 +275,7 @@ extern void d_move(struct dentry *, struct dentry *);
|
|||
/* 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 *);
|
||||
|
|
Loading…
Reference in a new issue