diff options
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 41 |
1 files changed, 17 insertions, 24 deletions
diff --git a/fs/namei.c b/fs/namei.c index 921ae32dbc80..a3cd028e8a9b 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1473,43 +1473,36 @@ static struct dentry *lookup_dcache(const struct qstr *name, } /* - * Call i_op->lookup on the dentry. The dentry must be negative and - * unhashed. - * - * dir->d_inode->i_mutex must be held + * Parent directory has inode locked exclusive. This is one + * and only case when ->lookup() gets called on non in-lookup + * dentries - as the matter of fact, this only gets called + * when directory is guaranteed to have no in-lookup children + * at all. */ -static struct dentry *lookup_real(struct inode *dir, struct dentry *dentry, - unsigned int flags) -{ - struct dentry *old; - - /* Don't create child dentry for a dead directory. */ - if (unlikely(IS_DEADDIR(dir))) { - dput(dentry); - return ERR_PTR(-ENOENT); - } - - old = dir->i_op->lookup(dir, dentry, flags); - if (unlikely(old)) { - dput(dentry); - dentry = old; - } - return dentry; -} - static struct dentry *__lookup_hash(const struct qstr *name, struct dentry *base, unsigned int flags) { struct dentry *dentry = lookup_dcache(name, base, flags); + struct dentry *old; + struct inode *dir = base->d_inode; if (dentry) return dentry; + /* Don't create child dentry for a dead directory. */ + if (unlikely(IS_DEADDIR(dir))) + return ERR_PTR(-ENOENT); + dentry = d_alloc(base, name); if (unlikely(!dentry)) return ERR_PTR(-ENOMEM); - return lookup_real(base->d_inode, dentry, flags); + old = dir->i_op->lookup(dir, dentry, flags); + if (unlikely(old)) { + dput(dentry); + dentry = old; + } + return dentry; } static int lookup_fast(struct nameidata *nd, |