summaryrefslogtreecommitdiff
path: root/include/linux
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2016-04-14 19:52:13 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2016-05-02 19:47:51 -0400
commit85c7f81041d57cfe9dc97f4680d5586b54534a39 (patch)
tree16415f1241c9fdc7b279d860d53e60c9c8a9e3fb /include/linux
parent0568d705b0087751f0c085c0a665aa3e954c810d (diff)
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 'include/linux')
-rw-r--r--include/linux/dcache.h18
1 files changed, 18 insertions, 0 deletions
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 4bb4de8d95ea..9a7aa890b642 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -232,6 +232,8 @@ struct dentry_operations {
#define DCACHE_ENCRYPTED_WITH_KEY 0x04000000 /* dir is encrypted with a valid key */
#define DCACHE_OP_REAL 0x08000000
+#define DCACHE_PAR_LOOKUP 0x10000000 /* being looked up (with parent locked shared) */
+
extern seqlock_t rename_lock;
/*
@@ -367,6 +369,22 @@ static inline void dont_mount(struct dentry *dentry)
spin_unlock(&dentry->d_lock);
}
+extern void __d_lookup_done(struct dentry *);
+
+static inline int d_in_lookup(struct dentry *dentry)
+{
+ return dentry->d_flags & DCACHE_PAR_LOOKUP;
+}
+
+static inline void d_lookup_done(struct dentry *dentry)
+{
+ if (unlikely(d_in_lookup(dentry))) {
+ spin_lock(&dentry->d_lock);
+ __d_lookup_done(dentry);
+ spin_unlock(&dentry->d_lock);
+ }
+}
+
extern void dput(struct dentry *);
static inline bool d_managed(const struct dentry *dentry)