2 fs/ext4/namei.c | 42 ++++++++++++++++++++++++++++++++++++++++++
3 1 file changed, 42 insertions(+)
7 @@ -1031,6 +1031,16 @@ errout:
12 +is_dot_or_dot_dot(const struct qstr *name)
14 + if (name->name[0] != '.')
16 + if (name->len == 1 || (name->len == 2 && name->name[1] == '.'))
21 static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
24 @@ -1061,6 +1071,38 @@ static struct dentry *ext4_lookup(struct
29 + /* ".." shouldn't go into dcache to preserve dcache hierarchy
30 + * otherwise we'll get parent being a child of actual child.
31 + * see bug 10458 for details -bzzz */
32 + if (inode && is_dot_or_dot_dot(&dentry->d_name)) {
33 + struct dentry *tmp, *goal = NULL;
34 + struct list_head *lp;
36 + /* first, look for an existing dentry - any one is good */
37 + spin_lock(&inode->i_lock);
38 + list_for_each(lp, &inode->i_dentry) {
39 + tmp = list_entry(lp, struct dentry, d_alias);
45 + /* there is no alias, we need to make current dentry:
46 + * a) inaccessible for __d_lookup()
47 + * b) inaccessible for iopen */
48 + J_ASSERT(list_empty(&dentry->d_alias));
49 + dentry->d_flags |= DCACHE_NFSFS_RENAMED;
50 + /* this is d_instantiate() ... */
51 + list_add(&dentry->d_alias, &inode->i_dentry);
52 + dentry->d_inode = inode;
54 + spin_unlock(&inode->i_lock);
60 return d_splice_alias(inode, dentry);