diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 7255b0c7aa7e2d967cab8fe6ecda4045f24072a9..df40cc5fd13a31f5d2ed3b3367f4c5beab518d3a 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -82,12 +82,10 @@ cifs_prime_dcache(struct dentry *parent, struct qstr *name, cFYI(1, "%s: for %s", __func__, name->name); - if (parent->d_op && parent->d_op->d_hash) - parent->d_op->d_hash(parent, parent->d_inode, name); - else - name->hash = full_name_hash(name->name, name->len); + dentry = d_hash_and_lookup(parent, name); + if (unlikely(IS_ERR(dentry))) + return; - dentry = d_lookup(parent, name); if (dentry) { int err; diff --git a/fs/dcache.c b/fs/dcache.c index ada6123414aec5dd4ff43cb725af35b1da69a3cc..ebab049826c0029349700eeac251f57cfbbba10f 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -1672,7 +1672,6 @@ EXPORT_SYMBOL(d_splice_alias); struct dentry *d_add_ci(struct dentry *dentry, struct inode *inode, struct qstr *name) { - int error; struct dentry *found; struct dentry *new; @@ -1681,10 +1680,12 @@ struct dentry *d_add_ci(struct dentry *dentry, struct inode *inode, * if not go ahead and create it now. */ found = d_hash_and_lookup(dentry->d_parent, name); + if (unlikely(IS_ERR(found))) + goto err_out; if (!found) { new = d_alloc(dentry->d_parent, name); if (!new) { - error = -ENOMEM; + found = ERR_PTR(-ENOMEM); goto err_out; } @@ -1725,7 +1726,7 @@ struct dentry *d_add_ci(struct dentry *dentry, struct inode *inode, err_out: iput(inode); - return ERR_PTR(error); + return found; } EXPORT_SYMBOL(d_add_ci); @@ -1997,12 +1998,10 @@ struct dentry *__d_lookup(const struct dentry *parent, const struct qstr *name) * @dir: Directory to search in * @name: qstr of name we wish to find * - * On hash failure or on lookup failure NULL is returned. + * On lookup failure NULL is returned; on bad name - ERR_PTR(-error) */ 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() @@ -2010,13 +2009,13 @@ struct dentry *d_hash_and_lookup(struct dentry *dir, struct qstr *name) */ name->hash = full_name_hash(name->name, name->len); if (dir->d_flags & DCACHE_OP_HASH) { - if (dir->d_op->d_hash(dir, dir->d_inode, name) < 0) - goto out; + int err = dir->d_op->d_hash(dir, dir->d_inode, name); + if (unlikely(err < 0)) + return ERR_PTR(err); } - dentry = d_lookup(dir, name); -out: - return dentry; + return d_lookup(dir, name); } +EXPORT_SYMBOL(d_hash_and_lookup); /** * d_validate - verify dentry provided from insecure source (deprecated) @@ -2995,7 +2994,7 @@ ino_t find_inode_number(struct dentry *dir, struct qstr *name) ino_t ino = 0; dentry = d_hash_and_lookup(dir, name); - if (dentry) { + if (!IS_ERR_OR_NULL(dentry)) { if (dentry->d_inode) ino = dentry->d_inode->i_ino; dput(dentry); diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c index 4117e7b377bbf731a5345ef8b640ad5aa6607837..8163260936561f07834f90beb2055dcd9300e1a6 100644 --- a/fs/ncpfs/dir.c +++ b/fs/ncpfs/dir.c @@ -593,14 +593,10 @@ ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir, return 1; /* I'm not sure */ qname.name = __name; - qname.hash = full_name_hash(qname.name, qname.len); - - if (dentry->d_op && dentry->d_op->d_hash) - if (dentry->d_op->d_hash(dentry, dentry->d_inode, &qname) != 0) - goto end_advance; - - newdent = d_lookup(dentry, &qname); + newdent = d_hash_and_lookup(dentry, &qname); + if (unlikely(IS_ERR(newdent))) + goto end_advance; if (!newdent) { newdent = d_alloc(dentry, &qname); if (!newdent) diff --git a/fs/proc/base.c b/fs/proc/base.c index 760268d6cba6e4a68b9549174af066d78344d41c..9d962555972791c41d6e8d154ff53c425b300a9d 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -2618,6 +2618,7 @@ static void proc_flush_task_mnt(struct vfsmount *mnt, pid_t pid, pid_t tgid) name.name = buf; name.len = snprintf(buf, sizeof(buf), "%d", pid); + /* no ->d_hash() rejects on procfs */ dentry = d_hash_and_lookup(mnt->mnt_root, &name); if (dentry) { shrink_dcache_parent(dentry);