diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-21 08:50:57 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-21 08:50:57 -0700 |
commit | 31ed8e6f93a27304c9e157dab0267772cd94eaad (patch) | |
tree | 2fd62bea73efa7e2920b0c3e1d81c425eb7bf71c /fs/namei.c | |
parent | 7e5cb5e151c5474b4a468f437f5038ba9f67ef4d (diff) | |
parent | 26fe575028703948880fce4355a210c76bb0536e (diff) |
Merge branch 'dentry-cleanups' (dcache access cleanups and optimizations)
This branch simplifies and clarifies the dcache lookup, and allows us to
do certain nice optimizations when comparing dentries. It also cleans
up the interface to __d_lookup_rcu(), especially around passing the
inode information around.
* dentry-cleanups:
vfs: make it possible to access the dentry hash/len as one 64-bit entry
vfs: move dentry name length comparison from dentry_cmp() into callers
vfs: do the careful dentry name access for all dentry_cmp cases
vfs: remove unnecessary d_unhashed() check from __d_lookup_rcu
vfs: clean up __d_lookup_rcu() and dentry_cmp() interfaces
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/fs/namei.c b/fs/namei.c index 709fb2c17b5..f9e883c1b85 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1144,12 +1144,25 @@ static int do_lookup(struct nameidata *nd, struct qstr *name, */ if (nd->flags & LOOKUP_RCU) { unsigned seq; - *inode = nd->inode; - dentry = __d_lookup_rcu(parent, name, &seq, inode); + dentry = __d_lookup_rcu(parent, name, &seq, nd->inode); if (!dentry) goto unlazy; - /* Memory barrier in read_seqcount_begin of child is enough */ + /* + * This sequence count validates that the inode matches + * the dentry name information from lookup. + */ + *inode = dentry->d_inode; + if (read_seqcount_retry(&dentry->d_seq, seq)) + return -ECHILD; + + /* + * This sequence count validates that the parent had no + * changes while we did the lookup of the dentry above. + * + * The memory barrier in read_seqcount_begin of child is + * enough, we can use __read_seqcount_retry here. + */ if (__read_seqcount_retry(&parent->d_seq, nd->seq)) return -ECHILD; nd->seq = seq; |