diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-16 22:09:57 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-16 22:09:57 -0400 |
commit | 054cfaacf88865bff1dd58d305443d5d6c068a08 (patch) | |
tree | 39cd85f0f5966ed8c501740359b1d03d48f5ea41 /fs | |
parent | dc113c1f1d4b47af1b1ca701c5a39e24d296c2ac (diff) | |
parent | 1a102ff92579edeff5e3d5d3c76ca49977898f00 (diff) |
Merge branch 'mnt_devname' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
* 'mnt_devname' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6:
vfs: bury ->get_sb()
nfs: switch NFS from ->get_sb() to ->mount()
nfs: stop mangling ->mnt_devname on NFS
vfs: new superblock methods to override /proc/*/mount{s,info}
nfs: nfs_do_{ref,sub}mount() superblock argument is redundant
nfs: make nfs_path() work without vfsmount
nfs: store devname at disconnected NFS roots
nfs: propagate devname to nfs{,4}_get_root()
Diffstat (limited to 'fs')
-rw-r--r-- | fs/namespace.c | 39 | ||||
-rw-r--r-- | fs/nfs/dir.c | 13 | ||||
-rw-r--r-- | fs/nfs/getroot.c | 42 | ||||
-rw-r--r-- | fs/nfs/internal.h | 21 | ||||
-rw-r--r-- | fs/nfs/namespace.c | 66 | ||||
-rw-r--r-- | fs/nfs/nfs4namespace.c | 41 | ||||
-rw-r--r-- | fs/nfs/super.c | 194 | ||||
-rw-r--r-- | fs/nfs/unlink.c | 20 | ||||
-rw-r--r-- | fs/super.c | 67 |
9 files changed, 273 insertions, 230 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index e96e03782def..d7513485c1f3 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -978,7 +978,13 @@ static int show_vfsmnt(struct seq_file *m, void *v) | |||
978 | int err = 0; | 978 | int err = 0; |
979 | struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt }; | 979 | struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt }; |
980 | 980 | ||
981 | mangle(m, mnt->mnt_devname ? mnt->mnt_devname : "none"); | 981 | if (mnt->mnt_sb->s_op->show_devname) { |
982 | err = mnt->mnt_sb->s_op->show_devname(m, mnt); | ||
983 | if (err) | ||
984 | goto out; | ||
985 | } else { | ||
986 | mangle(m, mnt->mnt_devname ? mnt->mnt_devname : "none"); | ||
987 | } | ||
982 | seq_putc(m, ' '); | 988 | seq_putc(m, ' '); |
983 | seq_path(m, &mnt_path, " \t\n\\"); | 989 | seq_path(m, &mnt_path, " \t\n\\"); |
984 | seq_putc(m, ' '); | 990 | seq_putc(m, ' '); |
@@ -1025,7 +1031,12 @@ static int show_mountinfo(struct seq_file *m, void *v) | |||
1025 | 1031 | ||
1026 | seq_printf(m, "%i %i %u:%u ", mnt->mnt_id, mnt->mnt_parent->mnt_id, | 1032 | seq_printf(m, "%i %i %u:%u ", mnt->mnt_id, mnt->mnt_parent->mnt_id, |
1027 | MAJOR(sb->s_dev), MINOR(sb->s_dev)); | 1033 | MAJOR(sb->s_dev), MINOR(sb->s_dev)); |
1028 | seq_dentry(m, mnt->mnt_root, " \t\n\\"); | 1034 | if (sb->s_op->show_path) |
1035 | err = sb->s_op->show_path(m, mnt); | ||
1036 | else | ||
1037 | seq_dentry(m, mnt->mnt_root, " \t\n\\"); | ||
1038 | if (err) | ||
1039 | goto out; | ||
1029 | seq_putc(m, ' '); | 1040 | seq_putc(m, ' '); |
1030 | seq_path_root(m, &mnt_path, &root, " \t\n\\"); | 1041 | seq_path_root(m, &mnt_path, &root, " \t\n\\"); |
1031 | if (root.mnt != p->root.mnt || root.dentry != p->root.dentry) { | 1042 | if (root.mnt != p->root.mnt || root.dentry != p->root.dentry) { |
@@ -1060,7 +1071,12 @@ static int show_mountinfo(struct seq_file *m, void *v) | |||
1060 | seq_puts(m, " - "); | 1071 | seq_puts(m, " - "); |
1061 | show_type(m, sb); | 1072 | show_type(m, sb); |
1062 | seq_putc(m, ' '); | 1073 | seq_putc(m, ' '); |
1063 | mangle(m, mnt->mnt_devname ? mnt->mnt_devname : "none"); | 1074 | if (sb->s_op->show_devname) |
1075 | err = sb->s_op->show_devname(m, mnt); | ||
1076 | else | ||
1077 | mangle(m, mnt->mnt_devname ? mnt->mnt_devname : "none"); | ||
1078 | if (err) | ||
1079 | goto out; | ||
1064 | seq_puts(m, sb->s_flags & MS_RDONLY ? " ro" : " rw"); | 1080 | seq_puts(m, sb->s_flags & MS_RDONLY ? " ro" : " rw"); |
1065 | err = show_sb_opts(m, sb); | 1081 | err = show_sb_opts(m, sb); |
1066 | if (err) | 1082 | if (err) |
@@ -1086,11 +1102,15 @@ static int show_vfsstat(struct seq_file *m, void *v) | |||
1086 | int err = 0; | 1102 | int err = 0; |
1087 | 1103 | ||
1088 | /* device */ | 1104 | /* device */ |
1089 | if (mnt->mnt_devname) { | 1105 | if (mnt->mnt_sb->s_op->show_devname) { |
1090 | seq_puts(m, "device "); | 1106 | err = mnt->mnt_sb->s_op->show_devname(m, mnt); |
1091 | mangle(m, mnt->mnt_devname); | 1107 | } else { |
1092 | } else | 1108 | if (mnt->mnt_devname) { |
1093 | seq_puts(m, "no device"); | 1109 | seq_puts(m, "device "); |
1110 | mangle(m, mnt->mnt_devname); | ||
1111 | } else | ||
1112 | seq_puts(m, "no device"); | ||
1113 | } | ||
1094 | 1114 | ||
1095 | /* mount point */ | 1115 | /* mount point */ |
1096 | seq_puts(m, " mounted on "); | 1116 | seq_puts(m, " mounted on "); |
@@ -1104,7 +1124,8 @@ static int show_vfsstat(struct seq_file *m, void *v) | |||
1104 | /* optional statistics */ | 1124 | /* optional statistics */ |
1105 | if (mnt->mnt_sb->s_op->show_stats) { | 1125 | if (mnt->mnt_sb->s_op->show_stats) { |
1106 | seq_putc(m, ' '); | 1126 | seq_putc(m, ' '); |
1107 | err = mnt->mnt_sb->s_op->show_stats(m, mnt); | 1127 | if (!err) |
1128 | err = mnt->mnt_sb->s_op->show_stats(m, mnt); | ||
1108 | } | 1129 | } |
1109 | 1130 | ||
1110 | seq_putc(m, '\n'); | 1131 | seq_putc(m, '\n'); |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 2c3eb33b904d..abdf38d5971d 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -1169,11 +1169,23 @@ static void nfs_dentry_iput(struct dentry *dentry, struct inode *inode) | |||
1169 | iput(inode); | 1169 | iput(inode); |
1170 | } | 1170 | } |
1171 | 1171 | ||
1172 | static void nfs_d_release(struct dentry *dentry) | ||
1173 | { | ||
1174 | /* free cached devname value, if it survived that far */ | ||
1175 | if (unlikely(dentry->d_fsdata)) { | ||
1176 | if (dentry->d_flags & DCACHE_NFSFS_RENAMED) | ||
1177 | WARN_ON(1); | ||
1178 | else | ||
1179 | kfree(dentry->d_fsdata); | ||
1180 | } | ||
1181 | } | ||
1182 | |||
1172 | const struct dentry_operations nfs_dentry_operations = { | 1183 | const struct dentry_operations nfs_dentry_operations = { |
1173 | .d_revalidate = nfs_lookup_revalidate, | 1184 | .d_revalidate = nfs_lookup_revalidate, |
1174 | .d_delete = nfs_dentry_delete, | 1185 | .d_delete = nfs_dentry_delete, |
1175 | .d_iput = nfs_dentry_iput, | 1186 | .d_iput = nfs_dentry_iput, |
1176 | .d_automount = nfs_d_automount, | 1187 | .d_automount = nfs_d_automount, |
1188 | .d_release = nfs_d_release, | ||
1177 | }; | 1189 | }; |
1178 | 1190 | ||
1179 | static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd) | 1191 | static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd) |
@@ -1248,6 +1260,7 @@ const struct dentry_operations nfs4_dentry_operations = { | |||
1248 | .d_delete = nfs_dentry_delete, | 1260 | .d_delete = nfs_dentry_delete, |
1249 | .d_iput = nfs_dentry_iput, | 1261 | .d_iput = nfs_dentry_iput, |
1250 | .d_automount = nfs_d_automount, | 1262 | .d_automount = nfs_d_automount, |
1263 | .d_release = nfs_d_release, | ||
1251 | }; | 1264 | }; |
1252 | 1265 | ||
1253 | /* | 1266 | /* |
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c index b5ffe8fa291f..1084792bc0fe 100644 --- a/fs/nfs/getroot.c +++ b/fs/nfs/getroot.c | |||
@@ -75,18 +75,25 @@ static int nfs_superblock_set_dummy_root(struct super_block *sb, struct inode *i | |||
75 | /* | 75 | /* |
76 | * get an NFS2/NFS3 root dentry from the root filehandle | 76 | * get an NFS2/NFS3 root dentry from the root filehandle |
77 | */ | 77 | */ |
78 | struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh) | 78 | struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh, |
79 | const char *devname) | ||
79 | { | 80 | { |
80 | struct nfs_server *server = NFS_SB(sb); | 81 | struct nfs_server *server = NFS_SB(sb); |
81 | struct nfs_fsinfo fsinfo; | 82 | struct nfs_fsinfo fsinfo; |
82 | struct dentry *ret; | 83 | struct dentry *ret; |
83 | struct inode *inode; | 84 | struct inode *inode; |
85 | void *name = kstrdup(devname, GFP_KERNEL); | ||
84 | int error; | 86 | int error; |
85 | 87 | ||
88 | if (!name) | ||
89 | return ERR_PTR(-ENOMEM); | ||
90 | |||
86 | /* get the actual root for this mount */ | 91 | /* get the actual root for this mount */ |
87 | fsinfo.fattr = nfs_alloc_fattr(); | 92 | fsinfo.fattr = nfs_alloc_fattr(); |
88 | if (fsinfo.fattr == NULL) | 93 | if (fsinfo.fattr == NULL) { |
94 | kfree(name); | ||
89 | return ERR_PTR(-ENOMEM); | 95 | return ERR_PTR(-ENOMEM); |
96 | } | ||
90 | 97 | ||
91 | error = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo); | 98 | error = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo); |
92 | if (error < 0) { | 99 | if (error < 0) { |
@@ -119,7 +126,15 @@ struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh) | |||
119 | } | 126 | } |
120 | 127 | ||
121 | security_d_instantiate(ret, inode); | 128 | security_d_instantiate(ret, inode); |
129 | spin_lock(&ret->d_lock); | ||
130 | if (IS_ROOT(ret) && !(ret->d_flags & DCACHE_NFSFS_RENAMED)) { | ||
131 | ret->d_fsdata = name; | ||
132 | name = NULL; | ||
133 | } | ||
134 | spin_unlock(&ret->d_lock); | ||
122 | out: | 135 | out: |
136 | if (name) | ||
137 | kfree(name); | ||
123 | nfs_free_fattr(fsinfo.fattr); | 138 | nfs_free_fattr(fsinfo.fattr); |
124 | return ret; | 139 | return ret; |
125 | } | 140 | } |
@@ -169,27 +184,35 @@ out: | |||
169 | /* | 184 | /* |
170 | * get an NFS4 root dentry from the root filehandle | 185 | * get an NFS4 root dentry from the root filehandle |
171 | */ | 186 | */ |
172 | struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh) | 187 | struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh, |
188 | const char *devname) | ||
173 | { | 189 | { |
174 | struct nfs_server *server = NFS_SB(sb); | 190 | struct nfs_server *server = NFS_SB(sb); |
175 | struct nfs_fattr *fattr = NULL; | 191 | struct nfs_fattr *fattr = NULL; |
176 | struct dentry *ret; | 192 | struct dentry *ret; |
177 | struct inode *inode; | 193 | struct inode *inode; |
194 | void *name = kstrdup(devname, GFP_KERNEL); | ||
178 | int error; | 195 | int error; |
179 | 196 | ||
180 | dprintk("--> nfs4_get_root()\n"); | 197 | dprintk("--> nfs4_get_root()\n"); |
181 | 198 | ||
199 | if (!name) | ||
200 | return ERR_PTR(-ENOMEM); | ||
201 | |||
182 | /* get the info about the server and filesystem */ | 202 | /* get the info about the server and filesystem */ |
183 | error = nfs4_server_capabilities(server, mntfh); | 203 | error = nfs4_server_capabilities(server, mntfh); |
184 | if (error < 0) { | 204 | if (error < 0) { |
185 | dprintk("nfs_get_root: getcaps error = %d\n", | 205 | dprintk("nfs_get_root: getcaps error = %d\n", |
186 | -error); | 206 | -error); |
207 | kfree(name); | ||
187 | return ERR_PTR(error); | 208 | return ERR_PTR(error); |
188 | } | 209 | } |
189 | 210 | ||
190 | fattr = nfs_alloc_fattr(); | 211 | fattr = nfs_alloc_fattr(); |
191 | if (fattr == NULL) | 212 | if (fattr == NULL) { |
192 | return ERR_PTR(-ENOMEM);; | 213 | kfree(name); |
214 | return ERR_PTR(-ENOMEM); | ||
215 | } | ||
193 | 216 | ||
194 | /* get the actual root for this mount */ | 217 | /* get the actual root for this mount */ |
195 | error = server->nfs_client->rpc_ops->getattr(server, mntfh, fattr); | 218 | error = server->nfs_client->rpc_ops->getattr(server, mntfh, fattr); |
@@ -223,8 +246,15 @@ struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh) | |||
223 | } | 246 | } |
224 | 247 | ||
225 | security_d_instantiate(ret, inode); | 248 | security_d_instantiate(ret, inode); |
226 | 249 | spin_lock(&ret->d_lock); | |
250 | if (IS_ROOT(ret) && !(ret->d_flags & DCACHE_NFSFS_RENAMED)) { | ||
251 | ret->d_fsdata = name; | ||
252 | name = NULL; | ||
253 | } | ||
254 | spin_unlock(&ret->d_lock); | ||
227 | out: | 255 | out: |
256 | if (name) | ||
257 | kfree(name); | ||
228 | nfs_free_fattr(fattr); | 258 | nfs_free_fattr(fattr); |
229 | dprintk("<-- nfs4_get_root()\n"); | 259 | dprintk("<-- nfs4_get_root()\n"); |
230 | return ret; | 260 | return ret; |
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index cf9fdbdabc67..e94ad22da5d2 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
@@ -163,10 +163,10 @@ static inline void nfs_fs_proc_exit(void) | |||
163 | 163 | ||
164 | /* nfs4namespace.c */ | 164 | /* nfs4namespace.c */ |
165 | #ifdef CONFIG_NFS_V4 | 165 | #ifdef CONFIG_NFS_V4 |
166 | extern struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentry *dentry); | 166 | extern struct vfsmount *nfs_do_refmount(struct dentry *dentry); |
167 | #else | 167 | #else |
168 | static inline | 168 | static inline |
169 | struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentry *dentry) | 169 | struct vfsmount *nfs_do_refmount(struct dentry *dentry) |
170 | { | 170 | { |
171 | return ERR_PTR(-ENOENT); | 171 | return ERR_PTR(-ENOENT); |
172 | } | 172 | } |
@@ -247,16 +247,16 @@ extern void nfs_sb_active(struct super_block *sb); | |||
247 | extern void nfs_sb_deactive(struct super_block *sb); | 247 | extern void nfs_sb_deactive(struct super_block *sb); |
248 | 248 | ||
249 | /* namespace.c */ | 249 | /* namespace.c */ |
250 | extern char *nfs_path(const char *base, | 250 | extern char *nfs_path(char **p, struct dentry *dentry, |
251 | const struct dentry *droot, | ||
252 | const struct dentry *dentry, | ||
253 | char *buffer, ssize_t buflen); | 251 | char *buffer, ssize_t buflen); |
254 | extern struct vfsmount *nfs_d_automount(struct path *path); | 252 | extern struct vfsmount *nfs_d_automount(struct path *path); |
255 | 253 | ||
256 | /* getroot.c */ | 254 | /* getroot.c */ |
257 | extern struct dentry *nfs_get_root(struct super_block *, struct nfs_fh *); | 255 | extern struct dentry *nfs_get_root(struct super_block *, struct nfs_fh *, |
256 | const char *); | ||
258 | #ifdef CONFIG_NFS_V4 | 257 | #ifdef CONFIG_NFS_V4 |
259 | extern struct dentry *nfs4_get_root(struct super_block *, struct nfs_fh *); | 258 | extern struct dentry *nfs4_get_root(struct super_block *, struct nfs_fh *, |
259 | const char *); | ||
260 | 260 | ||
261 | extern int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh); | 261 | extern int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh); |
262 | #endif | 262 | #endif |
@@ -288,12 +288,11 @@ extern int _nfs4_call_sync_session(struct nfs_server *server, | |||
288 | /* | 288 | /* |
289 | * Determine the device name as a string | 289 | * Determine the device name as a string |
290 | */ | 290 | */ |
291 | static inline char *nfs_devname(const struct vfsmount *mnt_parent, | 291 | static inline char *nfs_devname(struct dentry *dentry, |
292 | const struct dentry *dentry, | ||
293 | char *buffer, ssize_t buflen) | 292 | char *buffer, ssize_t buflen) |
294 | { | 293 | { |
295 | return nfs_path(mnt_parent->mnt_devname, mnt_parent->mnt_root, | 294 | char *dummy; |
296 | dentry, buffer, buflen); | 295 | return nfs_path(&dummy, dentry, buffer, buflen); |
297 | } | 296 | } |
298 | 297 | ||
299 | /* | 298 | /* |
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index f32b8603dca8..c0b8344db0c6 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c | |||
@@ -25,33 +25,30 @@ static LIST_HEAD(nfs_automount_list); | |||
25 | static DECLARE_DELAYED_WORK(nfs_automount_task, nfs_expire_automounts); | 25 | static DECLARE_DELAYED_WORK(nfs_automount_task, nfs_expire_automounts); |
26 | int nfs_mountpoint_expiry_timeout = 500 * HZ; | 26 | int nfs_mountpoint_expiry_timeout = 500 * HZ; |
27 | 27 | ||
28 | static struct vfsmount *nfs_do_submount(const struct vfsmount *mnt_parent, | 28 | static struct vfsmount *nfs_do_submount(struct dentry *dentry, |
29 | const struct dentry *dentry, | ||
30 | struct nfs_fh *fh, | 29 | struct nfs_fh *fh, |
31 | struct nfs_fattr *fattr); | 30 | struct nfs_fattr *fattr); |
32 | 31 | ||
33 | /* | 32 | /* |
34 | * nfs_path - reconstruct the path given an arbitrary dentry | 33 | * nfs_path - reconstruct the path given an arbitrary dentry |
35 | * @base - arbitrary string to prepend to the path | 34 | * @base - used to return pointer to the end of devname part of path |
36 | * @droot - pointer to root dentry for mountpoint | ||
37 | * @dentry - pointer to dentry | 35 | * @dentry - pointer to dentry |
38 | * @buffer - result buffer | 36 | * @buffer - result buffer |
39 | * @buflen - length of buffer | 37 | * @buflen - length of buffer |
40 | * | 38 | * |
41 | * Helper function for constructing the path from the | 39 | * Helper function for constructing the server pathname |
42 | * root dentry to an arbitrary hashed dentry. | 40 | * by arbitrary hashed dentry. |
43 | * | 41 | * |
44 | * This is mainly for use in figuring out the path on the | 42 | * This is mainly for use in figuring out the path on the |
45 | * server side when automounting on top of an existing partition. | 43 | * server side when automounting on top of an existing partition |
44 | * and in generating /proc/mounts and friends. | ||
46 | */ | 45 | */ |
47 | char *nfs_path(const char *base, | 46 | char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen) |
48 | const struct dentry *droot, | ||
49 | const struct dentry *dentry, | ||
50 | char *buffer, ssize_t buflen) | ||
51 | { | 47 | { |
52 | char *end; | 48 | char *end; |
53 | int namelen; | 49 | int namelen; |
54 | unsigned seq; | 50 | unsigned seq; |
51 | const char *base; | ||
55 | 52 | ||
56 | rename_retry: | 53 | rename_retry: |
57 | end = buffer+buflen; | 54 | end = buffer+buflen; |
@@ -60,7 +57,10 @@ rename_retry: | |||
60 | 57 | ||
61 | seq = read_seqbegin(&rename_lock); | 58 | seq = read_seqbegin(&rename_lock); |
62 | rcu_read_lock(); | 59 | rcu_read_lock(); |
63 | while (!IS_ROOT(dentry) && dentry != droot) { | 60 | while (1) { |
61 | spin_lock(&dentry->d_lock); | ||
62 | if (IS_ROOT(dentry)) | ||
63 | break; | ||
64 | namelen = dentry->d_name.len; | 64 | namelen = dentry->d_name.len; |
65 | buflen -= namelen + 1; | 65 | buflen -= namelen + 1; |
66 | if (buflen < 0) | 66 | if (buflen < 0) |
@@ -68,27 +68,47 @@ rename_retry: | |||
68 | end -= namelen; | 68 | end -= namelen; |
69 | memcpy(end, dentry->d_name.name, namelen); | 69 | memcpy(end, dentry->d_name.name, namelen); |
70 | *--end = '/'; | 70 | *--end = '/'; |
71 | spin_unlock(&dentry->d_lock); | ||
71 | dentry = dentry->d_parent; | 72 | dentry = dentry->d_parent; |
72 | } | 73 | } |
73 | rcu_read_unlock(); | 74 | if (read_seqretry(&rename_lock, seq)) { |
74 | if (read_seqretry(&rename_lock, seq)) | 75 | spin_unlock(&dentry->d_lock); |
76 | rcu_read_unlock(); | ||
75 | goto rename_retry; | 77 | goto rename_retry; |
78 | } | ||
76 | if (*end != '/') { | 79 | if (*end != '/') { |
77 | if (--buflen < 0) | 80 | if (--buflen < 0) { |
81 | spin_unlock(&dentry->d_lock); | ||
82 | rcu_read_unlock(); | ||
78 | goto Elong; | 83 | goto Elong; |
84 | } | ||
79 | *--end = '/'; | 85 | *--end = '/'; |
80 | } | 86 | } |
87 | *p = end; | ||
88 | base = dentry->d_fsdata; | ||
89 | if (!base) { | ||
90 | spin_unlock(&dentry->d_lock); | ||
91 | rcu_read_unlock(); | ||
92 | WARN_ON(1); | ||
93 | return end; | ||
94 | } | ||
81 | namelen = strlen(base); | 95 | namelen = strlen(base); |
82 | /* Strip off excess slashes in base string */ | 96 | /* Strip off excess slashes in base string */ |
83 | while (namelen > 0 && base[namelen - 1] == '/') | 97 | while (namelen > 0 && base[namelen - 1] == '/') |
84 | namelen--; | 98 | namelen--; |
85 | buflen -= namelen; | 99 | buflen -= namelen; |
86 | if (buflen < 0) | 100 | if (buflen < 0) { |
101 | spin_lock(&dentry->d_lock); | ||
102 | rcu_read_unlock(); | ||
87 | goto Elong; | 103 | goto Elong; |
104 | } | ||
88 | end -= namelen; | 105 | end -= namelen; |
89 | memcpy(end, base, namelen); | 106 | memcpy(end, base, namelen); |
107 | spin_unlock(&dentry->d_lock); | ||
108 | rcu_read_unlock(); | ||
90 | return end; | 109 | return end; |
91 | Elong_unlock: | 110 | Elong_unlock: |
111 | spin_lock(&dentry->d_lock); | ||
92 | rcu_read_unlock(); | 112 | rcu_read_unlock(); |
93 | if (read_seqretry(&rename_lock, seq)) | 113 | if (read_seqretry(&rename_lock, seq)) |
94 | goto rename_retry; | 114 | goto rename_retry; |
@@ -143,9 +163,9 @@ struct vfsmount *nfs_d_automount(struct path *path) | |||
143 | } | 163 | } |
144 | 164 | ||
145 | if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) | 165 | if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) |
146 | mnt = nfs_do_refmount(path->mnt, path->dentry); | 166 | mnt = nfs_do_refmount(path->dentry); |
147 | else | 167 | else |
148 | mnt = nfs_do_submount(path->mnt, path->dentry, fh, fattr); | 168 | mnt = nfs_do_submount(path->dentry, fh, fattr); |
149 | if (IS_ERR(mnt)) | 169 | if (IS_ERR(mnt)) |
150 | goto out; | 170 | goto out; |
151 | 171 | ||
@@ -209,19 +229,17 @@ static struct vfsmount *nfs_do_clone_mount(struct nfs_server *server, | |||
209 | 229 | ||
210 | /** | 230 | /** |
211 | * nfs_do_submount - set up mountpoint when crossing a filesystem boundary | 231 | * nfs_do_submount - set up mountpoint when crossing a filesystem boundary |
212 | * @mnt_parent - mountpoint of parent directory | ||
213 | * @dentry - parent directory | 232 | * @dentry - parent directory |
214 | * @fh - filehandle for new root dentry | 233 | * @fh - filehandle for new root dentry |
215 | * @fattr - attributes for new root inode | 234 | * @fattr - attributes for new root inode |
216 | * | 235 | * |
217 | */ | 236 | */ |
218 | static struct vfsmount *nfs_do_submount(const struct vfsmount *mnt_parent, | 237 | static struct vfsmount *nfs_do_submount(struct dentry *dentry, |
219 | const struct dentry *dentry, | ||
220 | struct nfs_fh *fh, | 238 | struct nfs_fh *fh, |
221 | struct nfs_fattr *fattr) | 239 | struct nfs_fattr *fattr) |
222 | { | 240 | { |
223 | struct nfs_clone_mount mountdata = { | 241 | struct nfs_clone_mount mountdata = { |
224 | .sb = mnt_parent->mnt_sb, | 242 | .sb = dentry->d_sb, |
225 | .dentry = dentry, | 243 | .dentry = dentry, |
226 | .fh = fh, | 244 | .fh = fh, |
227 | .fattr = fattr, | 245 | .fattr = fattr, |
@@ -237,11 +255,11 @@ static struct vfsmount *nfs_do_submount(const struct vfsmount *mnt_parent, | |||
237 | dentry->d_name.name); | 255 | dentry->d_name.name); |
238 | if (page == NULL) | 256 | if (page == NULL) |
239 | goto out; | 257 | goto out; |
240 | devname = nfs_devname(mnt_parent, dentry, page, PAGE_SIZE); | 258 | devname = nfs_devname(dentry, page, PAGE_SIZE); |
241 | mnt = (struct vfsmount *)devname; | 259 | mnt = (struct vfsmount *)devname; |
242 | if (IS_ERR(devname)) | 260 | if (IS_ERR(devname)) |
243 | goto free_page; | 261 | goto free_page; |
244 | mnt = nfs_do_clone_mount(NFS_SB(mnt_parent->mnt_sb), devname, &mountdata); | 262 | mnt = nfs_do_clone_mount(NFS_SB(dentry->d_sb), devname, &mountdata); |
245 | free_page: | 263 | free_page: |
246 | free_page((unsigned long)page); | 264 | free_page((unsigned long)page); |
247 | out: | 265 | out: |
diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c index 3c2a1724fbd2..bb80c49b6533 100644 --- a/fs/nfs/nfs4namespace.c +++ b/fs/nfs/nfs4namespace.c | |||
@@ -54,33 +54,29 @@ Elong: | |||
54 | /* | 54 | /* |
55 | * Determine the mount path as a string | 55 | * Determine the mount path as a string |
56 | */ | 56 | */ |
57 | static char *nfs4_path(const struct vfsmount *mnt_parent, | 57 | static char *nfs4_path(struct dentry *dentry, char *buffer, ssize_t buflen) |
58 | const struct dentry *dentry, | ||
59 | char *buffer, ssize_t buflen) | ||
60 | { | 58 | { |
61 | const char *srvpath; | 59 | char *limit; |
62 | 60 | char *path = nfs_path(&limit, dentry, buffer, buflen); | |
63 | srvpath = strchr(mnt_parent->mnt_devname, ':'); | 61 | if (!IS_ERR(path)) { |
64 | if (srvpath) | 62 | char *colon = strchr(path, ':'); |
65 | srvpath++; | 63 | if (colon && colon < limit) |
66 | else | 64 | path = colon + 1; |
67 | srvpath = mnt_parent->mnt_devname; | 65 | } |
68 | 66 | return path; | |
69 | return nfs_path(srvpath, mnt_parent->mnt_root, dentry, buffer, buflen); | ||
70 | } | 67 | } |
71 | 68 | ||
72 | /* | 69 | /* |
73 | * Check that fs_locations::fs_root [RFC3530 6.3] is a prefix for what we | 70 | * Check that fs_locations::fs_root [RFC3530 6.3] is a prefix for what we |
74 | * believe to be the server path to this dentry | 71 | * believe to be the server path to this dentry |
75 | */ | 72 | */ |
76 | static int nfs4_validate_fspath(const struct vfsmount *mnt_parent, | 73 | static int nfs4_validate_fspath(struct dentry *dentry, |
77 | const struct dentry *dentry, | ||
78 | const struct nfs4_fs_locations *locations, | 74 | const struct nfs4_fs_locations *locations, |
79 | char *page, char *page2) | 75 | char *page, char *page2) |
80 | { | 76 | { |
81 | const char *path, *fs_path; | 77 | const char *path, *fs_path; |
82 | 78 | ||
83 | path = nfs4_path(mnt_parent, dentry, page, PAGE_SIZE); | 79 | path = nfs4_path(dentry, page, PAGE_SIZE); |
84 | if (IS_ERR(path)) | 80 | if (IS_ERR(path)) |
85 | return PTR_ERR(path); | 81 | return PTR_ERR(path); |
86 | 82 | ||
@@ -165,20 +161,18 @@ static struct vfsmount *try_location(struct nfs_clone_mount *mountdata, | |||
165 | 161 | ||
166 | /** | 162 | /** |
167 | * nfs_follow_referral - set up mountpoint when hitting a referral on moved error | 163 | * nfs_follow_referral - set up mountpoint when hitting a referral on moved error |
168 | * @mnt_parent - mountpoint of parent directory | ||
169 | * @dentry - parent directory | 164 | * @dentry - parent directory |
170 | * @locations - array of NFSv4 server location information | 165 | * @locations - array of NFSv4 server location information |
171 | * | 166 | * |
172 | */ | 167 | */ |
173 | static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent, | 168 | static struct vfsmount *nfs_follow_referral(struct dentry *dentry, |
174 | const struct dentry *dentry, | ||
175 | const struct nfs4_fs_locations *locations) | 169 | const struct nfs4_fs_locations *locations) |
176 | { | 170 | { |
177 | struct vfsmount *mnt = ERR_PTR(-ENOENT); | 171 | struct vfsmount *mnt = ERR_PTR(-ENOENT); |
178 | struct nfs_clone_mount mountdata = { | 172 | struct nfs_clone_mount mountdata = { |
179 | .sb = mnt_parent->mnt_sb, | 173 | .sb = dentry->d_sb, |
180 | .dentry = dentry, | 174 | .dentry = dentry, |
181 | .authflavor = NFS_SB(mnt_parent->mnt_sb)->client->cl_auth->au_flavor, | 175 | .authflavor = NFS_SB(dentry->d_sb)->client->cl_auth->au_flavor, |
182 | }; | 176 | }; |
183 | char *page = NULL, *page2 = NULL; | 177 | char *page = NULL, *page2 = NULL; |
184 | int loc, error; | 178 | int loc, error; |
@@ -198,7 +192,7 @@ static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent, | |||
198 | goto out; | 192 | goto out; |
199 | 193 | ||
200 | /* Ensure fs path is a prefix of current dentry path */ | 194 | /* Ensure fs path is a prefix of current dentry path */ |
201 | error = nfs4_validate_fspath(mnt_parent, dentry, locations, page, page2); | 195 | error = nfs4_validate_fspath(dentry, locations, page, page2); |
202 | if (error < 0) { | 196 | if (error < 0) { |
203 | mnt = ERR_PTR(error); | 197 | mnt = ERR_PTR(error); |
204 | goto out; | 198 | goto out; |
@@ -225,11 +219,10 @@ out: | |||
225 | 219 | ||
226 | /* | 220 | /* |
227 | * nfs_do_refmount - handle crossing a referral on server | 221 | * nfs_do_refmount - handle crossing a referral on server |
228 | * @mnt_parent - mountpoint of referral | ||
229 | * @dentry - dentry of referral | 222 | * @dentry - dentry of referral |
230 | * | 223 | * |
231 | */ | 224 | */ |
232 | struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentry *dentry) | 225 | struct vfsmount *nfs_do_refmount(struct dentry *dentry) |
233 | { | 226 | { |
234 | struct vfsmount *mnt = ERR_PTR(-ENOMEM); | 227 | struct vfsmount *mnt = ERR_PTR(-ENOMEM); |
235 | struct dentry *parent; | 228 | struct dentry *parent; |
@@ -262,7 +255,7 @@ struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentr | |||
262 | fs_locations->fs_path.ncomponents <= 0) | 255 | fs_locations->fs_path.ncomponents <= 0) |
263 | goto out_free; | 256 | goto out_free; |
264 | 257 | ||
265 | mnt = nfs_follow_referral(mnt_parent, dentry, fs_locations); | 258 | mnt = nfs_follow_referral(dentry, fs_locations); |
266 | out_free: | 259 | out_free: |
267 | __free_page(page); | 260 | __free_page(page); |
268 | kfree(fs_locations); | 261 | kfree(fs_locations); |
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index b68c8607770f..d3286583009a 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -263,8 +263,11 @@ static match_table_t nfs_local_lock_tokens = { | |||
263 | static void nfs_umount_begin(struct super_block *); | 263 | static void nfs_umount_begin(struct super_block *); |
264 | static int nfs_statfs(struct dentry *, struct kstatfs *); | 264 | static int nfs_statfs(struct dentry *, struct kstatfs *); |
265 | static int nfs_show_options(struct seq_file *, struct vfsmount *); | 265 | static int nfs_show_options(struct seq_file *, struct vfsmount *); |
266 | static int nfs_show_devname(struct seq_file *, struct vfsmount *); | ||
267 | static int nfs_show_path(struct seq_file *, struct vfsmount *); | ||
266 | static int nfs_show_stats(struct seq_file *, struct vfsmount *); | 268 | static int nfs_show_stats(struct seq_file *, struct vfsmount *); |
267 | static int nfs_get_sb(struct file_system_type *, int, const char *, void *, struct vfsmount *); | 269 | static struct dentry *nfs_fs_mount(struct file_system_type *, |
270 | int, const char *, void *); | ||
268 | static struct dentry *nfs_xdev_mount(struct file_system_type *fs_type, | 271 | static struct dentry *nfs_xdev_mount(struct file_system_type *fs_type, |
269 | int flags, const char *dev_name, void *raw_data); | 272 | int flags, const char *dev_name, void *raw_data); |
270 | static void nfs_put_super(struct super_block *); | 273 | static void nfs_put_super(struct super_block *); |
@@ -274,7 +277,7 @@ static int nfs_remount(struct super_block *sb, int *flags, char *raw_data); | |||
274 | static struct file_system_type nfs_fs_type = { | 277 | static struct file_system_type nfs_fs_type = { |
275 | .owner = THIS_MODULE, | 278 | .owner = THIS_MODULE, |
276 | .name = "nfs", | 279 | .name = "nfs", |
277 | .get_sb = nfs_get_sb, | 280 | .mount = nfs_fs_mount, |
278 | .kill_sb = nfs_kill_super, | 281 | .kill_sb = nfs_kill_super, |
279 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, | 282 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, |
280 | }; | 283 | }; |
@@ -296,6 +299,8 @@ static const struct super_operations nfs_sops = { | |||
296 | .evict_inode = nfs_evict_inode, | 299 | .evict_inode = nfs_evict_inode, |
297 | .umount_begin = nfs_umount_begin, | 300 | .umount_begin = nfs_umount_begin, |
298 | .show_options = nfs_show_options, | 301 | .show_options = nfs_show_options, |
302 | .show_devname = nfs_show_devname, | ||
303 | .show_path = nfs_show_path, | ||
299 | .show_stats = nfs_show_stats, | 304 | .show_stats = nfs_show_stats, |
300 | .remount_fs = nfs_remount, | 305 | .remount_fs = nfs_remount, |
301 | }; | 306 | }; |
@@ -303,16 +308,16 @@ static const struct super_operations nfs_sops = { | |||
303 | #ifdef CONFIG_NFS_V4 | 308 | #ifdef CONFIG_NFS_V4 |
304 | static int nfs4_validate_text_mount_data(void *options, | 309 | static int nfs4_validate_text_mount_data(void *options, |
305 | struct nfs_parsed_mount_data *args, const char *dev_name); | 310 | struct nfs_parsed_mount_data *args, const char *dev_name); |
306 | static int nfs4_try_mount(int flags, const char *dev_name, | 311 | static struct dentry *nfs4_try_mount(int flags, const char *dev_name, |
307 | struct nfs_parsed_mount_data *data, struct vfsmount *mnt); | 312 | struct nfs_parsed_mount_data *data); |
308 | static int nfs4_get_sb(struct file_system_type *fs_type, | 313 | static struct dentry *nfs4_mount(struct file_system_type *fs_type, |
309 | int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); | 314 | int flags, const char *dev_name, void *raw_data); |
310 | static struct dentry *nfs4_remote_mount(struct file_system_type *fs_type, | 315 | static struct dentry *nfs4_remote_mount(struct file_system_type *fs_type, |
311 | int flags, const char *dev_name, void *raw_data); | 316 | int flags, const char *dev_name, void *raw_data); |
312 | static struct dentry *nfs4_xdev_mount(struct file_system_type *fs_type, | 317 | static struct dentry *nfs4_xdev_mount(struct file_system_type *fs_type, |
313 | int flags, const char *dev_name, void *raw_data); | 318 | int flags, const char *dev_name, void *raw_data); |
314 | static int nfs4_referral_get_sb(struct file_system_type *fs_type, | 319 | static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type, |
315 | int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); | 320 | int flags, const char *dev_name, void *raw_data); |
316 | static struct dentry *nfs4_remote_referral_mount(struct file_system_type *fs_type, | 321 | static struct dentry *nfs4_remote_referral_mount(struct file_system_type *fs_type, |
317 | int flags, const char *dev_name, void *raw_data); | 322 | int flags, const char *dev_name, void *raw_data); |
318 | static void nfs4_kill_super(struct super_block *sb); | 323 | static void nfs4_kill_super(struct super_block *sb); |
@@ -320,7 +325,7 @@ static void nfs4_kill_super(struct super_block *sb); | |||
320 | static struct file_system_type nfs4_fs_type = { | 325 | static struct file_system_type nfs4_fs_type = { |
321 | .owner = THIS_MODULE, | 326 | .owner = THIS_MODULE, |
322 | .name = "nfs4", | 327 | .name = "nfs4", |
323 | .get_sb = nfs4_get_sb, | 328 | .mount = nfs4_mount, |
324 | .kill_sb = nfs4_kill_super, | 329 | .kill_sb = nfs4_kill_super, |
325 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, | 330 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, |
326 | }; | 331 | }; |
@@ -352,7 +357,7 @@ static struct file_system_type nfs4_remote_referral_fs_type = { | |||
352 | struct file_system_type nfs4_referral_fs_type = { | 357 | struct file_system_type nfs4_referral_fs_type = { |
353 | .owner = THIS_MODULE, | 358 | .owner = THIS_MODULE, |
354 | .name = "nfs4", | 359 | .name = "nfs4", |
355 | .get_sb = nfs4_referral_get_sb, | 360 | .mount = nfs4_referral_mount, |
356 | .kill_sb = nfs4_kill_super, | 361 | .kill_sb = nfs4_kill_super, |
357 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, | 362 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, |
358 | }; | 363 | }; |
@@ -366,6 +371,8 @@ static const struct super_operations nfs4_sops = { | |||
366 | .evict_inode = nfs4_evict_inode, | 371 | .evict_inode = nfs4_evict_inode, |
367 | .umount_begin = nfs_umount_begin, | 372 | .umount_begin = nfs_umount_begin, |
368 | .show_options = nfs_show_options, | 373 | .show_options = nfs_show_options, |
374 | .show_devname = nfs_show_devname, | ||
375 | .show_path = nfs_show_path, | ||
369 | .show_stats = nfs_show_stats, | 376 | .show_stats = nfs_show_stats, |
370 | .remount_fs = nfs_remount, | 377 | .remount_fs = nfs_remount, |
371 | }; | 378 | }; |
@@ -726,6 +733,28 @@ static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt) | |||
726 | return 0; | 733 | return 0; |
727 | } | 734 | } |
728 | 735 | ||
736 | static int nfs_show_devname(struct seq_file *m, struct vfsmount *mnt) | ||
737 | { | ||
738 | char *page = (char *) __get_free_page(GFP_KERNEL); | ||
739 | char *devname, *dummy; | ||
740 | int err = 0; | ||
741 | if (!page) | ||
742 | return -ENOMEM; | ||
743 | devname = nfs_path(&dummy, mnt->mnt_root, page, PAGE_SIZE); | ||
744 | if (IS_ERR(devname)) | ||
745 | err = PTR_ERR(devname); | ||
746 | else | ||
747 | seq_escape(m, devname, " \t\n\\"); | ||
748 | free_page((unsigned long)page); | ||
749 | return err; | ||
750 | } | ||
751 | |||
752 | static int nfs_show_path(struct seq_file *m, struct vfsmount *mnt) | ||
753 | { | ||
754 | seq_puts(m, "/"); | ||
755 | return 0; | ||
756 | } | ||
757 | |||
729 | /* | 758 | /* |
730 | * Present statistical information for this VFS mountpoint | 759 | * Present statistical information for this VFS mountpoint |
731 | */ | 760 | */ |
@@ -2267,19 +2296,19 @@ static int nfs_bdi_register(struct nfs_server *server) | |||
2267 | return bdi_register_dev(&server->backing_dev_info, server->s_dev); | 2296 | return bdi_register_dev(&server->backing_dev_info, server->s_dev); |
2268 | } | 2297 | } |
2269 | 2298 | ||
2270 | static int nfs_get_sb(struct file_system_type *fs_type, | 2299 | static struct dentry *nfs_fs_mount(struct file_system_type *fs_type, |
2271 | int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) | 2300 | int flags, const char *dev_name, void *raw_data) |
2272 | { | 2301 | { |
2273 | struct nfs_server *server = NULL; | 2302 | struct nfs_server *server = NULL; |
2274 | struct super_block *s; | 2303 | struct super_block *s; |
2275 | struct nfs_parsed_mount_data *data; | 2304 | struct nfs_parsed_mount_data *data; |
2276 | struct nfs_fh *mntfh; | 2305 | struct nfs_fh *mntfh; |
2277 | struct dentry *mntroot; | 2306 | struct dentry *mntroot = ERR_PTR(-ENOMEM); |
2278 | int (*compare_super)(struct super_block *, void *) = nfs_compare_super; | 2307 | int (*compare_super)(struct super_block *, void *) = nfs_compare_super; |
2279 | struct nfs_sb_mountdata sb_mntdata = { | 2308 | struct nfs_sb_mountdata sb_mntdata = { |
2280 | .mntflags = flags, | 2309 | .mntflags = flags, |
2281 | }; | 2310 | }; |
2282 | int error = -ENOMEM; | 2311 | int error; |
2283 | 2312 | ||
2284 | data = nfs_alloc_parsed_mount_data(NFS_DEFAULT_VERSION); | 2313 | data = nfs_alloc_parsed_mount_data(NFS_DEFAULT_VERSION); |
2285 | mntfh = nfs_alloc_fhandle(); | 2314 | mntfh = nfs_alloc_fhandle(); |
@@ -2290,12 +2319,14 @@ static int nfs_get_sb(struct file_system_type *fs_type, | |||
2290 | 2319 | ||
2291 | /* Validate the mount data */ | 2320 | /* Validate the mount data */ |
2292 | error = nfs_validate_mount_data(raw_data, data, mntfh, dev_name); | 2321 | error = nfs_validate_mount_data(raw_data, data, mntfh, dev_name); |
2293 | if (error < 0) | 2322 | if (error < 0) { |
2323 | mntroot = ERR_PTR(error); | ||
2294 | goto out; | 2324 | goto out; |
2325 | } | ||
2295 | 2326 | ||
2296 | #ifdef CONFIG_NFS_V4 | 2327 | #ifdef CONFIG_NFS_V4 |
2297 | if (data->version == 4) { | 2328 | if (data->version == 4) { |
2298 | error = nfs4_try_mount(flags, dev_name, data, mnt); | 2329 | mntroot = nfs4_try_mount(flags, dev_name, data); |
2299 | kfree(data->client_address); | 2330 | kfree(data->client_address); |
2300 | kfree(data->nfs_server.export_path); | 2331 | kfree(data->nfs_server.export_path); |
2301 | goto out; | 2332 | goto out; |
@@ -2305,7 +2336,7 @@ static int nfs_get_sb(struct file_system_type *fs_type, | |||
2305 | /* Get a volume representation */ | 2336 | /* Get a volume representation */ |
2306 | server = nfs_create_server(data, mntfh); | 2337 | server = nfs_create_server(data, mntfh); |
2307 | if (IS_ERR(server)) { | 2338 | if (IS_ERR(server)) { |
2308 | error = PTR_ERR(server); | 2339 | mntroot = ERR_CAST(server); |
2309 | goto out; | 2340 | goto out; |
2310 | } | 2341 | } |
2311 | sb_mntdata.server = server; | 2342 | sb_mntdata.server = server; |
@@ -2316,7 +2347,7 @@ static int nfs_get_sb(struct file_system_type *fs_type, | |||
2316 | /* Get a superblock - note that we may end up sharing one that already exists */ | 2347 | /* Get a superblock - note that we may end up sharing one that already exists */ |
2317 | s = sget(fs_type, compare_super, nfs_set_super, &sb_mntdata); | 2348 | s = sget(fs_type, compare_super, nfs_set_super, &sb_mntdata); |
2318 | if (IS_ERR(s)) { | 2349 | if (IS_ERR(s)) { |
2319 | error = PTR_ERR(s); | 2350 | mntroot = ERR_CAST(s); |
2320 | goto out_err_nosb; | 2351 | goto out_err_nosb; |
2321 | } | 2352 | } |
2322 | 2353 | ||
@@ -2325,8 +2356,10 @@ static int nfs_get_sb(struct file_system_type *fs_type, | |||
2325 | server = NULL; | 2356 | server = NULL; |
2326 | } else { | 2357 | } else { |
2327 | error = nfs_bdi_register(server); | 2358 | error = nfs_bdi_register(server); |
2328 | if (error) | 2359 | if (error) { |
2360 | mntroot = ERR_PTR(error); | ||
2329 | goto error_splat_bdi; | 2361 | goto error_splat_bdi; |
2362 | } | ||
2330 | } | 2363 | } |
2331 | 2364 | ||
2332 | if (!s->s_root) { | 2365 | if (!s->s_root) { |
@@ -2336,20 +2369,15 @@ static int nfs_get_sb(struct file_system_type *fs_type, | |||
2336 | s, data ? data->fscache_uniq : NULL, NULL); | 2369 | s, data ? data->fscache_uniq : NULL, NULL); |
2337 | } | 2370 | } |
2338 | 2371 | ||
2339 | mntroot = nfs_get_root(s, mntfh); | 2372 | mntroot = nfs_get_root(s, mntfh, dev_name); |
2340 | if (IS_ERR(mntroot)) { | 2373 | if (IS_ERR(mntroot)) |
2341 | error = PTR_ERR(mntroot); | ||
2342 | goto error_splat_super; | 2374 | goto error_splat_super; |
2343 | } | ||
2344 | 2375 | ||
2345 | error = security_sb_set_mnt_opts(s, &data->lsm_opts); | 2376 | error = security_sb_set_mnt_opts(s, &data->lsm_opts); |
2346 | if (error) | 2377 | if (error) |
2347 | goto error_splat_root; | 2378 | goto error_splat_root; |
2348 | 2379 | ||
2349 | s->s_flags |= MS_ACTIVE; | 2380 | s->s_flags |= MS_ACTIVE; |
2350 | mnt->mnt_sb = s; | ||
2351 | mnt->mnt_root = mntroot; | ||
2352 | error = 0; | ||
2353 | 2381 | ||
2354 | out: | 2382 | out: |
2355 | kfree(data->nfs_server.hostname); | 2383 | kfree(data->nfs_server.hostname); |
@@ -2359,7 +2387,7 @@ out: | |||
2359 | out_free_fh: | 2387 | out_free_fh: |
2360 | nfs_free_fhandle(mntfh); | 2388 | nfs_free_fhandle(mntfh); |
2361 | kfree(data); | 2389 | kfree(data); |
2362 | return error; | 2390 | return mntroot; |
2363 | 2391 | ||
2364 | out_err_nosb: | 2392 | out_err_nosb: |
2365 | nfs_free_server(server); | 2393 | nfs_free_server(server); |
@@ -2367,6 +2395,7 @@ out_err_nosb: | |||
2367 | 2395 | ||
2368 | error_splat_root: | 2396 | error_splat_root: |
2369 | dput(mntroot); | 2397 | dput(mntroot); |
2398 | mntroot = ERR_PTR(error); | ||
2370 | error_splat_super: | 2399 | error_splat_super: |
2371 | if (server && !s->s_root) | 2400 | if (server && !s->s_root) |
2372 | bdi_unregister(&server->backing_dev_info); | 2401 | bdi_unregister(&server->backing_dev_info); |
@@ -2450,7 +2479,7 @@ nfs_xdev_mount(struct file_system_type *fs_type, int flags, | |||
2450 | nfs_fscache_get_super_cookie(s, NULL, data); | 2479 | nfs_fscache_get_super_cookie(s, NULL, data); |
2451 | } | 2480 | } |
2452 | 2481 | ||
2453 | mntroot = nfs_get_root(s, data->fh); | 2482 | mntroot = nfs_get_root(s, data->fh, dev_name); |
2454 | if (IS_ERR(mntroot)) { | 2483 | if (IS_ERR(mntroot)) { |
2455 | error = PTR_ERR(mntroot); | 2484 | error = PTR_ERR(mntroot); |
2456 | goto error_splat_super; | 2485 | goto error_splat_super; |
@@ -2718,7 +2747,7 @@ nfs4_remote_mount(struct file_system_type *fs_type, int flags, | |||
2718 | s, data ? data->fscache_uniq : NULL, NULL); | 2747 | s, data ? data->fscache_uniq : NULL, NULL); |
2719 | } | 2748 | } |
2720 | 2749 | ||
2721 | mntroot = nfs4_get_root(s, mntfh); | 2750 | mntroot = nfs4_get_root(s, mntfh, dev_name); |
2722 | if (IS_ERR(mntroot)) { | 2751 | if (IS_ERR(mntroot)) { |
2723 | error = PTR_ERR(mntroot); | 2752 | error = PTR_ERR(mntroot); |
2724 | goto error_splat_super; | 2753 | goto error_splat_super; |
@@ -2771,27 +2800,6 @@ static struct vfsmount *nfs_do_root_mount(struct file_system_type *fs_type, | |||
2771 | return root_mnt; | 2800 | return root_mnt; |
2772 | } | 2801 | } |
2773 | 2802 | ||
2774 | static void nfs_fix_devname(const struct path *path, struct vfsmount *mnt) | ||
2775 | { | ||
2776 | char *page = (char *) __get_free_page(GFP_KERNEL); | ||
2777 | char *devname, *tmp; | ||
2778 | |||
2779 | if (page == NULL) | ||
2780 | return; | ||
2781 | devname = nfs_path(path->mnt->mnt_devname, | ||
2782 | path->mnt->mnt_root, path->dentry, | ||
2783 | page, PAGE_SIZE); | ||
2784 | if (IS_ERR(devname)) | ||
2785 | goto out_freepage; | ||
2786 | tmp = kstrdup(devname, GFP_KERNEL); | ||
2787 | if (tmp == NULL) | ||
2788 | goto out_freepage; | ||
2789 | kfree(mnt->mnt_devname); | ||
2790 | mnt->mnt_devname = tmp; | ||
2791 | out_freepage: | ||
2792 | free_page((unsigned long)page); | ||
2793 | } | ||
2794 | |||
2795 | struct nfs_referral_count { | 2803 | struct nfs_referral_count { |
2796 | struct list_head list; | 2804 | struct list_head list; |
2797 | const struct task_struct *task; | 2805 | const struct task_struct *task; |
@@ -2858,17 +2866,18 @@ static void nfs_referral_loop_unprotect(void) | |||
2858 | kfree(p); | 2866 | kfree(p); |
2859 | } | 2867 | } |
2860 | 2868 | ||
2861 | static int nfs_follow_remote_path(struct vfsmount *root_mnt, | 2869 | static struct dentry *nfs_follow_remote_path(struct vfsmount *root_mnt, |
2862 | const char *export_path, struct vfsmount *mnt_target) | 2870 | const char *export_path) |
2863 | { | 2871 | { |
2864 | struct nameidata *nd = NULL; | 2872 | struct nameidata *nd = NULL; |
2865 | struct mnt_namespace *ns_private; | 2873 | struct mnt_namespace *ns_private; |
2866 | struct super_block *s; | 2874 | struct super_block *s; |
2875 | struct dentry *dentry; | ||
2867 | int ret; | 2876 | int ret; |
2868 | 2877 | ||
2869 | nd = kmalloc(sizeof(*nd), GFP_KERNEL); | 2878 | nd = kmalloc(sizeof(*nd), GFP_KERNEL); |
2870 | if (nd == NULL) | 2879 | if (nd == NULL) |
2871 | return -ENOMEM; | 2880 | return ERR_PTR(-ENOMEM); |
2872 | 2881 | ||
2873 | ns_private = create_mnt_ns(root_mnt); | 2882 | ns_private = create_mnt_ns(root_mnt); |
2874 | ret = PTR_ERR(ns_private); | 2883 | ret = PTR_ERR(ns_private); |
@@ -2890,32 +2899,27 @@ static int nfs_follow_remote_path(struct vfsmount *root_mnt, | |||
2890 | 2899 | ||
2891 | s = nd->path.mnt->mnt_sb; | 2900 | s = nd->path.mnt->mnt_sb; |
2892 | atomic_inc(&s->s_active); | 2901 | atomic_inc(&s->s_active); |
2893 | mnt_target->mnt_sb = s; | 2902 | dentry = dget(nd->path.dentry); |
2894 | mnt_target->mnt_root = dget(nd->path.dentry); | ||
2895 | |||
2896 | /* Correct the device pathname */ | ||
2897 | nfs_fix_devname(&nd->path, mnt_target); | ||
2898 | 2903 | ||
2899 | path_put(&nd->path); | 2904 | path_put(&nd->path); |
2900 | kfree(nd); | 2905 | kfree(nd); |
2901 | down_write(&s->s_umount); | 2906 | down_write(&s->s_umount); |
2902 | return 0; | 2907 | return dentry; |
2903 | out_put_mnt_ns: | 2908 | out_put_mnt_ns: |
2904 | put_mnt_ns(ns_private); | 2909 | put_mnt_ns(ns_private); |
2905 | out_mntput: | 2910 | out_mntput: |
2906 | mntput(root_mnt); | 2911 | mntput(root_mnt); |
2907 | out_err: | 2912 | out_err: |
2908 | kfree(nd); | 2913 | kfree(nd); |
2909 | return ret; | 2914 | return ERR_PTR(ret); |
2910 | } | 2915 | } |
2911 | 2916 | ||
2912 | static int nfs4_try_mount(int flags, const char *dev_name, | 2917 | static struct dentry *nfs4_try_mount(int flags, const char *dev_name, |
2913 | struct nfs_parsed_mount_data *data, | 2918 | struct nfs_parsed_mount_data *data) |
2914 | struct vfsmount *mnt) | ||
2915 | { | 2919 | { |
2916 | char *export_path; | 2920 | char *export_path; |
2917 | struct vfsmount *root_mnt; | 2921 | struct vfsmount *root_mnt; |
2918 | int error; | 2922 | struct dentry *res; |
2919 | 2923 | ||
2920 | dfprintk(MOUNT, "--> nfs4_try_mount()\n"); | 2924 | dfprintk(MOUNT, "--> nfs4_try_mount()\n"); |
2921 | 2925 | ||
@@ -2925,26 +2929,25 @@ static int nfs4_try_mount(int flags, const char *dev_name, | |||
2925 | data->nfs_server.hostname); | 2929 | data->nfs_server.hostname); |
2926 | data->nfs_server.export_path = export_path; | 2930 | data->nfs_server.export_path = export_path; |
2927 | 2931 | ||
2928 | error = PTR_ERR(root_mnt); | 2932 | res = ERR_CAST(root_mnt); |
2929 | if (IS_ERR(root_mnt)) | 2933 | if (!IS_ERR(root_mnt)) |
2930 | goto out; | 2934 | res = nfs_follow_remote_path(root_mnt, export_path); |
2931 | 2935 | ||
2932 | error = nfs_follow_remote_path(root_mnt, export_path, mnt); | 2936 | dfprintk(MOUNT, "<-- nfs4_try_mount() = %ld%s\n", |
2933 | 2937 | IS_ERR(res) ? PTR_ERR(res) : 0, | |
2934 | out: | 2938 | IS_ERR(res) ? " [error]" : ""); |
2935 | dfprintk(MOUNT, "<-- nfs4_try_mount() = %d%s\n", error, | 2939 | return res; |
2936 | error != 0 ? " [error]" : ""); | ||
2937 | return error; | ||
2938 | } | 2940 | } |
2939 | 2941 | ||
2940 | /* | 2942 | /* |
2941 | * Get the superblock for an NFS4 mountpoint | 2943 | * Get the superblock for an NFS4 mountpoint |
2942 | */ | 2944 | */ |
2943 | static int nfs4_get_sb(struct file_system_type *fs_type, | 2945 | static struct dentry *nfs4_mount(struct file_system_type *fs_type, |
2944 | int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) | 2946 | int flags, const char *dev_name, void *raw_data) |
2945 | { | 2947 | { |
2946 | struct nfs_parsed_mount_data *data; | 2948 | struct nfs_parsed_mount_data *data; |
2947 | int error = -ENOMEM; | 2949 | int error = -ENOMEM; |
2950 | struct dentry *res = ERR_PTR(-ENOMEM); | ||
2948 | 2951 | ||
2949 | data = nfs_alloc_parsed_mount_data(4); | 2952 | data = nfs_alloc_parsed_mount_data(4); |
2950 | if (data == NULL) | 2953 | if (data == NULL) |
@@ -2952,10 +2955,14 @@ static int nfs4_get_sb(struct file_system_type *fs_type, | |||
2952 | 2955 | ||
2953 | /* Validate the mount data */ | 2956 | /* Validate the mount data */ |
2954 | error = nfs4_validate_mount_data(raw_data, data, dev_name); | 2957 | error = nfs4_validate_mount_data(raw_data, data, dev_name); |
2955 | if (error < 0) | 2958 | if (error < 0) { |
2959 | res = ERR_PTR(error); | ||
2956 | goto out; | 2960 | goto out; |
2961 | } | ||
2957 | 2962 | ||
2958 | error = nfs4_try_mount(flags, dev_name, data, mnt); | 2963 | res = nfs4_try_mount(flags, dev_name, data); |
2964 | if (IS_ERR(res)) | ||
2965 | error = PTR_ERR(res); | ||
2959 | 2966 | ||
2960 | out: | 2967 | out: |
2961 | kfree(data->client_address); | 2968 | kfree(data->client_address); |
@@ -2964,9 +2971,9 @@ out: | |||
2964 | kfree(data->fscache_uniq); | 2971 | kfree(data->fscache_uniq); |
2965 | out_free_data: | 2972 | out_free_data: |
2966 | kfree(data); | 2973 | kfree(data); |
2967 | dprintk("<-- nfs4_get_sb() = %d%s\n", error, | 2974 | dprintk("<-- nfs4_mount() = %d%s\n", error, |
2968 | error != 0 ? " [error]" : ""); | 2975 | error != 0 ? " [error]" : ""); |
2969 | return error; | 2976 | return res; |
2970 | } | 2977 | } |
2971 | 2978 | ||
2972 | static void nfs4_kill_super(struct super_block *sb) | 2979 | static void nfs4_kill_super(struct super_block *sb) |
@@ -3033,7 +3040,7 @@ nfs4_xdev_mount(struct file_system_type *fs_type, int flags, | |||
3033 | nfs_fscache_get_super_cookie(s, NULL, data); | 3040 | nfs_fscache_get_super_cookie(s, NULL, data); |
3034 | } | 3041 | } |
3035 | 3042 | ||
3036 | mntroot = nfs4_get_root(s, data->fh); | 3043 | mntroot = nfs4_get_root(s, data->fh, dev_name); |
3037 | if (IS_ERR(mntroot)) { | 3044 | if (IS_ERR(mntroot)) { |
3038 | error = PTR_ERR(mntroot); | 3045 | error = PTR_ERR(mntroot); |
3039 | goto error_splat_super; | 3046 | goto error_splat_super; |
@@ -3120,7 +3127,7 @@ nfs4_remote_referral_mount(struct file_system_type *fs_type, int flags, | |||
3120 | nfs_fscache_get_super_cookie(s, NULL, data); | 3127 | nfs_fscache_get_super_cookie(s, NULL, data); |
3121 | } | 3128 | } |
3122 | 3129 | ||
3123 | mntroot = nfs4_get_root(s, mntfh); | 3130 | mntroot = nfs4_get_root(s, mntfh, dev_name); |
3124 | if (IS_ERR(mntroot)) { | 3131 | if (IS_ERR(mntroot)) { |
3125 | error = PTR_ERR(mntroot); | 3132 | error = PTR_ERR(mntroot); |
3126 | goto error_splat_super; | 3133 | goto error_splat_super; |
@@ -3160,16 +3167,15 @@ error_splat_bdi: | |||
3160 | /* | 3167 | /* |
3161 | * Create an NFS4 server record on referral traversal | 3168 | * Create an NFS4 server record on referral traversal |
3162 | */ | 3169 | */ |
3163 | static int nfs4_referral_get_sb(struct file_system_type *fs_type, | 3170 | static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type, |
3164 | int flags, const char *dev_name, void *raw_data, | 3171 | int flags, const char *dev_name, void *raw_data) |
3165 | struct vfsmount *mnt) | ||
3166 | { | 3172 | { |
3167 | struct nfs_clone_mount *data = raw_data; | 3173 | struct nfs_clone_mount *data = raw_data; |
3168 | char *export_path; | 3174 | char *export_path; |
3169 | struct vfsmount *root_mnt; | 3175 | struct vfsmount *root_mnt; |
3170 | int error; | 3176 | struct dentry *res; |
3171 | 3177 | ||
3172 | dprintk("--> nfs4_referral_get_sb()\n"); | 3178 | dprintk("--> nfs4_referral_mount()\n"); |
3173 | 3179 | ||
3174 | export_path = data->mnt_path; | 3180 | export_path = data->mnt_path; |
3175 | data->mnt_path = "/"; | 3181 | data->mnt_path = "/"; |
@@ -3178,15 +3184,13 @@ static int nfs4_referral_get_sb(struct file_system_type *fs_type, | |||
3178 | flags, data, data->hostname); | 3184 | flags, data, data->hostname); |
3179 | data->mnt_path = export_path; | 3185 | data->mnt_path = export_path; |
3180 | 3186 | ||
3181 | error = PTR_ERR(root_mnt); | 3187 | res = ERR_CAST(root_mnt); |
3182 | if (IS_ERR(root_mnt)) | 3188 | if (!IS_ERR(root_mnt)) |
3183 | goto out; | 3189 | res = nfs_follow_remote_path(root_mnt, export_path); |
3184 | 3190 | dprintk("<-- nfs4_referral_mount() = %ld%s\n", | |
3185 | error = nfs_follow_remote_path(root_mnt, export_path, mnt); | 3191 | IS_ERR(res) ? PTR_ERR(res) : 0, |
3186 | out: | 3192 | IS_ERR(res) ? " [error]" : ""); |
3187 | dprintk("<-- nfs4_referral_get_sb() = %d%s\n", error, | 3193 | return res; |
3188 | error != 0 ? " [error]" : ""); | ||
3189 | return error; | ||
3190 | } | 3194 | } |
3191 | 3195 | ||
3192 | #endif /* CONFIG_NFS_V4 */ | 3196 | #endif /* CONFIG_NFS_V4 */ |
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c index 6481d537d69d..8d6864c2a5fa 100644 --- a/fs/nfs/unlink.c +++ b/fs/nfs/unlink.c | |||
@@ -148,6 +148,7 @@ static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct n | |||
148 | alias = d_lookup(parent, &data->args.name); | 148 | alias = d_lookup(parent, &data->args.name); |
149 | if (alias != NULL) { | 149 | if (alias != NULL) { |
150 | int ret = 0; | 150 | int ret = 0; |
151 | void *devname_garbage = NULL; | ||
151 | 152 | ||
152 | /* | 153 | /* |
153 | * Hey, we raced with lookup... See if we need to transfer | 154 | * Hey, we raced with lookup... See if we need to transfer |
@@ -157,6 +158,7 @@ static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct n | |||
157 | spin_lock(&alias->d_lock); | 158 | spin_lock(&alias->d_lock); |
158 | if (alias->d_inode != NULL && | 159 | if (alias->d_inode != NULL && |
159 | !(alias->d_flags & DCACHE_NFSFS_RENAMED)) { | 160 | !(alias->d_flags & DCACHE_NFSFS_RENAMED)) { |
161 | devname_garbage = alias->d_fsdata; | ||
160 | alias->d_fsdata = data; | 162 | alias->d_fsdata = data; |
161 | alias->d_flags |= DCACHE_NFSFS_RENAMED; | 163 | alias->d_flags |= DCACHE_NFSFS_RENAMED; |
162 | ret = 1; | 164 | ret = 1; |
@@ -164,6 +166,13 @@ static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct n | |||
164 | spin_unlock(&alias->d_lock); | 166 | spin_unlock(&alias->d_lock); |
165 | nfs_dec_sillycount(dir); | 167 | nfs_dec_sillycount(dir); |
166 | dput(alias); | 168 | dput(alias); |
169 | /* | ||
170 | * If we'd displaced old cached devname, free it. At that | ||
171 | * point dentry is definitely not a root, so we won't need | ||
172 | * that anymore. | ||
173 | */ | ||
174 | if (devname_garbage) | ||
175 | kfree(devname_garbage); | ||
167 | return ret; | 176 | return ret; |
168 | } | 177 | } |
169 | data->dir = igrab(dir); | 178 | data->dir = igrab(dir); |
@@ -252,6 +261,7 @@ nfs_async_unlink(struct inode *dir, struct dentry *dentry) | |||
252 | { | 261 | { |
253 | struct nfs_unlinkdata *data; | 262 | struct nfs_unlinkdata *data; |
254 | int status = -ENOMEM; | 263 | int status = -ENOMEM; |
264 | void *devname_garbage = NULL; | ||
255 | 265 | ||
256 | data = kzalloc(sizeof(*data), GFP_KERNEL); | 266 | data = kzalloc(sizeof(*data), GFP_KERNEL); |
257 | if (data == NULL) | 267 | if (data == NULL) |
@@ -269,8 +279,16 @@ nfs_async_unlink(struct inode *dir, struct dentry *dentry) | |||
269 | if (dentry->d_flags & DCACHE_NFSFS_RENAMED) | 279 | if (dentry->d_flags & DCACHE_NFSFS_RENAMED) |
270 | goto out_unlock; | 280 | goto out_unlock; |
271 | dentry->d_flags |= DCACHE_NFSFS_RENAMED; | 281 | dentry->d_flags |= DCACHE_NFSFS_RENAMED; |
282 | devname_garbage = dentry->d_fsdata; | ||
272 | dentry->d_fsdata = data; | 283 | dentry->d_fsdata = data; |
273 | spin_unlock(&dentry->d_lock); | 284 | spin_unlock(&dentry->d_lock); |
285 | /* | ||
286 | * If we'd displaced old cached devname, free it. At that | ||
287 | * point dentry is definitely not a root, so we won't need | ||
288 | * that anymore. | ||
289 | */ | ||
290 | if (devname_garbage) | ||
291 | kfree(devname_garbage); | ||
274 | return 0; | 292 | return 0; |
275 | out_unlock: | 293 | out_unlock: |
276 | spin_unlock(&dentry->d_lock); | 294 | spin_unlock(&dentry->d_lock); |
@@ -299,6 +317,7 @@ nfs_complete_unlink(struct dentry *dentry, struct inode *inode) | |||
299 | if (dentry->d_flags & DCACHE_NFSFS_RENAMED) { | 317 | if (dentry->d_flags & DCACHE_NFSFS_RENAMED) { |
300 | dentry->d_flags &= ~DCACHE_NFSFS_RENAMED; | 318 | dentry->d_flags &= ~DCACHE_NFSFS_RENAMED; |
301 | data = dentry->d_fsdata; | 319 | data = dentry->d_fsdata; |
320 | dentry->d_fsdata = NULL; | ||
302 | } | 321 | } |
303 | spin_unlock(&dentry->d_lock); | 322 | spin_unlock(&dentry->d_lock); |
304 | 323 | ||
@@ -315,6 +334,7 @@ nfs_cancel_async_unlink(struct dentry *dentry) | |||
315 | struct nfs_unlinkdata *data = dentry->d_fsdata; | 334 | struct nfs_unlinkdata *data = dentry->d_fsdata; |
316 | 335 | ||
317 | dentry->d_flags &= ~DCACHE_NFSFS_RENAMED; | 336 | dentry->d_flags &= ~DCACHE_NFSFS_RENAMED; |
337 | dentry->d_fsdata = NULL; | ||
318 | spin_unlock(&dentry->d_lock); | 338 | spin_unlock(&dentry->d_lock); |
319 | nfs_free_unlinkdata(data); | 339 | nfs_free_unlinkdata(data); |
320 | return; | 340 | return; |
diff --git a/fs/super.c b/fs/super.c index 7e9dd4cc2c01..4bae0ef6110e 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -843,23 +843,6 @@ error: | |||
843 | } | 843 | } |
844 | EXPORT_SYMBOL(mount_bdev); | 844 | EXPORT_SYMBOL(mount_bdev); |
845 | 845 | ||
846 | int get_sb_bdev(struct file_system_type *fs_type, | ||
847 | int flags, const char *dev_name, void *data, | ||
848 | int (*fill_super)(struct super_block *, void *, int), | ||
849 | struct vfsmount *mnt) | ||
850 | { | ||
851 | struct dentry *root; | ||
852 | |||
853 | root = mount_bdev(fs_type, flags, dev_name, data, fill_super); | ||
854 | if (IS_ERR(root)) | ||
855 | return PTR_ERR(root); | ||
856 | mnt->mnt_root = root; | ||
857 | mnt->mnt_sb = root->d_sb; | ||
858 | return 0; | ||
859 | } | ||
860 | |||
861 | EXPORT_SYMBOL(get_sb_bdev); | ||
862 | |||
863 | void kill_block_super(struct super_block *sb) | 846 | void kill_block_super(struct super_block *sb) |
864 | { | 847 | { |
865 | struct block_device *bdev = sb->s_bdev; | 848 | struct block_device *bdev = sb->s_bdev; |
@@ -897,22 +880,6 @@ struct dentry *mount_nodev(struct file_system_type *fs_type, | |||
897 | } | 880 | } |
898 | EXPORT_SYMBOL(mount_nodev); | 881 | EXPORT_SYMBOL(mount_nodev); |
899 | 882 | ||
900 | int get_sb_nodev(struct file_system_type *fs_type, | ||
901 | int flags, void *data, | ||
902 | int (*fill_super)(struct super_block *, void *, int), | ||
903 | struct vfsmount *mnt) | ||
904 | { | ||
905 | struct dentry *root; | ||
906 | |||
907 | root = mount_nodev(fs_type, flags, data, fill_super); | ||
908 | if (IS_ERR(root)) | ||
909 | return PTR_ERR(root); | ||
910 | mnt->mnt_root = root; | ||
911 | mnt->mnt_sb = root->d_sb; | ||
912 | return 0; | ||
913 | } | ||
914 | EXPORT_SYMBOL(get_sb_nodev); | ||
915 | |||
916 | static int compare_single(struct super_block *s, void *p) | 883 | static int compare_single(struct super_block *s, void *p) |
917 | { | 884 | { |
918 | return 1; | 885 | return 1; |
@@ -943,22 +910,6 @@ struct dentry *mount_single(struct file_system_type *fs_type, | |||
943 | } | 910 | } |
944 | EXPORT_SYMBOL(mount_single); | 911 | EXPORT_SYMBOL(mount_single); |
945 | 912 | ||
946 | int get_sb_single(struct file_system_type *fs_type, | ||
947 | int flags, void *data, | ||
948 | int (*fill_super)(struct super_block *, void *, int), | ||
949 | struct vfsmount *mnt) | ||
950 | { | ||
951 | struct dentry *root; | ||
952 | root = mount_single(fs_type, flags, data, fill_super); | ||
953 | if (IS_ERR(root)) | ||
954 | return PTR_ERR(root); | ||
955 | mnt->mnt_root = root; | ||
956 | mnt->mnt_sb = root->d_sb; | ||
957 | return 0; | ||
958 | } | ||
959 | |||
960 | EXPORT_SYMBOL(get_sb_single); | ||
961 | |||
962 | struct vfsmount * | 913 | struct vfsmount * |
963 | vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data) | 914 | vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data) |
964 | { | 915 | { |
@@ -988,19 +939,13 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void | |||
988 | goto out_free_secdata; | 939 | goto out_free_secdata; |
989 | } | 940 | } |
990 | 941 | ||
991 | if (type->mount) { | 942 | root = type->mount(type, flags, name, data); |
992 | root = type->mount(type, flags, name, data); | 943 | if (IS_ERR(root)) { |
993 | if (IS_ERR(root)) { | 944 | error = PTR_ERR(root); |
994 | error = PTR_ERR(root); | 945 | goto out_free_secdata; |
995 | goto out_free_secdata; | ||
996 | } | ||
997 | mnt->mnt_root = root; | ||
998 | mnt->mnt_sb = root->d_sb; | ||
999 | } else { | ||
1000 | error = type->get_sb(type, flags, name, data, mnt); | ||
1001 | if (error < 0) | ||
1002 | goto out_free_secdata; | ||
1003 | } | 946 | } |
947 | mnt->mnt_root = root; | ||
948 | mnt->mnt_sb = root->d_sb; | ||
1004 | BUG_ON(!mnt->mnt_sb); | 949 | BUG_ON(!mnt->mnt_sb); |
1005 | WARN_ON(!mnt->mnt_sb->s_bdi); | 950 | WARN_ON(!mnt->mnt_sb->s_bdi); |
1006 | mnt->mnt_sb->s_flags |= MS_BORN; | 951 | mnt->mnt_sb->s_flags |= MS_BORN; |