summaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2016-04-15 01:52:13 +0200
committerAl Viro <viro@zeniv.linux.org.uk>2016-05-03 01:47:51 +0200
commit85c7f81041d57cfe9dc97f4680d5586b54534a39 (patch)
tree16415f1241c9fdc7b279d860d53e60c9c8a9e3fb /fs/namei.c
parent__d_add(): don't drop/regain ->d_lock (diff)
downloadlinux-85c7f81041d57cfe9dc97f4680d5586b54534a39.tar.xz
linux-85c7f81041d57cfe9dc97f4680d5586b54534a39.zip
beginning of transition to parallel lookups - marking in-lookup dentries
marked as such when (would be) parallel lookup is about to pass them to actual ->lookup(); unmarked when * __d_add() is about to make it hashed, positive or not. * __d_move() (from d_splice_alias(), directly or via __d_unalias()) puts a preexisting dentry in its place * in caller of ->lookup() if it has escaped all of the above. Bug (WARN_ON, actually) if it reaches the final dput() or d_instantiate() while still marked such. As the result, we are guaranteed that for as long as the flag is set, dentry will * remain negative unhashed with positive refcount * never have its ->d_alias looked at * never have its ->d_lru looked at * never have its ->d_parent and ->d_name changed Right now we have at most one such for any given parent directory. With parallel lookups that restriction will weaken to * only exist when parent is locked shared * at most one with given (parent,name) pair (comparison of names is according to ->d_compare()) * only exist when there's no hashed dentry with the same (parent,name) Transition will take the next several commits; unfortunately, we'll only be able to switch to rwsem at the end of this series. The reason for not making it a single patch is to simplify review. New primitives: d_in_lookup() (a predicate checking if dentry is in the in-lookup state) and d_lookup_done() (tells the system that we are done with lookup and if it's still marked as in-lookup, it should cease to be such). Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/fs/namei.c b/fs/namei.c
index c275635c4b9e..26e5f84e0c36 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1634,7 +1634,11 @@ static struct dentry *lookup_slow(const struct qstr *name,
inode_unlock(inode);
return ERR_PTR(-ENOMEM);
}
+ spin_lock(&dentry->d_lock);
+ dentry->d_flags |= DCACHE_PAR_LOOKUP;
+ spin_unlock(&dentry->d_lock);
old = inode->i_op->lookup(inode, dentry, flags);
+ d_lookup_done(dentry);
if (unlikely(old)) {
dput(dentry);
dentry = old;