aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-03-16 22:09:57 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-03-16 22:09:57 -0400
commit054cfaacf88865bff1dd58d305443d5d6c068a08 (patch)
tree39cd85f0f5966ed8c501740359b1d03d48f5ea41
parentdc113c1f1d4b47af1b1ca701c5a39e24d296c2ac (diff)
parent1a102ff92579edeff5e3d5d3c76ca49977898f00 (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()
-rw-r--r--Documentation/filesystems/Locking6
-rw-r--r--Documentation/filesystems/porting7
-rw-r--r--Documentation/filesystems/vfs.txt56
-rw-r--r--fs/namespace.c39
-rw-r--r--fs/nfs/dir.c13
-rw-r--r--fs/nfs/getroot.c42
-rw-r--r--fs/nfs/internal.h21
-rw-r--r--fs/nfs/namespace.c66
-rw-r--r--fs/nfs/nfs4namespace.c41
-rw-r--r--fs/nfs/super.c194
-rw-r--r--fs/nfs/unlink.c20
-rw-r--r--fs/super.c67
-rw-r--r--include/linux/fs.h16
13 files changed, 316 insertions, 272 deletions
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
index 4471a416c27..2e994efe12c 100644
--- a/Documentation/filesystems/Locking
+++ b/Documentation/filesystems/Locking
@@ -166,13 +166,11 @@ prototypes:
166 void (*kill_sb) (struct super_block *); 166 void (*kill_sb) (struct super_block *);
167locking rules: 167locking rules:
168 may block 168 may block
169get_sb yes
170mount yes 169mount yes
171kill_sb yes 170kill_sb yes
172 171
173->get_sb() returns error or 0 with locked superblock attached to the vfsmount 172->mount() returns ERR_PTR or the root dentry; its superblock should be locked
174(exclusive on ->s_umount). 173on return.
175->mount() returns ERR_PTR or the root dentry.
176->kill_sb() takes a write-locked superblock, does all shutdown work on it, 174->kill_sb() takes a write-locked superblock, does all shutdown work on it,
177unlocks and drops the reference. 175unlocks and drops the reference.
178 176
diff --git a/Documentation/filesystems/porting b/Documentation/filesystems/porting
index dfbcd1b00b0..0c986c9e851 100644
--- a/Documentation/filesystems/porting
+++ b/Documentation/filesystems/porting
@@ -394,3 +394,10 @@ file) you must return -EOPNOTSUPP if FALLOC_FL_PUNCH_HOLE is set in mode.
394Currently you can only have FALLOC_FL_PUNCH_HOLE with FALLOC_FL_KEEP_SIZE set, 394Currently you can only have FALLOC_FL_PUNCH_HOLE with FALLOC_FL_KEEP_SIZE set,
395so the i_size should not change when hole punching, even when puching the end of 395so the i_size should not change when hole punching, even when puching the end of
396a file off. 396a file off.
397
398--
399[mandatory]
400 ->get_sb() is gone. Switch to use of ->mount(). Typically it's just
401a matter of switching from calling get_sb_... to mount_... and changing the
402function type. If you were doing it manually, just switch from setting ->mnt_root
403to some pointer to returning that pointer. On errors return ERR_PTR(...).
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index 94cf97b901d..ef0714aa8e4 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -95,10 +95,11 @@ functions:
95 extern int unregister_filesystem(struct file_system_type *); 95 extern int unregister_filesystem(struct file_system_type *);
96 96
97The passed struct file_system_type describes your filesystem. When a 97The passed struct file_system_type describes your filesystem. When a
98request is made to mount a device onto a directory in your filespace, 98request is made to mount a filesystem onto a directory in your namespace,
99the VFS will call the appropriate get_sb() method for the specific 99the VFS will call the appropriate mount() method for the specific
100filesystem. The dentry for the mount point will then be updated to 100filesystem. New vfsmount refering to the tree returned by ->mount()
101point to the root inode for the new filesystem. 101will be attached to the mountpoint, so that when pathname resolution
102reaches the mountpoint it will jump into the root of that vfsmount.
102 103
103You can see all filesystems that are registered to the kernel in the 104You can see all filesystems that are registered to the kernel in the
104file /proc/filesystems. 105file /proc/filesystems.
@@ -107,14 +108,14 @@ file /proc/filesystems.
107struct file_system_type 108struct file_system_type
108----------------------- 109-----------------------
109 110
110This describes the filesystem. As of kernel 2.6.22, the following 111This describes the filesystem. As of kernel 2.6.39, the following
111members are defined: 112members are defined:
112 113
113struct file_system_type { 114struct file_system_type {
114 const char *name; 115 const char *name;
115 int fs_flags; 116 int fs_flags;
116 int (*get_sb) (struct file_system_type *, int, 117 struct dentry (*mount) (struct file_system_type *, int,
117 const char *, void *, struct vfsmount *); 118 const char *, void *);
118 void (*kill_sb) (struct super_block *); 119 void (*kill_sb) (struct super_block *);
119 struct module *owner; 120 struct module *owner;
120 struct file_system_type * next; 121 struct file_system_type * next;
@@ -128,11 +129,11 @@ struct file_system_type {
128 129
129 fs_flags: various flags (i.e. FS_REQUIRES_DEV, FS_NO_DCACHE, etc.) 130 fs_flags: various flags (i.e. FS_REQUIRES_DEV, FS_NO_DCACHE, etc.)
130 131
131 get_sb: the method to call when a new instance of this 132 mount: the method to call when a new instance of this
132 filesystem should be mounted 133 filesystem should be mounted
133 134
134 kill_sb: the method to call when an instance of this filesystem 135 kill_sb: the method to call when an instance of this filesystem
135 should be unmounted 136 should be shut down
136 137
137 owner: for internal VFS use: you should initialize this to THIS_MODULE in 138 owner: for internal VFS use: you should initialize this to THIS_MODULE in
138 most cases. 139 most cases.
@@ -141,7 +142,7 @@ struct file_system_type {
141 142
142 s_lock_key, s_umount_key: lockdep-specific 143 s_lock_key, s_umount_key: lockdep-specific
143 144
144The get_sb() method has the following arguments: 145The mount() method has the following arguments:
145 146
146 struct file_system_type *fs_type: describes the filesystem, partly initialized 147 struct file_system_type *fs_type: describes the filesystem, partly initialized
147 by the specific filesystem code 148 by the specific filesystem code
@@ -153,32 +154,39 @@ The get_sb() method has the following arguments:
153 void *data: arbitrary mount options, usually comes as an ASCII 154 void *data: arbitrary mount options, usually comes as an ASCII
154 string (see "Mount Options" section) 155 string (see "Mount Options" section)
155 156
156 struct vfsmount *mnt: a vfs-internal representation of a mount point 157The mount() method must return the root dentry of the tree requested by
158caller. An active reference to its superblock must be grabbed and the
159superblock must be locked. On failure it should return ERR_PTR(error).
157 160
158The get_sb() method must determine if the block device specified 161The arguments match those of mount(2) and their interpretation
159in the dev_name and fs_type contains a filesystem of the type the method 162depends on filesystem type. E.g. for block filesystems, dev_name is
160supports. If it succeeds in opening the named block device, it initializes a 163interpreted as block device name, that device is opened and if it
161struct super_block descriptor for the filesystem contained by the block device. 164contains a suitable filesystem image the method creates and initializes
162On failure it returns an error. 165struct super_block accordingly, returning its root dentry to caller.
166
167->mount() may choose to return a subtree of existing filesystem - it
168doesn't have to create a new one. The main result from the caller's
169point of view is a reference to dentry at the root of (sub)tree to
170be attached; creation of new superblock is a common side effect.
163 171
164The most interesting member of the superblock structure that the 172The most interesting member of the superblock structure that the
165get_sb() method fills in is the "s_op" field. This is a pointer to 173mount() method fills in is the "s_op" field. This is a pointer to
166a "struct super_operations" which describes the next level of the 174a "struct super_operations" which describes the next level of the
167filesystem implementation. 175filesystem implementation.
168 176
169Usually, a filesystem uses one of the generic get_sb() implementations 177Usually, a filesystem uses one of the generic mount() implementations
170and provides a fill_super() method instead. The generic methods are: 178and provides a fill_super() callback instead. The generic variants are:
171 179
172 get_sb_bdev: mount a filesystem residing on a block device 180 mount_bdev: mount a filesystem residing on a block device
173 181
174 get_sb_nodev: mount a filesystem that is not backed by a device 182 mount_nodev: mount a filesystem that is not backed by a device
175 183
176 get_sb_single: mount a filesystem which shares the instance between 184 mount_single: mount a filesystem which shares the instance between
177 all mounts 185 all mounts
178 186
179A fill_super() method implementation has the following arguments: 187A fill_super() callback implementation has the following arguments:
180 188
181 struct super_block *sb: the superblock structure. The method fill_super() 189 struct super_block *sb: the superblock structure. The callback
182 must initialize this properly. 190 must initialize this properly.
183 191
184 void *data: arbitrary mount options, usually comes as an ASCII 192 void *data: arbitrary mount options, usually comes as an ASCII
diff --git a/fs/namespace.c b/fs/namespace.c
index e96e03782de..d7513485c1f 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 2c3eb33b904..abdf38d5971 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
1172static 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
1172const struct dentry_operations nfs_dentry_operations = { 1183const 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
1179static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd) 1191static 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 b5ffe8fa291..1084792bc0f 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 */
78struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh) 78struct 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);
122out: 135out:
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 */
172struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh) 187struct 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);
227out: 255out:
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 cf9fdbdabc6..e94ad22da5d 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
166extern struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentry *dentry); 166extern struct vfsmount *nfs_do_refmount(struct dentry *dentry);
167#else 167#else
168static inline 168static inline
169struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentry *dentry) 169struct 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);
247extern void nfs_sb_deactive(struct super_block *sb); 247extern void nfs_sb_deactive(struct super_block *sb);
248 248
249/* namespace.c */ 249/* namespace.c */
250extern char *nfs_path(const char *base, 250extern 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);
254extern struct vfsmount *nfs_d_automount(struct path *path); 252extern struct vfsmount *nfs_d_automount(struct path *path);
255 253
256/* getroot.c */ 254/* getroot.c */
257extern struct dentry *nfs_get_root(struct super_block *, struct nfs_fh *); 255extern struct dentry *nfs_get_root(struct super_block *, struct nfs_fh *,
256 const char *);
258#ifdef CONFIG_NFS_V4 257#ifdef CONFIG_NFS_V4
259extern struct dentry *nfs4_get_root(struct super_block *, struct nfs_fh *); 258extern struct dentry *nfs4_get_root(struct super_block *, struct nfs_fh *,
259 const char *);
260 260
261extern int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh); 261extern 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 */
291static inline char *nfs_devname(const struct vfsmount *mnt_parent, 291static 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 f32b8603dca..c0b8344db0c 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -25,33 +25,30 @@ static LIST_HEAD(nfs_automount_list);
25static DECLARE_DELAYED_WORK(nfs_automount_task, nfs_expire_automounts); 25static DECLARE_DELAYED_WORK(nfs_automount_task, nfs_expire_automounts);
26int nfs_mountpoint_expiry_timeout = 500 * HZ; 26int nfs_mountpoint_expiry_timeout = 500 * HZ;
27 27
28static struct vfsmount *nfs_do_submount(const struct vfsmount *mnt_parent, 28static 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 */
47char *nfs_path(const char *base, 46char *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
56rename_retry: 53rename_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;
91Elong_unlock: 110Elong_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 */
218static struct vfsmount *nfs_do_submount(const struct vfsmount *mnt_parent, 237static 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);
245free_page: 263free_page:
246 free_page((unsigned long)page); 264 free_page((unsigned long)page);
247out: 265out:
diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c
index 3c2a1724fbd..bb80c49b653 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 */
57static char *nfs4_path(const struct vfsmount *mnt_parent, 57static 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 */
76static int nfs4_validate_fspath(const struct vfsmount *mnt_parent, 73static 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 */
173static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent, 168static 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 */
232struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentry *dentry) 225struct 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);
266out_free: 259out_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 b68c8607770..d3286583009 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -263,8 +263,11 @@ static match_table_t nfs_local_lock_tokens = {
263static void nfs_umount_begin(struct super_block *); 263static void nfs_umount_begin(struct super_block *);
264static int nfs_statfs(struct dentry *, struct kstatfs *); 264static int nfs_statfs(struct dentry *, struct kstatfs *);
265static int nfs_show_options(struct seq_file *, struct vfsmount *); 265static int nfs_show_options(struct seq_file *, struct vfsmount *);
266static int nfs_show_devname(struct seq_file *, struct vfsmount *);
267static int nfs_show_path(struct seq_file *, struct vfsmount *);
266static int nfs_show_stats(struct seq_file *, struct vfsmount *); 268static int nfs_show_stats(struct seq_file *, struct vfsmount *);
267static int nfs_get_sb(struct file_system_type *, int, const char *, void *, struct vfsmount *); 269static struct dentry *nfs_fs_mount(struct file_system_type *,
270 int, const char *, void *);
268static struct dentry *nfs_xdev_mount(struct file_system_type *fs_type, 271static 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);
270static void nfs_put_super(struct super_block *); 273static void nfs_put_super(struct super_block *);
@@ -274,7 +277,7 @@ static int nfs_remount(struct super_block *sb, int *flags, char *raw_data);
274static struct file_system_type nfs_fs_type = { 277static 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
304static int nfs4_validate_text_mount_data(void *options, 309static 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);
306static int nfs4_try_mount(int flags, const char *dev_name, 311static 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);
308static int nfs4_get_sb(struct file_system_type *fs_type, 313static 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);
310static struct dentry *nfs4_remote_mount(struct file_system_type *fs_type, 315static 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);
312static struct dentry *nfs4_xdev_mount(struct file_system_type *fs_type, 317static 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);
314static int nfs4_referral_get_sb(struct file_system_type *fs_type, 319static 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);
316static struct dentry *nfs4_remote_referral_mount(struct file_system_type *fs_type, 321static 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);
318static void nfs4_kill_super(struct super_block *sb); 323static void nfs4_kill_super(struct super_block *sb);
@@ -320,7 +325,7 @@ static void nfs4_kill_super(struct super_block *sb);
320static struct file_system_type nfs4_fs_type = { 325static 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 = {
352struct file_system_type nfs4_referral_fs_type = { 357struct 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
736static 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
752static 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
2270static int nfs_get_sb(struct file_system_type *fs_type, 2299static 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
2354out: 2382out:
2355 kfree(data->nfs_server.hostname); 2383 kfree(data->nfs_server.hostname);
@@ -2359,7 +2387,7 @@ out:
2359out_free_fh: 2387out_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
2364out_err_nosb: 2392out_err_nosb:
2365 nfs_free_server(server); 2393 nfs_free_server(server);
@@ -2367,6 +2395,7 @@ out_err_nosb:
2367 2395
2368error_splat_root: 2396error_splat_root:
2369 dput(mntroot); 2397 dput(mntroot);
2398 mntroot = ERR_PTR(error);
2370error_splat_super: 2399error_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
2774static 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;
2791out_freepage:
2792 free_page((unsigned long)page);
2793}
2794
2795struct nfs_referral_count { 2803struct 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
2861static int nfs_follow_remote_path(struct vfsmount *root_mnt, 2869static 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;
2903out_put_mnt_ns: 2908out_put_mnt_ns:
2904 put_mnt_ns(ns_private); 2909 put_mnt_ns(ns_private);
2905out_mntput: 2910out_mntput:
2906 mntput(root_mnt); 2911 mntput(root_mnt);
2907out_err: 2912out_err:
2908 kfree(nd); 2913 kfree(nd);
2909 return ret; 2914 return ERR_PTR(ret);
2910} 2915}
2911 2916
2912static int nfs4_try_mount(int flags, const char *dev_name, 2917static 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,
2934out: 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 */
2943static int nfs4_get_sb(struct file_system_type *fs_type, 2945static 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
2960out: 2967out:
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);
2965out_free_data: 2972out_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
2972static void nfs4_kill_super(struct super_block *sb) 2979static 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 */
3163static int nfs4_referral_get_sb(struct file_system_type *fs_type, 3170static 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,
3186out: 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 6481d537d69..8d6864c2a5f 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;
275out_unlock: 293out_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 7e9dd4cc2c0..4bae0ef6110 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -843,23 +843,6 @@ error:
843} 843}
844EXPORT_SYMBOL(mount_bdev); 844EXPORT_SYMBOL(mount_bdev);
845 845
846int 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
861EXPORT_SYMBOL(get_sb_bdev);
862
863void kill_block_super(struct super_block *sb) 846void 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}
898EXPORT_SYMBOL(mount_nodev); 881EXPORT_SYMBOL(mount_nodev);
899 882
900int 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}
914EXPORT_SYMBOL(get_sb_nodev);
915
916static int compare_single(struct super_block *s, void *p) 883static 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}
944EXPORT_SYMBOL(mount_single); 911EXPORT_SYMBOL(mount_single);
945 912
946int 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
960EXPORT_SYMBOL(get_sb_single);
961
962struct vfsmount * 913struct vfsmount *
963vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data) 914vfs_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;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 2f5a71d6d76..92f7e04aea1 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1631,6 +1631,8 @@ struct super_operations {
1631 void (*umount_begin) (struct super_block *); 1631 void (*umount_begin) (struct super_block *);
1632 1632
1633 int (*show_options)(struct seq_file *, struct vfsmount *); 1633 int (*show_options)(struct seq_file *, struct vfsmount *);
1634 int (*show_devname)(struct seq_file *, struct vfsmount *);
1635 int (*show_path)(struct seq_file *, struct vfsmount *);
1634 int (*show_stats)(struct seq_file *, struct vfsmount *); 1636 int (*show_stats)(struct seq_file *, struct vfsmount *);
1635#ifdef CONFIG_QUOTA 1637#ifdef CONFIG_QUOTA
1636 ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t); 1638 ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
@@ -1794,8 +1796,6 @@ int sync_inode_metadata(struct inode *inode, int wait);
1794struct file_system_type { 1796struct file_system_type {
1795 const char *name; 1797 const char *name;
1796 int fs_flags; 1798 int fs_flags;
1797 int (*get_sb) (struct file_system_type *, int,
1798 const char *, void *, struct vfsmount *);
1799 struct dentry *(*mount) (struct file_system_type *, int, 1799 struct dentry *(*mount) (struct file_system_type *, int,
1800 const char *, void *); 1800 const char *, void *);
1801 void (*kill_sb) (struct super_block *); 1801 void (*kill_sb) (struct super_block *);
@@ -1818,24 +1818,12 @@ extern struct dentry *mount_ns(struct file_system_type *fs_type, int flags,
1818extern struct dentry *mount_bdev(struct file_system_type *fs_type, 1818extern struct dentry *mount_bdev(struct file_system_type *fs_type,
1819 int flags, const char *dev_name, void *data, 1819 int flags, const char *dev_name, void *data,
1820 int (*fill_super)(struct super_block *, void *, int)); 1820 int (*fill_super)(struct super_block *, void *, int));
1821extern int get_sb_bdev(struct file_system_type *fs_type,
1822 int flags, const char *dev_name, void *data,
1823 int (*fill_super)(struct super_block *, void *, int),
1824 struct vfsmount *mnt);
1825extern struct dentry *mount_single(struct file_system_type *fs_type, 1821extern struct dentry *mount_single(struct file_system_type *fs_type,
1826 int flags, void *data, 1822 int flags, void *data,
1827 int (*fill_super)(struct super_block *, void *, int)); 1823 int (*fill_super)(struct super_block *, void *, int));
1828extern int get_sb_single(struct file_system_type *fs_type,
1829 int flags, void *data,
1830 int (*fill_super)(struct super_block *, void *, int),
1831 struct vfsmount *mnt);
1832extern struct dentry *mount_nodev(struct file_system_type *fs_type, 1824extern struct dentry *mount_nodev(struct file_system_type *fs_type,
1833 int flags, void *data, 1825 int flags, void *data,
1834 int (*fill_super)(struct super_block *, void *, int)); 1826 int (*fill_super)(struct super_block *, void *, int));
1835extern int get_sb_nodev(struct file_system_type *fs_type,
1836 int flags, void *data,
1837 int (*fill_super)(struct super_block *, void *, int),
1838 struct vfsmount *mnt);
1839void generic_shutdown_super(struct super_block *sb); 1827void generic_shutdown_super(struct super_block *sb);
1840void kill_block_super(struct super_block *sb); 1828void kill_block_super(struct super_block *sb);
1841void kill_anon_super(struct super_block *sb); 1829void kill_anon_super(struct super_block *sb);