aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/dcache.h
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-09-02 14:38:06 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-09-02 14:38:06 -0400
commit15570086b590a69d59183b08a7770e316cca20a7 (patch)
tree12c1494a59a3786bc99674567aa9b77af40a3698 /include/linux/dcache.h
parentdf3d0bbcdb2cafa23a70223d806655bd37e64a9b (diff)
vfs: reimplement d_rcu_to_refcount() using lockref_get_or_lock()
This moves __d_rcu_to_refcount() from <linux/dcache.h> into fs/namei.c and re-implements it using the lockref infrastructure instead. It also adds a lot of comments about what is actually going on, because turning a dentry that was looked up using RCU into a long-lived reference counted entry is one of the more subtle parts of the rcu walk. We also used to be _particularly_ subtle in unlazy_walk() where we re-validate both the dentry and its parent using the same sequence count. We used to do it by nesting the locks and then verifying the sequence count just once. That was silly, because nested locking is expensive, but the sequence count check is not. So this just re-validates the dentry and the parent separately, avoiding the nested locking, and making the lockref lookup possible. Acked-by: Waiman Long <waiman.long@hp.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include/linux/dcache.h')
-rw-r--r--include/linux/dcache.h22
1 files changed, 0 insertions, 22 deletions
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index efdc94434c30..9169b91ea2d2 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -304,28 +304,6 @@ extern struct dentry *__d_lookup(const struct dentry *, const struct qstr *);
304extern struct dentry *__d_lookup_rcu(const struct dentry *parent, 304extern struct dentry *__d_lookup_rcu(const struct dentry *parent,
305 const struct qstr *name, unsigned *seq); 305 const struct qstr *name, unsigned *seq);
306 306
307/**
308 * __d_rcu_to_refcount - take a refcount on dentry if sequence check is ok
309 * @dentry: dentry to take a ref on
310 * @seq: seqcount to verify against
311 * Returns: 0 on failure, else 1.
312 *
313 * __d_rcu_to_refcount operates on a dentry,seq pair that was returned
314 * by __d_lookup_rcu, to get a reference on an rcu-walk dentry.
315 */
316static inline int __d_rcu_to_refcount(struct dentry *dentry, unsigned seq)
317{
318 int ret = 0;
319
320 assert_spin_locked(&dentry->d_lock);
321 if (!read_seqcount_retry(&dentry->d_seq, seq)) {
322 ret = 1;
323 dentry->d_lockref.count++;
324 }
325
326 return ret;
327}
328
329static inline unsigned d_count(const struct dentry *dentry) 307static inline unsigned d_count(const struct dentry *dentry)
330{ 308{
331 return dentry->d_lockref.count; 309 return dentry->d_lockref.count;