diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-04 12:05:25 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-04 12:05:25 -0700 |
commit | 2e08edc5c50a01dc52c005fd939c24476eaf55ef (patch) | |
tree | e5d91ecfc9d966dd4cc006cf005732bd569be5c5 /fs/namei.c | |
parent | 17dec0a949153d9ac00760ba2f5b78cb583e995f (diff) | |
parent | 04bbc9795d2e89c79edf48fb1303ace2e8c90a60 (diff) | |
download | linux-2e08edc5c50a01dc52c005fd939c24476eaf55ef.tar.gz linux-2e08edc5c50a01dc52c005fd939c24476eaf55ef.tar.bz2 linux-2e08edc5c50a01dc52c005fd939c24476eaf55ef.zip |
Merge branch 'work.dcache' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs dcache updates from Al Viro:
"Part of this is what the trylock loop elimination series has turned
into, part making d_move() preserve the parent (and thus the path) of
victim, plus some general cleanups"
* 'work.dcache' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (22 commits)
d_genocide: move export to definition
fold dentry_lock_for_move() into its sole caller and clean it up
make non-exchanging __d_move() copy ->d_parent rather than swap them
oprofilefs: don't oops on allocation failure
lustre: get rid of pointless casts to struct dentry *
debugfs_lookup(): switch to lookup_one_len_unlocked()
fold lookup_real() into __lookup_hash()
take out orphan externs (empty_string/slash_string)
split d_path() and friends into a separate file
dcache.c: trim includes
fs/dcache: Avoid a try_lock loop in shrink_dentry_list()
get rid of trylock loop around dentry_kill()
handle move to LRU in retain_dentry()
dput(): consolidate the "do we need to retain it?" into an inlined helper
split the slow part of lock_parent() off
now lock_parent() can't run into killed dentry
get rid of trylock loop in locking dentries on shrink list
d_delete(): get rid of trylock loop
fs/dcache: Move dentry_kill() below lock_parent()
fs/dcache: Remove stale comment from dentry_kill()
...
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 5c2b953c352d..a09419379f5d 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1474,43 +1474,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, |