aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorBryan Schumaker <bjschuma@netapp.com>2012-07-16 16:39:20 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-07-17 13:33:55 -0400
commitfbdefd6442811392e857721573b63a51d1149cc8 (patch)
treed3b36fa0af3a91a22c3799db13c4cb07d0ec2fff /fs/nfs
parent3cadf4b864cab9d19b935289c004799d1065cd03 (diff)
NFS: Split out the NFS v4 filesystem types
This allows me to move the v4 mounting and unmounting functions out of the generic client and into a file that is only compiled when CONFIG_NFS_V4 is enabled. Signed-off-by: Bryan Schumaker <bjschuma@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/internal.h29
-rw-r--r--fs/nfs/nfs4_fs.h2
-rw-r--r--fs/nfs/nfs4super.c328
-rw-r--r--fs/nfs/super.c395
4 files changed, 381 insertions, 373 deletions
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index b4a35705246..cfafd13b6fe 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -153,6 +153,14 @@ struct nfs_mount_request {
153 struct net *net; 153 struct net *net;
154}; 154};
155 155
156struct nfs_mount_info {
157 void (*fill_super)(struct super_block *, struct nfs_mount_info *);
158 int (*set_security)(struct super_block *, struct dentry *, struct nfs_mount_info *);
159 struct nfs_parsed_mount_data *parsed;
160 struct nfs_clone_mount *cloned;
161 struct nfs_fh *mntfh;
162};
163
156extern int nfs_mount(struct nfs_mount_request *info); 164extern int nfs_mount(struct nfs_mount_request *info);
157extern void nfs_umount(const struct nfs_mount_request *info); 165extern void nfs_umount(const struct nfs_mount_request *info);
158 166
@@ -318,6 +326,16 @@ extern struct file_system_type nfs_xdev_fs_type;
318extern struct file_system_type nfs4_xdev_fs_type; 326extern struct file_system_type nfs4_xdev_fs_type;
319extern struct file_system_type nfs4_referral_fs_type; 327extern struct file_system_type nfs4_referral_fs_type;
320#endif 328#endif
329void nfs_initialise_sb(struct super_block *);
330int nfs_set_sb_security(struct super_block *, struct dentry *, struct nfs_mount_info *);
331int nfs_clone_sb_security(struct super_block *, struct dentry *, struct nfs_mount_info *);
332struct dentry *nfs_fs_mount_common(struct file_system_type *, struct nfs_server *,
333 int, const char *, struct nfs_mount_info *);
334struct dentry *nfs_fs_mount(struct file_system_type *, int, const char *, void *);
335struct dentry * nfs_xdev_mount_common(struct file_system_type *, int,
336 const char *, struct nfs_mount_info *);
337void nfs_kill_super(struct super_block *);
338void nfs_fill_super(struct super_block *, struct nfs_mount_info *);
321 339
322extern struct rpc_stat nfs_rpcstat; 340extern struct rpc_stat nfs_rpcstat;
323 341
@@ -364,6 +382,17 @@ extern void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio,
364extern void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio); 382extern void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio);
365extern void nfs_readdata_release(struct nfs_read_data *rdata); 383extern void nfs_readdata_release(struct nfs_read_data *rdata);
366 384
385/* super.c */
386void nfs_clone_super(struct super_block *, struct nfs_mount_info *);
387void nfs_umount_begin(struct super_block *);
388int nfs_statfs(struct dentry *, struct kstatfs *);
389int nfs_show_options(struct seq_file *, struct dentry *);
390int nfs_show_devname(struct seq_file *, struct dentry *);
391int nfs_show_path(struct seq_file *, struct dentry *);
392int nfs_show_stats(struct seq_file *, struct dentry *);
393void nfs_put_super(struct super_block *);
394int nfs_remount(struct super_block *sb, int *flags, char *raw_data);
395
367/* write.c */ 396/* write.c */
368extern void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, 397extern void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio,
369 struct inode *inode, int ioflags, 398 struct inode *inode, int ioflags,
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index b508fef1a32..b1ecacd8784 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -365,6 +365,8 @@ extern void nfs4_free_lock_state(struct nfs_server *server, struct nfs4_lock_sta
365extern const nfs4_stateid zero_stateid; 365extern const nfs4_stateid zero_stateid;
366 366
367/* nfs4super.c */ 367/* nfs4super.c */
368struct nfs_mount_info;
369struct dentry *nfs4_try_mount(int, const char *, struct nfs_mount_info *);
368int init_nfs_v4(void); 370int init_nfs_v4(void);
369void exit_nfs_v4(void); 371void exit_nfs_v4(void);
370 372
diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c
index 70c394e75ca..2af26913884 100644
--- a/fs/nfs/nfs4super.c
+++ b/fs/nfs/nfs4super.c
@@ -2,10 +2,331 @@
2 * Copyright (c) 2012 Bryan Schumaker <bjschuma@netapp.com> 2 * Copyright (c) 2012 Bryan Schumaker <bjschuma@netapp.com>
3 */ 3 */
4#include <linux/init.h> 4#include <linux/init.h>
5#include <linux/module.h>
5#include <linux/nfs_idmap.h> 6#include <linux/nfs_idmap.h>
7#include <linux/nfs4_mount.h>
6#include <linux/nfs_fs.h> 8#include <linux/nfs_fs.h>
9#include "internal.h"
7#include "nfs4_fs.h" 10#include "nfs4_fs.h"
8 11
12#define NFSDBG_FACILITY NFSDBG_VFS
13
14static struct dentry *nfs4_remote_mount(struct file_system_type *fs_type,
15 int flags, const char *dev_name, void *raw_data);
16static struct dentry *nfs4_xdev_mount(struct file_system_type *fs_type,
17 int flags, const char *dev_name, void *raw_data);
18static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type,
19 int flags, const char *dev_name, void *raw_data);
20static struct dentry *nfs4_remote_referral_mount(struct file_system_type *fs_type,
21 int flags, const char *dev_name, void *raw_data);
22
23static struct file_system_type nfs4_fs_type = {
24 .owner = THIS_MODULE,
25 .name = "nfs4",
26 .mount = nfs_fs_mount,
27 .kill_sb = nfs_kill_super,
28 .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
29};
30
31static struct file_system_type nfs4_remote_fs_type = {
32 .owner = THIS_MODULE,
33 .name = "nfs4",
34 .mount = nfs4_remote_mount,
35 .kill_sb = nfs_kill_super,
36 .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
37};
38
39struct file_system_type nfs4_xdev_fs_type = {
40 .owner = THIS_MODULE,
41 .name = "nfs4",
42 .mount = nfs4_xdev_mount,
43 .kill_sb = nfs_kill_super,
44 .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
45};
46
47static struct file_system_type nfs4_remote_referral_fs_type = {
48 .owner = THIS_MODULE,
49 .name = "nfs4",
50 .mount = nfs4_remote_referral_mount,
51 .kill_sb = nfs_kill_super,
52 .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
53};
54
55struct file_system_type nfs4_referral_fs_type = {
56 .owner = THIS_MODULE,
57 .name = "nfs4",
58 .mount = nfs4_referral_mount,
59 .kill_sb = nfs_kill_super,
60 .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
61};
62
63static const struct super_operations nfs4_sops = {
64 .alloc_inode = nfs_alloc_inode,
65 .destroy_inode = nfs_destroy_inode,
66 .write_inode = nfs4_write_inode,
67 .put_super = nfs_put_super,
68 .statfs = nfs_statfs,
69 .evict_inode = nfs4_evict_inode,
70 .umount_begin = nfs_umount_begin,
71 .show_options = nfs_show_options,
72 .show_devname = nfs_show_devname,
73 .show_path = nfs_show_path,
74 .show_stats = nfs_show_stats,
75 .remount_fs = nfs_remount,
76};
77
78/*
79 * Set up an NFS4 superblock
80 */
81static void nfs4_fill_super(struct super_block *sb,
82 struct nfs_mount_info *mount_info)
83{
84 sb->s_time_gran = 1;
85 sb->s_op = &nfs4_sops;
86 /*
87 * The VFS shouldn't apply the umask to mode bits. We will do
88 * so ourselves when necessary.
89 */
90 sb->s_flags |= MS_POSIXACL;
91 sb->s_xattr = nfs4_xattr_handlers;
92 nfs_initialise_sb(sb);
93}
94
95/*
96 * Get the superblock for the NFS4 root partition
97 */
98static struct dentry *
99nfs4_remote_mount(struct file_system_type *fs_type, int flags,
100 const char *dev_name, void *info)
101{
102 struct nfs_mount_info *mount_info = info;
103 struct nfs_server *server;
104 struct dentry *mntroot = ERR_PTR(-ENOMEM);
105
106 mount_info->fill_super = nfs4_fill_super;
107 mount_info->set_security = nfs_set_sb_security;
108
109 /* Get a volume representation */
110 server = nfs4_create_server(mount_info->parsed, mount_info->mntfh);
111 if (IS_ERR(server)) {
112 mntroot = ERR_CAST(server);
113 goto out;
114 }
115
116 mntroot = nfs_fs_mount_common(fs_type, server, flags, dev_name, mount_info);
117
118out:
119 return mntroot;
120}
121
122static struct vfsmount *nfs_do_root_mount(struct file_system_type *fs_type,
123 int flags, void *data, const char *hostname)
124{
125 struct vfsmount *root_mnt;
126 char *root_devname;
127 size_t len;
128
129 len = strlen(hostname) + 5;
130 root_devname = kmalloc(len, GFP_KERNEL);
131 if (root_devname == NULL)
132 return ERR_PTR(-ENOMEM);
133 /* Does hostname needs to be enclosed in brackets? */
134 if (strchr(hostname, ':'))
135 snprintf(root_devname, len, "[%s]:/", hostname);
136 else
137 snprintf(root_devname, len, "%s:/", hostname);
138 root_mnt = vfs_kern_mount(fs_type, flags, root_devname, data);
139 kfree(root_devname);
140 return root_mnt;
141}
142
143struct nfs_referral_count {
144 struct list_head list;
145 const struct task_struct *task;
146 unsigned int referral_count;
147};
148
149static LIST_HEAD(nfs_referral_count_list);
150static DEFINE_SPINLOCK(nfs_referral_count_list_lock);
151
152static struct nfs_referral_count *nfs_find_referral_count(void)
153{
154 struct nfs_referral_count *p;
155
156 list_for_each_entry(p, &nfs_referral_count_list, list) {
157 if (p->task == current)
158 return p;
159 }
160 return NULL;
161}
162
163#define NFS_MAX_NESTED_REFERRALS 2
164
165static int nfs_referral_loop_protect(void)
166{
167 struct nfs_referral_count *p, *new;
168 int ret = -ENOMEM;
169
170 new = kmalloc(sizeof(*new), GFP_KERNEL);
171 if (!new)
172 goto out;
173 new->task = current;
174 new->referral_count = 1;
175
176 ret = 0;
177 spin_lock(&nfs_referral_count_list_lock);
178 p = nfs_find_referral_count();
179 if (p != NULL) {
180 if (p->referral_count >= NFS_MAX_NESTED_REFERRALS)
181 ret = -ELOOP;
182 else
183 p->referral_count++;
184 } else {
185 list_add(&new->list, &nfs_referral_count_list);
186 new = NULL;
187 }
188 spin_unlock(&nfs_referral_count_list_lock);
189 kfree(new);
190out:
191 return ret;
192}
193
194static void nfs_referral_loop_unprotect(void)
195{
196 struct nfs_referral_count *p;
197
198 spin_lock(&nfs_referral_count_list_lock);
199 p = nfs_find_referral_count();
200 p->referral_count--;
201 if (p->referral_count == 0)
202 list_del(&p->list);
203 else
204 p = NULL;
205 spin_unlock(&nfs_referral_count_list_lock);
206 kfree(p);
207}
208
209static struct dentry *nfs_follow_remote_path(struct vfsmount *root_mnt,
210 const char *export_path)
211{
212 struct dentry *dentry;
213 int err;
214
215 if (IS_ERR(root_mnt))
216 return ERR_CAST(root_mnt);
217
218 err = nfs_referral_loop_protect();
219 if (err) {
220 mntput(root_mnt);
221 return ERR_PTR(err);
222 }
223
224 dentry = mount_subtree(root_mnt, export_path);
225 nfs_referral_loop_unprotect();
226
227 return dentry;
228}
229
230struct dentry *nfs4_try_mount(int flags, const char *dev_name,
231 struct nfs_mount_info *mount_info)
232{
233 char *export_path;
234 struct vfsmount *root_mnt;
235 struct dentry *res;
236 struct nfs_parsed_mount_data *data = mount_info->parsed;
237
238 dfprintk(MOUNT, "--> nfs4_try_mount()\n");
239
240 mount_info->fill_super = nfs4_fill_super;
241
242 export_path = data->nfs_server.export_path;
243 data->nfs_server.export_path = "/";
244 root_mnt = nfs_do_root_mount(&nfs4_remote_fs_type, flags, mount_info,
245 data->nfs_server.hostname);
246 data->nfs_server.export_path = export_path;
247
248 res = nfs_follow_remote_path(root_mnt, export_path);
249
250 dfprintk(MOUNT, "<-- nfs4_try_mount() = %ld%s\n",
251 IS_ERR(res) ? PTR_ERR(res) : 0,
252 IS_ERR(res) ? " [error]" : "");
253 return res;
254}
255
256/*
257 * Clone an NFS4 server record on xdev traversal (FSID-change)
258 */
259static struct dentry *
260nfs4_xdev_mount(struct file_system_type *fs_type, int flags,
261 const char *dev_name, void *raw_data)
262{
263 struct nfs_mount_info mount_info = {
264 .fill_super = nfs_clone_super,
265 .set_security = nfs_clone_sb_security,
266 .cloned = raw_data,
267 };
268 return nfs_xdev_mount_common(&nfs4_fs_type, flags, dev_name, &mount_info);
269}
270
271static struct dentry *
272nfs4_remote_referral_mount(struct file_system_type *fs_type, int flags,
273 const char *dev_name, void *raw_data)
274{
275 struct nfs_mount_info mount_info = {
276 .fill_super = nfs4_fill_super,
277 .set_security = nfs_clone_sb_security,
278 .cloned = raw_data,
279 };
280 struct nfs_server *server;
281 struct dentry *mntroot = ERR_PTR(-ENOMEM);
282
283 dprintk("--> nfs4_referral_get_sb()\n");
284
285 mount_info.mntfh = nfs_alloc_fhandle();
286 if (mount_info.cloned == NULL || mount_info.mntfh == NULL)
287 goto out;
288
289 /* create a new volume representation */
290 server = nfs4_create_referral_server(mount_info.cloned, mount_info.mntfh);
291 if (IS_ERR(server)) {
292 mntroot = ERR_CAST(server);
293 goto out;
294 }
295
296 mntroot = nfs_fs_mount_common(&nfs4_fs_type, server, flags, dev_name, &mount_info);
297out:
298 nfs_free_fhandle(mount_info.mntfh);
299 return mntroot;
300}
301
302/*
303 * Create an NFS4 server record on referral traversal
304 */
305static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type,
306 int flags, const char *dev_name, void *raw_data)
307{
308 struct nfs_clone_mount *data = raw_data;
309 char *export_path;
310 struct vfsmount *root_mnt;
311 struct dentry *res;
312
313 dprintk("--> nfs4_referral_mount()\n");
314
315 export_path = data->mnt_path;
316 data->mnt_path = "/";
317
318 root_mnt = nfs_do_root_mount(&nfs4_remote_referral_fs_type,
319 flags, data, data->hostname);
320 data->mnt_path = export_path;
321
322 res = nfs_follow_remote_path(root_mnt, export_path);
323 dprintk("<-- nfs4_referral_mount() = %ld%s\n",
324 IS_ERR(res) ? PTR_ERR(res) : 0,
325 IS_ERR(res) ? " [error]" : "");
326 return res;
327}
328
329
9int __init init_nfs_v4(void) 330int __init init_nfs_v4(void)
10{ 331{
11 int err; 332 int err;
@@ -18,7 +339,13 @@ int __init init_nfs_v4(void)
18 if (err) 339 if (err)
19 goto out1; 340 goto out1;
20 341
342 err = register_filesystem(&nfs4_fs_type);
343 if (err < 0)
344 goto out2;
345
21 return 0; 346 return 0;
347out2:
348 nfs4_unregister_sysctl();
22out1: 349out1:
23 nfs_idmap_quit(); 350 nfs_idmap_quit();
24out: 351out:
@@ -27,6 +354,7 @@ out:
27 354
28void __exit exit_nfs_v4(void) 355void __exit exit_nfs_v4(void)
29{ 356{
357 unregister_filesystem(&nfs4_fs_type);
30 nfs4_unregister_sysctl(); 358 nfs4_unregister_sysctl();
31 nfs_idmap_quit(); 359 nfs_idmap_quit();
32} 360}
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index ca3c0e8cf77..95866a8c21b 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -278,29 +278,8 @@ static match_table_t nfs_vers_tokens = {
278 { Opt_vers_err, NULL } 278 { Opt_vers_err, NULL }
279}; 279};
280 280
281struct nfs_mount_info {
282 void (*fill_super)(struct super_block *, struct nfs_mount_info *);
283 int (*set_security)(struct super_block *, struct dentry *, struct nfs_mount_info *);
284 struct nfs_parsed_mount_data *parsed;
285 struct nfs_clone_mount *cloned;
286 struct nfs_fh *mntfh;
287};
288
289static void nfs_umount_begin(struct super_block *);
290static int nfs_statfs(struct dentry *, struct kstatfs *);
291static int nfs_show_options(struct seq_file *, struct dentry *);
292static int nfs_show_devname(struct seq_file *, struct dentry *);
293static int nfs_show_path(struct seq_file *, struct dentry *);
294static int nfs_show_stats(struct seq_file *, struct dentry *);
295static struct dentry *nfs_fs_mount_common(struct file_system_type *,
296 struct nfs_server *, int, const char *, struct nfs_mount_info *);
297static struct dentry *nfs_fs_mount(struct file_system_type *,
298 int, const char *, void *);
299static struct dentry *nfs_xdev_mount(struct file_system_type *fs_type, 281static struct dentry *nfs_xdev_mount(struct file_system_type *fs_type,
300 int flags, const char *dev_name, void *raw_data); 282 int flags, const char *dev_name, void *raw_data);
301static void nfs_put_super(struct super_block *);
302static void nfs_kill_super(struct super_block *);
303static int nfs_remount(struct super_block *sb, int *flags, char *raw_data);
304 283
305static struct file_system_type nfs_fs_type = { 284static struct file_system_type nfs_fs_type = {
306 .owner = THIS_MODULE, 285 .owner = THIS_MODULE,
@@ -337,71 +316,6 @@ static const struct super_operations nfs_sops = {
337static void nfs4_validate_mount_flags(struct nfs_parsed_mount_data *); 316static void nfs4_validate_mount_flags(struct nfs_parsed_mount_data *);
338static int nfs4_validate_mount_data(void *options, 317static int nfs4_validate_mount_data(void *options,
339 struct nfs_parsed_mount_data *args, const char *dev_name); 318 struct nfs_parsed_mount_data *args, const char *dev_name);
340static struct dentry *nfs4_try_mount(int flags, const char *dev_name,
341 struct nfs_mount_info *mount_info);
342static struct dentry *nfs4_remote_mount(struct file_system_type *fs_type,
343 int flags, const char *dev_name, void *raw_data);
344static struct dentry *nfs4_xdev_mount(struct file_system_type *fs_type,
345 int flags, const char *dev_name, void *raw_data);
346static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type,
347 int flags, const char *dev_name, void *raw_data);
348static struct dentry *nfs4_remote_referral_mount(struct file_system_type *fs_type,
349 int flags, const char *dev_name, void *raw_data);
350
351static struct file_system_type nfs4_fs_type = {
352 .owner = THIS_MODULE,
353 .name = "nfs4",
354 .mount = nfs_fs_mount,
355 .kill_sb = nfs_kill_super,
356 .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
357};
358
359static struct file_system_type nfs4_remote_fs_type = {
360 .owner = THIS_MODULE,
361 .name = "nfs4",
362 .mount = nfs4_remote_mount,
363 .kill_sb = nfs_kill_super,
364 .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
365};
366
367struct file_system_type nfs4_xdev_fs_type = {
368 .owner = THIS_MODULE,
369 .name = "nfs4",
370 .mount = nfs4_xdev_mount,
371 .kill_sb = nfs_kill_super,
372 .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
373};
374
375static struct file_system_type nfs4_remote_referral_fs_type = {
376 .owner = THIS_MODULE,
377 .name = "nfs4",
378 .mount = nfs4_remote_referral_mount,
379 .kill_sb = nfs_kill_super,
380 .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
381};
382
383struct file_system_type nfs4_referral_fs_type = {
384 .owner = THIS_MODULE,
385 .name = "nfs4",
386 .mount = nfs4_referral_mount,
387 .kill_sb = nfs_kill_super,
388 .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
389};
390
391static const struct super_operations nfs4_sops = {
392 .alloc_inode = nfs_alloc_inode,
393 .destroy_inode = nfs_destroy_inode,
394 .write_inode = nfs4_write_inode,
395 .put_super = nfs_put_super,
396 .statfs = nfs_statfs,
397 .evict_inode = nfs4_evict_inode,
398 .umount_begin = nfs_umount_begin,
399 .show_options = nfs_show_options,
400 .show_devname = nfs_show_devname,
401 .show_path = nfs_show_path,
402 .show_stats = nfs_show_stats,
403 .remount_fs = nfs_remount,
404};
405#endif 319#endif
406 320
407static struct shrinker acl_shrinker = { 321static struct shrinker acl_shrinker = {
@@ -423,18 +337,9 @@ int __init register_nfs_fs(void)
423 ret = nfs_register_sysctl(); 337 ret = nfs_register_sysctl();
424 if (ret < 0) 338 if (ret < 0)
425 goto error_1; 339 goto error_1;
426#ifdef CONFIG_NFS_V4
427 ret = register_filesystem(&nfs4_fs_type);
428 if (ret < 0)
429 goto error_2;
430#endif
431 register_shrinker(&acl_shrinker); 340 register_shrinker(&acl_shrinker);
432 return 0; 341 return 0;
433 342
434#ifdef CONFIG_NFS_V4
435error_2:
436 nfs_unregister_sysctl();
437#endif
438error_1: 343error_1:
439 unregister_filesystem(&nfs_fs_type); 344 unregister_filesystem(&nfs_fs_type);
440error_0: 345error_0:
@@ -447,9 +352,6 @@ error_0:
447void __exit unregister_nfs_fs(void) 352void __exit unregister_nfs_fs(void)
448{ 353{
449 unregister_shrinker(&acl_shrinker); 354 unregister_shrinker(&acl_shrinker);
450#ifdef CONFIG_NFS_V4
451 unregister_filesystem(&nfs4_fs_type);
452#endif
453 nfs_unregister_sysctl(); 355 nfs_unregister_sysctl();
454 unregister_filesystem(&nfs_fs_type); 356 unregister_filesystem(&nfs_fs_type);
455} 357}
@@ -473,7 +375,7 @@ void nfs_sb_deactive(struct super_block *sb)
473/* 375/*
474 * Deliver file system statistics to userspace 376 * Deliver file system statistics to userspace
475 */ 377 */
476static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf) 378int nfs_statfs(struct dentry *dentry, struct kstatfs *buf)
477{ 379{
478 struct nfs_server *server = NFS_SB(dentry->d_sb); 380 struct nfs_server *server = NFS_SB(dentry->d_sb);
479 unsigned char blockbits; 381 unsigned char blockbits;
@@ -756,7 +658,7 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
756/* 658/*
757 * Describe the mount options on this VFS mountpoint 659 * Describe the mount options on this VFS mountpoint
758 */ 660 */
759static int nfs_show_options(struct seq_file *m, struct dentry *root) 661int nfs_show_options(struct seq_file *m, struct dentry *root)
760{ 662{
761 struct nfs_server *nfss = NFS_SB(root->d_sb); 663 struct nfs_server *nfss = NFS_SB(root->d_sb);
762 664
@@ -814,7 +716,7 @@ static void show_implementation_id(struct seq_file *m, struct nfs_server *nfss)
814} 716}
815#endif 717#endif
816 718
817static int nfs_show_devname(struct seq_file *m, struct dentry *root) 719int nfs_show_devname(struct seq_file *m, struct dentry *root)
818{ 720{
819 char *page = (char *) __get_free_page(GFP_KERNEL); 721 char *page = (char *) __get_free_page(GFP_KERNEL);
820 char *devname, *dummy; 722 char *devname, *dummy;
@@ -830,7 +732,7 @@ static int nfs_show_devname(struct seq_file *m, struct dentry *root)
830 return err; 732 return err;
831} 733}
832 734
833static int nfs_show_path(struct seq_file *m, struct dentry *dentry) 735int nfs_show_path(struct seq_file *m, struct dentry *dentry)
834{ 736{
835 seq_puts(m, "/"); 737 seq_puts(m, "/");
836 return 0; 738 return 0;
@@ -839,7 +741,7 @@ static int nfs_show_path(struct seq_file *m, struct dentry *dentry)
839/* 741/*
840 * Present statistical information for this VFS mountpoint 742 * Present statistical information for this VFS mountpoint
841 */ 743 */
842static int nfs_show_stats(struct seq_file *m, struct dentry *root) 744int nfs_show_stats(struct seq_file *m, struct dentry *root)
843{ 745{
844 int i, cpu; 746 int i, cpu;
845 struct nfs_server *nfss = NFS_SB(root->d_sb); 747 struct nfs_server *nfss = NFS_SB(root->d_sb);
@@ -932,7 +834,7 @@ static int nfs_show_stats(struct seq_file *m, struct dentry *root)
932 * Begin unmount by attempting to remove all automounted mountpoints we added 834 * Begin unmount by attempting to remove all automounted mountpoints we added
933 * in response to xdev traversals and referrals 835 * in response to xdev traversals and referrals
934 */ 836 */
935static void nfs_umount_begin(struct super_block *sb) 837void nfs_umount_begin(struct super_block *sb)
936{ 838{
937 struct nfs_server *server; 839 struct nfs_server *server;
938 struct rpc_clnt *rpc; 840 struct rpc_clnt *rpc;
@@ -2107,7 +2009,7 @@ nfs_compare_remount_data(struct nfs_server *nfss,
2107 return 0; 2009 return 0;
2108} 2010}
2109 2011
2110static int 2012int
2111nfs_remount(struct super_block *sb, int *flags, char *raw_data) 2013nfs_remount(struct super_block *sb, int *flags, char *raw_data)
2112{ 2014{
2113 int error; 2015 int error;
@@ -2172,7 +2074,7 @@ out:
2172/* 2074/*
2173 * Initialise the common bits of the superblock 2075 * Initialise the common bits of the superblock
2174 */ 2076 */
2175static inline void nfs_initialise_sb(struct super_block *sb) 2077inline void nfs_initialise_sb(struct super_block *sb)
2176{ 2078{
2177 struct nfs_server *server = NFS_SB(sb); 2079 struct nfs_server *server = NFS_SB(sb);
2178 2080
@@ -2194,8 +2096,7 @@ static inline void nfs_initialise_sb(struct super_block *sb)
2194/* 2096/*
2195 * Finish setting up an NFS2/3 superblock 2097 * Finish setting up an NFS2/3 superblock
2196 */ 2098 */
2197static void nfs_fill_super(struct super_block *sb, 2099void nfs_fill_super(struct super_block *sb, struct nfs_mount_info *mount_info)
2198 struct nfs_mount_info *mount_info)
2199{ 2100{
2200 struct nfs_parsed_mount_data *data = mount_info->parsed; 2101 struct nfs_parsed_mount_data *data = mount_info->parsed;
2201 struct nfs_server *server = NFS_SB(sb); 2102 struct nfs_server *server = NFS_SB(sb);
@@ -2220,8 +2121,7 @@ static void nfs_fill_super(struct super_block *sb,
2220/* 2121/*
2221 * Finish setting up a cloned NFS2/3/4 superblock 2122 * Finish setting up a cloned NFS2/3/4 superblock
2222 */ 2123 */
2223static void nfs_clone_super(struct super_block *sb, 2124void nfs_clone_super(struct super_block *sb, struct nfs_mount_info *mount_info)
2224 struct nfs_mount_info *mount_info)
2225{ 2125{
2226 const struct super_block *old_sb = mount_info->cloned->sb; 2126 const struct super_block *old_sb = mount_info->cloned->sb;
2227 struct nfs_server *server = NFS_SB(sb); 2127 struct nfs_server *server = NFS_SB(sb);
@@ -2381,14 +2281,14 @@ static int nfs_bdi_register(struct nfs_server *server)
2381 return bdi_register_dev(&server->backing_dev_info, server->s_dev); 2281 return bdi_register_dev(&server->backing_dev_info, server->s_dev);
2382} 2282}
2383 2283
2384static int nfs_set_sb_security(struct super_block *s, struct dentry *mntroot, 2284int nfs_set_sb_security(struct super_block *s, struct dentry *mntroot,
2385 struct nfs_mount_info *mount_info) 2285 struct nfs_mount_info *mount_info)
2386{ 2286{
2387 return security_sb_set_mnt_opts(s, &mount_info->parsed->lsm_opts); 2287 return security_sb_set_mnt_opts(s, &mount_info->parsed->lsm_opts);
2388} 2288}
2389 2289
2390static int nfs_clone_sb_security(struct super_block *s, struct dentry *mntroot, 2290int nfs_clone_sb_security(struct super_block *s, struct dentry *mntroot,
2391 struct nfs_mount_info *mount_info) 2291 struct nfs_mount_info *mount_info)
2392{ 2292{
2393 /* clone any lsm security options from the parent to the new sb */ 2293 /* clone any lsm security options from the parent to the new sb */
2394 security_sb_clone_mnt_opts(mount_info->cloned->sb, s); 2294 security_sb_clone_mnt_opts(mount_info->cloned->sb, s);
@@ -2397,10 +2297,10 @@ static int nfs_clone_sb_security(struct super_block *s, struct dentry *mntroot,
2397 return 0; 2297 return 0;
2398} 2298}
2399 2299
2400static struct dentry *nfs_fs_mount_common(struct file_system_type *fs_type, 2300struct dentry *nfs_fs_mount_common(struct file_system_type *fs_type,
2401 struct nfs_server *server, 2301 struct nfs_server *server,
2402 int flags, const char *dev_name, 2302 int flags, const char *dev_name,
2403 struct nfs_mount_info *mount_info) 2303 struct nfs_mount_info *mount_info)
2404{ 2304{
2405 struct super_block *s; 2305 struct super_block *s;
2406 struct dentry *mntroot = ERR_PTR(-ENOMEM); 2306 struct dentry *mntroot = ERR_PTR(-ENOMEM);
@@ -2470,7 +2370,7 @@ error_splat_bdi:
2470 goto out; 2370 goto out;
2471} 2371}
2472 2372
2473static struct dentry *nfs_fs_mount(struct file_system_type *fs_type, 2373struct dentry *nfs_fs_mount(struct file_system_type *fs_type,
2474 int flags, const char *dev_name, void *raw_data) 2374 int flags, const char *dev_name, void *raw_data)
2475{ 2375{
2476 struct nfs_mount_info mount_info = { 2376 struct nfs_mount_info mount_info = {
@@ -2511,7 +2411,7 @@ out:
2511 * Ensure that we unregister the bdi before kill_anon_super 2411 * Ensure that we unregister the bdi before kill_anon_super
2512 * releases the device name 2412 * releases the device name
2513 */ 2413 */
2514static void nfs_put_super(struct super_block *s) 2414void nfs_put_super(struct super_block *s)
2515{ 2415{
2516 struct nfs_server *server = NFS_SB(s); 2416 struct nfs_server *server = NFS_SB(s);
2517 2417
@@ -2521,7 +2421,7 @@ static void nfs_put_super(struct super_block *s)
2521/* 2421/*
2522 * Destroy an NFS2/3 superblock 2422 * Destroy an NFS2/3 superblock
2523 */ 2423 */
2524static void nfs_kill_super(struct super_block *s) 2424void nfs_kill_super(struct super_block *s)
2525{ 2425{
2526 struct nfs_server *server = NFS_SB(s); 2426 struct nfs_server *server = NFS_SB(s);
2527 2427
@@ -2533,7 +2433,7 @@ static void nfs_kill_super(struct super_block *s)
2533/* 2433/*
2534 * Clone an NFS2/3/4 server record on xdev traversal (FSID-change) 2434 * Clone an NFS2/3/4 server record on xdev traversal (FSID-change)
2535 */ 2435 */
2536static struct dentry * 2436struct dentry *
2537nfs_xdev_mount_common(struct file_system_type *fs_type, int flags, 2437nfs_xdev_mount_common(struct file_system_type *fs_type, int flags,
2538 const char *dev_name, struct nfs_mount_info *mount_info) 2438 const char *dev_name, struct nfs_mount_info *mount_info)
2539{ 2439{
@@ -2580,23 +2480,6 @@ nfs_xdev_mount(struct file_system_type *fs_type, int flags,
2580 2480
2581#ifdef CONFIG_NFS_V4 2481#ifdef CONFIG_NFS_V4
2582 2482
2583/*
2584 * Set up an NFS4 superblock
2585 */
2586static void nfs4_fill_super(struct super_block *sb,
2587 struct nfs_mount_info *mount_info)
2588{
2589 sb->s_time_gran = 1;
2590 sb->s_op = &nfs4_sops;
2591 /*
2592 * The VFS shouldn't apply the umask to mode bits. We will do
2593 * so ourselves when necessary.
2594 */
2595 sb->s_flags |= MS_POSIXACL;
2596 sb->s_xattr = nfs4_xattr_handlers;
2597 nfs_initialise_sb(sb);
2598}
2599
2600static void nfs4_validate_mount_flags(struct nfs_parsed_mount_data *args) 2483static void nfs4_validate_mount_flags(struct nfs_parsed_mount_data *args)
2601{ 2484{
2602 args->flags &= ~(NFS_MOUNT_NONLM|NFS_MOUNT_NOACL|NFS_MOUNT_VER3| 2485 args->flags &= ~(NFS_MOUNT_NONLM|NFS_MOUNT_NOACL|NFS_MOUNT_VER3|
@@ -2694,238 +2577,4 @@ out_no_address:
2694 return -EINVAL; 2577 return -EINVAL;
2695} 2578}
2696 2579
2697/*
2698 * Get the superblock for the NFS4 root partition
2699 */
2700static struct dentry *
2701nfs4_remote_mount(struct file_system_type *fs_type, int flags,
2702 const char *dev_name, void *info)
2703{
2704 struct nfs_mount_info *mount_info = info;
2705 struct nfs_server *server;
2706 struct dentry *mntroot = ERR_PTR(-ENOMEM);
2707
2708 mount_info->fill_super = nfs4_fill_super;
2709 mount_info->set_security = nfs_set_sb_security;
2710
2711 /* Get a volume representation */
2712 server = nfs4_create_server(mount_info->parsed, mount_info->mntfh);
2713 if (IS_ERR(server)) {
2714 mntroot = ERR_CAST(server);
2715 goto out;
2716 }
2717
2718 mntroot = nfs_fs_mount_common(fs_type, server, flags, dev_name, mount_info);
2719
2720out:
2721 return mntroot;
2722}
2723
2724static struct vfsmount *nfs_do_root_mount(struct file_system_type *fs_type,
2725 int flags, void *data, const char *hostname)
2726{
2727 struct vfsmount *root_mnt;
2728 char *root_devname;
2729 size_t len;
2730
2731 len = strlen(hostname) + 5;
2732 root_devname = kmalloc(len, GFP_KERNEL);
2733 if (root_devname == NULL)
2734 return ERR_PTR(-ENOMEM);
2735 /* Does hostname needs to be enclosed in brackets? */
2736 if (strchr(hostname, ':'))
2737 snprintf(root_devname, len, "[%s]:/", hostname);
2738 else
2739 snprintf(root_devname, len, "%s:/", hostname);
2740 root_mnt = vfs_kern_mount(fs_type, flags, root_devname, data);
2741 kfree(root_devname);
2742 return root_mnt;
2743}
2744
2745struct nfs_referral_count {
2746 struct list_head list;
2747 const struct task_struct *task;
2748 unsigned int referral_count;
2749};
2750
2751static LIST_HEAD(nfs_referral_count_list);
2752static DEFINE_SPINLOCK(nfs_referral_count_list_lock);
2753
2754static struct nfs_referral_count *nfs_find_referral_count(void)
2755{
2756 struct nfs_referral_count *p;
2757
2758 list_for_each_entry(p, &nfs_referral_count_list, list) {
2759 if (p->task == current)
2760 return p;
2761 }
2762 return NULL;
2763}
2764
2765#define NFS_MAX_NESTED_REFERRALS 2
2766
2767static int nfs_referral_loop_protect(void)
2768{
2769 struct nfs_referral_count *p, *new;
2770 int ret = -ENOMEM;
2771
2772 new = kmalloc(sizeof(*new), GFP_KERNEL);
2773 if (!new)
2774 goto out;
2775 new->task = current;
2776 new->referral_count = 1;
2777
2778 ret = 0;
2779 spin_lock(&nfs_referral_count_list_lock);
2780 p = nfs_find_referral_count();
2781 if (p != NULL) {
2782 if (p->referral_count >= NFS_MAX_NESTED_REFERRALS)
2783 ret = -ELOOP;
2784 else
2785 p->referral_count++;
2786 } else {
2787 list_add(&new->list, &nfs_referral_count_list);
2788 new = NULL;
2789 }
2790 spin_unlock(&nfs_referral_count_list_lock);
2791 kfree(new);
2792out:
2793 return ret;
2794}
2795
2796static void nfs_referral_loop_unprotect(void)
2797{
2798 struct nfs_referral_count *p;
2799
2800 spin_lock(&nfs_referral_count_list_lock);
2801 p = nfs_find_referral_count();
2802 p->referral_count--;
2803 if (p->referral_count == 0)
2804 list_del(&p->list);
2805 else
2806 p = NULL;
2807 spin_unlock(&nfs_referral_count_list_lock);
2808 kfree(p);
2809}
2810
2811static struct dentry *nfs_follow_remote_path(struct vfsmount *root_mnt,
2812 const char *export_path)
2813{
2814 struct dentry *dentry;
2815 int err;
2816
2817 if (IS_ERR(root_mnt))
2818 return ERR_CAST(root_mnt);
2819
2820 err = nfs_referral_loop_protect();
2821 if (err) {
2822 mntput(root_mnt);
2823 return ERR_PTR(err);
2824 }
2825
2826 dentry = mount_subtree(root_mnt, export_path);
2827 nfs_referral_loop_unprotect();
2828
2829 return dentry;
2830}
2831
2832static struct dentry *nfs4_try_mount(int flags, const char *dev_name,
2833 struct nfs_mount_info *mount_info)
2834{
2835 char *export_path;
2836 struct vfsmount *root_mnt;
2837 struct dentry *res;
2838 struct nfs_parsed_mount_data *data = mount_info->parsed;
2839
2840 dfprintk(MOUNT, "--> nfs4_try_mount()\n");
2841
2842 mount_info->fill_super = nfs4_fill_super;
2843
2844 export_path = data->nfs_server.export_path;
2845 data->nfs_server.export_path = "/";
2846 root_mnt = nfs_do_root_mount(&nfs4_remote_fs_type, flags, mount_info,
2847 data->nfs_server.hostname);
2848 data->nfs_server.export_path = export_path;
2849
2850 res = nfs_follow_remote_path(root_mnt, export_path);
2851
2852 dfprintk(MOUNT, "<-- nfs4_try_mount() = %ld%s\n",
2853 IS_ERR(res) ? PTR_ERR(res) : 0,
2854 IS_ERR(res) ? " [error]" : "");
2855 return res;
2856}
2857
2858/*
2859 * Clone an NFS4 server record on xdev traversal (FSID-change)
2860 */
2861static struct dentry *
2862nfs4_xdev_mount(struct file_system_type *fs_type, int flags,
2863 const char *dev_name, void *raw_data)
2864{
2865 struct nfs_mount_info mount_info = {
2866 .fill_super = nfs_clone_super,
2867 .set_security = nfs_clone_sb_security,
2868 .cloned = raw_data,
2869 };
2870 return nfs_xdev_mount_common(&nfs4_fs_type, flags, dev_name, &mount_info);
2871}
2872
2873static struct dentry *
2874nfs4_remote_referral_mount(struct file_system_type *fs_type, int flags,
2875 const char *dev_name, void *raw_data)
2876{
2877 struct nfs_mount_info mount_info = {
2878 .fill_super = nfs4_fill_super,
2879 .set_security = nfs_clone_sb_security,
2880 .cloned = raw_data,
2881 };
2882 struct nfs_server *server;
2883 struct dentry *mntroot = ERR_PTR(-ENOMEM);
2884
2885 dprintk("--> nfs4_referral_get_sb()\n");
2886
2887 mount_info.mntfh = nfs_alloc_fhandle();
2888 if (mount_info.cloned == NULL || mount_info.mntfh == NULL)
2889 goto out;
2890
2891 /* create a new volume representation */
2892 server = nfs4_create_referral_server(mount_info.cloned, mount_info.mntfh);
2893 if (IS_ERR(server)) {
2894 mntroot = ERR_CAST(server);
2895 goto out;
2896 }
2897
2898 mntroot = nfs_fs_mount_common(&nfs4_fs_type, server, flags, dev_name, &mount_info);
2899out:
2900 nfs_free_fhandle(mount_info.mntfh);
2901 return mntroot;
2902}
2903
2904/*
2905 * Create an NFS4 server record on referral traversal
2906 */
2907static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type,
2908 int flags, const char *dev_name, void *raw_data)
2909{
2910 struct nfs_clone_mount *data = raw_data;
2911 char *export_path;
2912 struct vfsmount *root_mnt;
2913 struct dentry *res;
2914
2915 dprintk("--> nfs4_referral_mount()\n");
2916
2917 export_path = data->mnt_path;
2918 data->mnt_path = "/";
2919
2920 root_mnt = nfs_do_root_mount(&nfs4_remote_referral_fs_type,
2921 flags, data, data->hostname);
2922 data->mnt_path = export_path;
2923
2924 res = nfs_follow_remote_path(root_mnt, export_path);
2925 dprintk("<-- nfs4_referral_mount() = %ld%s\n",
2926 IS_ERR(res) ? PTR_ERR(res) : 0,
2927 IS_ERR(res) ? " [error]" : "");
2928 return res;
2929}
2930
2931#endif /* CONFIG_NFS_V4 */ 2580#endif /* CONFIG_NFS_V4 */