Whamcloud - gitweb
LU-4708 ldiskfs: do not copy NUL terminator from direntry
[fs/lustre-release.git] / ldiskfs / kernel_patches / patches / sles11sp2 / ext4-lookup-dotdot.patch
1 ---
2  fs/ext4/namei.c |   42 ++++++++++++++++++++++++++++++++++++++++++
3  1 file changed, 42 insertions(+)
4
5 --- a/fs/ext4/namei.c
6 +++ b/fs/ext4/namei.c
7 @@ -1031,6 +1031,16 @@ errout:
8         return NULL;
9  }
10  
11 +static inline int
12 +is_dot_or_dot_dot(const struct qstr *name)
13 +{
14 +       if (name->name[0] != '.')
15 +               return 0;
16 +       if (name->len == 1 || (name->len == 2 && name->name[1] == '.'))
17 +               return 1;
18 +       return 0;
19 +}
20 +
21  static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
22  {
23         struct inode *inode;
24 @@ -1061,6 +1071,38 @@ static struct dentry *ext4_lookup(struct
25                         }
26                 }
27         }
28 +
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;
35 +
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);
40 +                       goal = tmp;
41 +                       dget(goal);
42 +                       break;
43 +               }
44 +               if (goal == NULL) {
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;
53 +               }
54 +               spin_unlock(&inode->i_lock);
55 +               if (goal)
56 +                       iput(inode);
57 +               return goal;
58 +       }
59 +
60         return d_splice_alias(inode, dentry);
61  }
62