refresh 2.6.32 patches with -rc7
[openwrt/svn-archive/archive.git] / target / linux / generic-2.6 / patches-2.6.32 / 235-union_mount_fixes.patch
1 --- a/fs/namespace.c
2 +++ b/fs/namespace.c
3 @@ -1656,8 +1656,10 @@ static int do_move_mount(struct path *pa
4
5 /* moving to or from a union mount is not supported */
6 err = -EINVAL;
7 +#if 0
8 if (IS_MNT_UNION(path->mnt))
9 goto exit;
10 +#endif
11 if (IS_MNT_UNION(old_path.mnt))
12 goto exit;
13
14 --- a/fs/union.c
15 +++ b/fs/union.c
16 @@ -260,8 +260,6 @@ int append_to_union(struct vfsmount *mnt
17 spin_lock(&union_lock);
18 um = union_lookup(dentry, mnt);
19 if (um) {
20 - BUG_ON((um->u_next.dentry != dest_dentry) ||
21 - (um->u_next.mnt != dest_mnt));
22 spin_unlock(&union_lock);
23 union_put(this);
24 return 0;
25 @@ -274,6 +272,23 @@ int append_to_union(struct vfsmount *mnt
26 return 0;
27 }
28
29 +int follow_union_mountpoint(struct path *path)
30 +{
31 + struct path new_path = *path;
32 +
33 + path_get(&new_path);
34 + while (follow_union_down(&new_path)) {
35 + if (new_path.dentry != new_path.mnt->mnt_root)
36 + continue;
37 +
38 + path_put(path);
39 + *path = new_path;
40 + return 1;
41 + }
42 + path_put(&new_path);
43 + return 0;
44 +}
45 +
46 /*
47 * follow_union_down - follow the union stack one layer down
48 *
49 --- a/include/linux/union.h
50 +++ b/include/linux/union.h
51 @@ -47,6 +47,7 @@ extern int append_to_union(struct vfsmou
52 struct vfsmount *, struct dentry *);
53 extern int follow_union_down(struct path *);
54 extern int follow_union_mount(struct path *);
55 +extern int follow_union_mountpoint(struct path *path);
56 extern void __d_drop_unions(struct dentry *);
57 extern void shrink_d_unions(struct dentry *);
58 extern void __shrink_d_unions(struct dentry *, struct list_head *);
59 @@ -68,6 +69,7 @@ extern int union_permission(struct path
60 #define append_to_union(x1, y1, x2, y2) ({ BUG(); (0); })
61 #define follow_union_down(x) ({ (0); })
62 #define follow_union_mount(x) ({ (0); })
63 +#define follow_union_mountpoint(x) ({ (0); })
64 #define __d_drop_unions(x) do { } while (0)
65 #define shrink_d_unions(x) do { } while (0)
66 #define __shrink_d_unions(x,y) do { } while (0)
67 --- a/fs/namei.c
68 +++ b/fs/namei.c
69 @@ -626,6 +626,9 @@ static int cache_lookup_union(struct nam
70 !S_ISDIR(path->dentry->d_inode->i_mode))
71 goto out;
72
73 + if (follow_union_mountpoint(path))
74 + goto out;
75 +
76 /* Build the union stack for this part */
77 res = __cache_lookup_build_union(nd, name, path);
78 if (res) {
79 @@ -892,6 +895,9 @@ static int real_lookup_union(struct name
80 !S_ISDIR(path->dentry->d_inode->i_mode))
81 goto out;
82
83 + if (follow_union_mountpoint(path))
84 + goto out;
85 +
86 /* Build the union stack for this part */
87 res = __real_lookup_build_union(nd, name, path);
88 if (res) {
89 @@ -1813,6 +1819,9 @@ int hash_lookup_union(struct nameidata *
90 !S_ISDIR(path->dentry->d_inode->i_mode))
91 goto out;
92
93 + if (follow_union_mountpoint(path))
94 + goto out;
95 +
96 /* Build the union stack for this part */
97 res = __hash_lookup_build_union(nd, name, path);
98 if (res) {
99 --- a/fs/readdir.c
100 +++ b/fs/readdir.c
101 @@ -17,6 +17,7 @@
102 #include <linux/syscalls.h>
103 #include <linux/unistd.h>
104 #include <linux/union.h>
105 +#include <linux/mount.h>
106
107 #include <asm/uaccess.h>
108
109 @@ -45,7 +46,7 @@ int vfs_readdir(struct file *file, filld
110 * below this one in the union stack.
111 */
112 if (is_unionized(file->f_path.dentry, file->f_path.mnt) &&
113 - !IS_OPAQUE(inode)) {
114 + !IS_OPAQUE(inode) && IS_MNT_UNION(file->f_path.mnt)) {
115 res = union_copyup_dir(&file->f_path);
116 if (res)
117 goto out_unlock;