aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/super.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2006-06-09 09:34:33 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2006-06-09 09:34:33 -0400
commitf7b422b17ee5ee4920e8ae24a6ad04bf3481ce72 (patch)
tree4ae8372762efc092ceb4f884b57cad1efe6594de /fs/nfs/super.c
parent4e5ccf60c5aa79d325c123f47d288a068166f389 (diff)
NFS: Split fs/nfs/inode.c
As fs/nfs/inode.c is rather large, heterogenous and unwieldy, the attached patch splits it up into a number of files: (*) fs/nfs/inode.c Strictly inode specific functions. (*) fs/nfs/super.c Superblock management functions for NFS and NFS4, normal access, clones and referrals. The NFS4 superblock functions _could_ move out into a separate conditionally compiled file, but it's probably not worth it as there're so many common bits. (*) fs/nfs/namespace.c Some namespace-specific functions have been moved here. (*) fs/nfs/nfs4namespace.c NFS4-specific namespace functions (this could be merged into the previous file). This file is conditionally compiled. (*) fs/nfs/internal.h Inter-file declarations, plus a few simple utility functions moved from fs/nfs/inode.c. Additionally, all the in-.c-file externs have been moved here, and those files they were moved from now includes this file. For the most part, the functions have not been changed, only some multiplexor functions have changed significantly. I've also: (*) Added some extra banner comments above some functions. (*) Rearranged the function order within the files to be more logical and better grouped (IMO), though someone may prefer a different order. (*) Reduced the number of #ifdefs in .c files. (*) Added missing __init and __exit directives. Signed-Off-By: David Howells <dhowells@redhat.com>
Diffstat (limited to 'fs/nfs/super.c')
-rw-r--r--fs/nfs/super.c1468
1 files changed, 1468 insertions, 0 deletions
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
new file mode 100644
index 000000000000..4acd3ee96427
--- /dev/null
+++ b/fs/nfs/super.c
@@ -0,0 +1,1468 @@
1/*
2 * linux/fs/nfs/super.c
3 *
4 * Copyright (C) 1992 Rick Sladkey
5 *
6 * nfs superblock handling functions
7 *
8 * Modularised by Alan Cox <Alan.Cox@linux.org>, while hacking some
9 * experimental NFS changes. Modularisation taken straight from SYS5 fs.
10 *
11 * Change to nfs_read_super() to permit NFS mounts to multi-homed hosts.
12 * J.S.Peatfield@damtp.cam.ac.uk
13 *
14 * Split from inode.c by David Howells <dhowells@redhat.com>
15 *
16 */
17
18#include <linux/config.h>
19#include <linux/module.h>
20#include <linux/init.h>
21
22#include <linux/time.h>
23#include <linux/kernel.h>
24#include <linux/mm.h>
25#include <linux/string.h>
26#include <linux/stat.h>
27#include <linux/errno.h>
28#include <linux/unistd.h>
29#include <linux/sunrpc/clnt.h>
30#include <linux/sunrpc/stats.h>
31#include <linux/sunrpc/metrics.h>
32#include <linux/nfs_fs.h>
33#include <linux/nfs_mount.h>
34#include <linux/nfs4_mount.h>
35#include <linux/lockd/bind.h>
36#include <linux/smp_lock.h>
37#include <linux/seq_file.h>
38#include <linux/mount.h>
39#include <linux/nfs_idmap.h>
40#include <linux/vfs.h>
41#include <linux/inet.h>
42#include <linux/nfs_xdr.h>
43
44#include <asm/system.h>
45#include <asm/uaccess.h>
46
47#include "nfs4_fs.h"
48#include "callback.h"
49#include "delegation.h"
50#include "iostat.h"
51#include "internal.h"
52
53#define NFSDBG_FACILITY NFSDBG_VFS
54
55/* Maximum number of readahead requests
56 * FIXME: this should really be a sysctl so that users may tune it to suit
57 * their needs. People that do NFS over a slow network, might for
58 * instance want to reduce it to something closer to 1 for improved
59 * interactive response.
60 */
61#define NFS_MAX_READAHEAD (RPC_DEF_SLOT_TABLE - 1)
62
63/*
64 * RPC cruft for NFS
65 */
66static struct rpc_version * nfs_version[] = {
67 NULL,
68 NULL,
69 &nfs_version2,
70#if defined(CONFIG_NFS_V3)
71 &nfs_version3,
72#elif defined(CONFIG_NFS_V4)
73 NULL,
74#endif
75#if defined(CONFIG_NFS_V4)
76 &nfs_version4,
77#endif
78};
79
80static struct rpc_program nfs_program = {
81 .name = "nfs",
82 .number = NFS_PROGRAM,
83 .nrvers = ARRAY_SIZE(nfs_version),
84 .version = nfs_version,
85 .stats = &nfs_rpcstat,
86 .pipe_dir_name = "/nfs",
87};
88
89struct rpc_stat nfs_rpcstat = {
90 .program = &nfs_program
91};
92
93
94#ifdef CONFIG_NFS_V3_ACL
95static struct rpc_stat nfsacl_rpcstat = { &nfsacl_program };
96static struct rpc_version * nfsacl_version[] = {
97 [3] = &nfsacl_version3,
98};
99
100struct rpc_program nfsacl_program = {
101 .name = "nfsacl",
102 .number = NFS_ACL_PROGRAM,
103 .nrvers = ARRAY_SIZE(nfsacl_version),
104 .version = nfsacl_version,
105 .stats = &nfsacl_rpcstat,
106};
107#endif /* CONFIG_NFS_V3_ACL */
108
109static void nfs_umount_begin(struct vfsmount *, int);
110static int nfs_statfs(struct super_block *, struct kstatfs *);
111static int nfs_show_options(struct seq_file *, struct vfsmount *);
112static int nfs_show_stats(struct seq_file *, struct vfsmount *);
113static struct super_block *nfs_get_sb(struct file_system_type *, int, const char *, void *);
114static struct super_block *nfs_clone_nfs_sb(struct file_system_type *fs_type,
115 int flags, const char *dev_name, void *raw_data);
116static void nfs_kill_super(struct super_block *);
117
118static struct file_system_type nfs_fs_type = {
119 .owner = THIS_MODULE,
120 .name = "nfs",
121 .get_sb = nfs_get_sb,
122 .kill_sb = nfs_kill_super,
123 .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
124};
125
126struct file_system_type clone_nfs_fs_type = {
127 .owner = THIS_MODULE,
128 .name = "nfs",
129 .get_sb = nfs_clone_nfs_sb,
130 .kill_sb = nfs_kill_super,
131 .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
132};
133
134static struct super_operations nfs_sops = {
135 .alloc_inode = nfs_alloc_inode,
136 .destroy_inode = nfs_destroy_inode,
137 .write_inode = nfs_write_inode,
138 .statfs = nfs_statfs,
139 .clear_inode = nfs_clear_inode,
140 .umount_begin = nfs_umount_begin,
141 .show_options = nfs_show_options,
142 .show_stats = nfs_show_stats,
143};
144
145#ifdef CONFIG_NFS_V4
146static struct super_block *nfs4_get_sb(struct file_system_type *fs_type,
147 int flags, const char *dev_name, void *raw_data);
148static struct super_block *nfs_clone_nfs4_sb(struct file_system_type *fs_type,
149 int flags, const char *dev_name, void *raw_data);
150static struct super_block *nfs_referral_nfs4_sb(struct file_system_type *fs_type,
151 int flags, const char *dev_name, void *raw_data);
152static void nfs4_kill_super(struct super_block *sb);
153
154static struct file_system_type nfs4_fs_type = {
155 .owner = THIS_MODULE,
156 .name = "nfs4",
157 .get_sb = nfs4_get_sb,
158 .kill_sb = nfs4_kill_super,
159 .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
160};
161
162struct file_system_type clone_nfs4_fs_type = {
163 .owner = THIS_MODULE,
164 .name = "nfs4",
165 .get_sb = nfs_clone_nfs4_sb,
166 .kill_sb = nfs4_kill_super,
167 .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
168};
169
170struct file_system_type nfs_referral_nfs4_fs_type = {
171 .owner = THIS_MODULE,
172 .name = "nfs4",
173 .get_sb = nfs_referral_nfs4_sb,
174 .kill_sb = nfs4_kill_super,
175 .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
176};
177
178static struct super_operations nfs4_sops = {
179 .alloc_inode = nfs_alloc_inode,
180 .destroy_inode = nfs_destroy_inode,
181 .write_inode = nfs_write_inode,
182 .statfs = nfs_statfs,
183 .clear_inode = nfs4_clear_inode,
184 .umount_begin = nfs_umount_begin,
185 .show_options = nfs_show_options,
186 .show_stats = nfs_show_stats,
187};
188#endif
189
190static const int nfs_set_port_min = 0;
191static const int nfs_set_port_max = 65535;
192
193static int param_set_port(const char *val, struct kernel_param *kp)
194{
195 char *endp;
196 int num = simple_strtol(val, &endp, 0);
197 if (endp == val || *endp || num < nfs_set_port_min || num > nfs_set_port_max)
198 return -EINVAL;
199 *((int *)kp->arg) = num;
200 return 0;
201}
202
203module_param_call(callback_tcpport, param_set_port, param_get_int,
204 &nfs_callback_set_tcpport, 0644);
205
206static int param_set_idmap_timeout(const char *val, struct kernel_param *kp)
207{
208 char *endp;
209 int num = simple_strtol(val, &endp, 0);
210 int jif = num * HZ;
211 if (endp == val || *endp || num < 0 || jif < num)
212 return -EINVAL;
213 *((int *)kp->arg) = jif;
214 return 0;
215}
216
217module_param_call(idmap_cache_timeout, param_set_idmap_timeout, param_get_int,
218 &nfs_idmap_cache_timeout, 0644);
219
220/*
221 * Register the NFS filesystems
222 */
223int __init register_nfs_fs(void)
224{
225 int ret;
226
227 ret = register_filesystem(&nfs_fs_type);
228 if (ret < 0)
229 goto error_0;
230
231#ifdef CONFIG_NFS_V4
232 ret = nfs_register_sysctl();
233 if (ret < 0)
234 goto error_1;
235 ret = register_filesystem(&nfs4_fs_type);
236 if (ret < 0)
237 goto error_2;
238#endif
239 return 0;
240
241#ifdef CONFIG_NFS_V4
242error_2:
243 nfs_unregister_sysctl();
244error_1:
245 unregister_filesystem(&nfs_fs_type);
246#endif
247error_0:
248 return ret;
249}
250
251/*
252 * Unregister the NFS filesystems
253 */
254void __exit unregister_nfs_fs(void)
255{
256#ifdef CONFIG_NFS_V4
257 unregister_filesystem(&nfs4_fs_type);
258 nfs_unregister_sysctl();
259#endif
260 unregister_filesystem(&nfs_fs_type);
261}
262
263/*
264 * Deliver file system statistics to userspace
265 */
266static int nfs_statfs(struct super_block *sb, struct kstatfs *buf)
267{
268 struct nfs_server *server = NFS_SB(sb);
269 unsigned char blockbits;
270 unsigned long blockres;
271 struct nfs_fh *rootfh = NFS_FH(sb->s_root->d_inode);
272 struct nfs_fattr fattr;
273 struct nfs_fsstat res = {
274 .fattr = &fattr,
275 };
276 int error;
277
278 lock_kernel();
279
280 error = server->rpc_ops->statfs(server, rootfh, &res);
281 buf->f_type = NFS_SUPER_MAGIC;
282 if (error < 0)
283 goto out_err;
284
285 /*
286 * Current versions of glibc do not correctly handle the
287 * case where f_frsize != f_bsize. Eventually we want to
288 * report the value of wtmult in this field.
289 */
290 buf->f_frsize = sb->s_blocksize;
291
292 /*
293 * On most *nix systems, f_blocks, f_bfree, and f_bavail
294 * are reported in units of f_frsize. Linux hasn't had
295 * an f_frsize field in its statfs struct until recently,
296 * thus historically Linux's sys_statfs reports these
297 * fields in units of f_bsize.
298 */
299 buf->f_bsize = sb->s_blocksize;
300 blockbits = sb->s_blocksize_bits;
301 blockres = (1 << blockbits) - 1;
302 buf->f_blocks = (res.tbytes + blockres) >> blockbits;
303 buf->f_bfree = (res.fbytes + blockres) >> blockbits;
304 buf->f_bavail = (res.abytes + blockres) >> blockbits;
305
306 buf->f_files = res.tfiles;
307 buf->f_ffree = res.afiles;
308
309 buf->f_namelen = server->namelen;
310 out:
311 unlock_kernel();
312 return 0;
313
314 out_err:
315 dprintk("%s: statfs error = %d\n", __FUNCTION__, -error);
316 buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1;
317 goto out;
318
319}
320
321/*
322 * Describe the mount options in force on this server representation
323 */
324static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, int showdefaults)
325{
326 static struct proc_nfs_info {
327 int flag;
328 char *str;
329 char *nostr;
330 } nfs_info[] = {
331 { NFS_MOUNT_SOFT, ",soft", ",hard" },
332 { NFS_MOUNT_INTR, ",intr", "" },
333 { NFS_MOUNT_NOCTO, ",nocto", "" },
334 { NFS_MOUNT_NOAC, ",noac", "" },
335 { NFS_MOUNT_NONLM, ",nolock", "" },
336 { NFS_MOUNT_NOACL, ",noacl", "" },
337 { 0, NULL, NULL }
338 };
339 struct proc_nfs_info *nfs_infop;
340 char buf[12];
341 char *proto;
342
343 seq_printf(m, ",vers=%d", nfss->rpc_ops->version);
344 seq_printf(m, ",rsize=%d", nfss->rsize);
345 seq_printf(m, ",wsize=%d", nfss->wsize);
346 if (nfss->acregmin != 3*HZ || showdefaults)
347 seq_printf(m, ",acregmin=%d", nfss->acregmin/HZ);
348 if (nfss->acregmax != 60*HZ || showdefaults)
349 seq_printf(m, ",acregmax=%d", nfss->acregmax/HZ);
350 if (nfss->acdirmin != 30*HZ || showdefaults)
351 seq_printf(m, ",acdirmin=%d", nfss->acdirmin/HZ);
352 if (nfss->acdirmax != 60*HZ || showdefaults)
353 seq_printf(m, ",acdirmax=%d", nfss->acdirmax/HZ);
354 for (nfs_infop = nfs_info; nfs_infop->flag; nfs_infop++) {
355 if (nfss->flags & nfs_infop->flag)
356 seq_puts(m, nfs_infop->str);
357 else
358 seq_puts(m, nfs_infop->nostr);
359 }
360 switch (nfss->client->cl_xprt->prot) {
361 case IPPROTO_TCP:
362 proto = "tcp";
363 break;
364 case IPPROTO_UDP:
365 proto = "udp";
366 break;
367 default:
368 snprintf(buf, sizeof(buf), "%u", nfss->client->cl_xprt->prot);
369 proto = buf;
370 }
371 seq_printf(m, ",proto=%s", proto);
372 seq_printf(m, ",timeo=%lu", 10U * nfss->retrans_timeo / HZ);
373 seq_printf(m, ",retrans=%u", nfss->retrans_count);
374}
375
376/*
377 * Describe the mount options on this VFS mountpoint
378 */
379static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt)
380{
381 struct nfs_server *nfss = NFS_SB(mnt->mnt_sb);
382
383 nfs_show_mount_options(m, nfss, 0);
384
385 seq_puts(m, ",addr=");
386 seq_escape(m, nfss->hostname, " \t\n\\");
387
388 return 0;
389}
390
391/*
392 * Present statistical information for this VFS mountpoint
393 */
394static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt)
395{
396 int i, cpu;
397 struct nfs_server *nfss = NFS_SB(mnt->mnt_sb);
398 struct rpc_auth *auth = nfss->client->cl_auth;
399 struct nfs_iostats totals = { };
400
401 seq_printf(m, "statvers=%s", NFS_IOSTAT_VERS);
402
403 /*
404 * Display all mount option settings
405 */
406 seq_printf(m, "\n\topts:\t");
407 seq_puts(m, mnt->mnt_sb->s_flags & MS_RDONLY ? "ro" : "rw");
408 seq_puts(m, mnt->mnt_sb->s_flags & MS_SYNCHRONOUS ? ",sync" : "");
409 seq_puts(m, mnt->mnt_sb->s_flags & MS_NOATIME ? ",noatime" : "");
410 seq_puts(m, mnt->mnt_sb->s_flags & MS_NODIRATIME ? ",nodiratime" : "");
411 nfs_show_mount_options(m, nfss, 1);
412
413 seq_printf(m, "\n\tage:\t%lu", (jiffies - nfss->mount_time) / HZ);
414
415 seq_printf(m, "\n\tcaps:\t");
416 seq_printf(m, "caps=0x%x", nfss->caps);
417 seq_printf(m, ",wtmult=%d", nfss->wtmult);
418 seq_printf(m, ",dtsize=%d", nfss->dtsize);
419 seq_printf(m, ",bsize=%d", nfss->bsize);
420 seq_printf(m, ",namelen=%d", nfss->namelen);
421
422#ifdef CONFIG_NFS_V4
423 if (nfss->rpc_ops->version == 4) {
424 seq_printf(m, "\n\tnfsv4:\t");
425 seq_printf(m, "bm0=0x%x", nfss->attr_bitmask[0]);
426 seq_printf(m, ",bm1=0x%x", nfss->attr_bitmask[1]);
427 seq_printf(m, ",acl=0x%x", nfss->acl_bitmask);
428 }
429#endif
430
431 /*
432 * Display security flavor in effect for this mount
433 */
434 seq_printf(m, "\n\tsec:\tflavor=%d", auth->au_ops->au_flavor);
435 if (auth->au_flavor)
436 seq_printf(m, ",pseudoflavor=%d", auth->au_flavor);
437
438 /*
439 * Display superblock I/O counters
440 */
441 for_each_possible_cpu(cpu) {
442 struct nfs_iostats *stats;
443
444 preempt_disable();
445 stats = per_cpu_ptr(nfss->io_stats, cpu);
446
447 for (i = 0; i < __NFSIOS_COUNTSMAX; i++)
448 totals.events[i] += stats->events[i];
449 for (i = 0; i < __NFSIOS_BYTESMAX; i++)
450 totals.bytes[i] += stats->bytes[i];
451
452 preempt_enable();
453 }
454
455 seq_printf(m, "\n\tevents:\t");
456 for (i = 0; i < __NFSIOS_COUNTSMAX; i++)
457 seq_printf(m, "%lu ", totals.events[i]);
458 seq_printf(m, "\n\tbytes:\t");
459 for (i = 0; i < __NFSIOS_BYTESMAX; i++)
460 seq_printf(m, "%Lu ", totals.bytes[i]);
461 seq_printf(m, "\n");
462
463 rpc_print_iostats(m, nfss->client);
464
465 return 0;
466}
467
468/*
469 * Begin unmount by attempting to remove all automounted mountpoints we added
470 * in response to traversals
471 */
472static void nfs_umount_begin(struct vfsmount *vfsmnt, int flags)
473{
474 struct nfs_server *server;
475 struct rpc_clnt *rpc;
476
477 shrink_submounts(vfsmnt, &nfs_automount_list);
478 if (!(flags & MNT_FORCE))
479 return;
480 /* -EIO all pending I/O */
481 server = NFS_SB(vfsmnt->mnt_sb);
482 rpc = server->client;
483 if (!IS_ERR(rpc))
484 rpc_killall_tasks(rpc);
485 rpc = server->client_acl;
486 if (!IS_ERR(rpc))
487 rpc_killall_tasks(rpc);
488}
489
490/*
491 * Obtain the root inode of the file system.
492 */
493static struct inode *
494nfs_get_root(struct super_block *sb, struct nfs_fh *rootfh, struct nfs_fsinfo *fsinfo)
495{
496 struct nfs_server *server = NFS_SB(sb);
497 int error;
498
499 error = server->rpc_ops->getroot(server, rootfh, fsinfo);
500 if (error < 0) {
501 dprintk("nfs_get_root: getattr error = %d\n", -error);
502 return ERR_PTR(error);
503 }
504
505 server->fsid = fsinfo->fattr->fsid;
506 return nfs_fhget(sb, rootfh, fsinfo->fattr);
507}
508
509/*
510 * Do NFS version-independent mount processing, and sanity checking
511 */
512static int
513nfs_sb_init(struct super_block *sb, rpc_authflavor_t authflavor)
514{
515 struct nfs_server *server;
516 struct inode *root_inode;
517 struct nfs_fattr fattr;
518 struct nfs_fsinfo fsinfo = {
519 .fattr = &fattr,
520 };
521 struct nfs_pathconf pathinfo = {
522 .fattr = &fattr,
523 };
524 int no_root_error = 0;
525 unsigned long max_rpc_payload;
526
527 /* We probably want something more informative here */
528 snprintf(sb->s_id, sizeof(sb->s_id), "%x:%x", MAJOR(sb->s_dev), MINOR(sb->s_dev));
529
530 server = NFS_SB(sb);
531
532 sb->s_magic = NFS_SUPER_MAGIC;
533
534 server->io_stats = nfs_alloc_iostats();
535 if (server->io_stats == NULL)
536 return -ENOMEM;
537
538 root_inode = nfs_get_root(sb, &server->fh, &fsinfo);
539 /* Did getting the root inode fail? */
540 if (IS_ERR(root_inode)) {
541 no_root_error = PTR_ERR(root_inode);
542 goto out_no_root;
543 }
544 sb->s_root = d_alloc_root(root_inode);
545 if (!sb->s_root) {
546 no_root_error = -ENOMEM;
547 goto out_no_root;
548 }
549 sb->s_root->d_op = server->rpc_ops->dentry_ops;
550
551 /* mount time stamp, in seconds */
552 server->mount_time = jiffies;
553
554 /* Get some general file system info */
555 if (server->namelen == 0 &&
556 server->rpc_ops->pathconf(server, &server->fh, &pathinfo) >= 0)
557 server->namelen = pathinfo.max_namelen;
558 /* Work out a lot of parameters */
559 if (server->rsize == 0)
560 server->rsize = nfs_block_size(fsinfo.rtpref, NULL);
561 if (server->wsize == 0)
562 server->wsize = nfs_block_size(fsinfo.wtpref, NULL);
563
564 if (fsinfo.rtmax >= 512 && server->rsize > fsinfo.rtmax)
565 server->rsize = nfs_block_size(fsinfo.rtmax, NULL);
566 if (fsinfo.wtmax >= 512 && server->wsize > fsinfo.wtmax)
567 server->wsize = nfs_block_size(fsinfo.wtmax, NULL);
568
569 max_rpc_payload = nfs_block_size(rpc_max_payload(server->client), NULL);
570 if (server->rsize > max_rpc_payload)
571 server->rsize = max_rpc_payload;
572 if (server->rsize > NFS_MAX_FILE_IO_SIZE)
573 server->rsize = NFS_MAX_FILE_IO_SIZE;
574 server->rpages = (server->rsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
575
576 if (server->wsize > max_rpc_payload)
577 server->wsize = max_rpc_payload;
578 if (server->wsize > NFS_MAX_FILE_IO_SIZE)
579 server->wsize = NFS_MAX_FILE_IO_SIZE;
580 server->wpages = (server->wsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
581
582 if (sb->s_blocksize == 0)
583 sb->s_blocksize = nfs_block_bits(server->wsize,
584 &sb->s_blocksize_bits);
585 server->wtmult = nfs_block_bits(fsinfo.wtmult, NULL);
586
587 server->dtsize = nfs_block_size(fsinfo.dtpref, NULL);
588 if (server->dtsize > PAGE_CACHE_SIZE)
589 server->dtsize = PAGE_CACHE_SIZE;
590 if (server->dtsize > server->rsize)
591 server->dtsize = server->rsize;
592
593 if (server->flags & NFS_MOUNT_NOAC) {
594 server->acregmin = server->acregmax = 0;
595 server->acdirmin = server->acdirmax = 0;
596 sb->s_flags |= MS_SYNCHRONOUS;
597 }
598 server->backing_dev_info.ra_pages = server->rpages * NFS_MAX_READAHEAD;
599
600 nfs_super_set_maxbytes(sb, fsinfo.maxfilesize);
601
602 server->client->cl_intr = (server->flags & NFS_MOUNT_INTR) ? 1 : 0;
603 server->client->cl_softrtry = (server->flags & NFS_MOUNT_SOFT) ? 1 : 0;
604
605 /* We're airborne Set socket buffersize */
606 rpc_setbufsize(server->client, server->wsize + 100, server->rsize + 100);
607 return 0;
608 /* Yargs. It didn't work out. */
609out_no_root:
610 dprintk("nfs_sb_init: get root inode failed: errno %d\n", -no_root_error);
611 if (!IS_ERR(root_inode))
612 iput(root_inode);
613 return no_root_error;
614}
615
616/*
617 * Initialise the timeout values for a connection
618 */
619static void nfs_init_timeout_values(struct rpc_timeout *to, int proto, unsigned int timeo, unsigned int retrans)
620{
621 to->to_initval = timeo * HZ / 10;
622 to->to_retries = retrans;
623 if (!to->to_retries)
624 to->to_retries = 2;
625
626 switch (proto) {
627 case IPPROTO_TCP:
628 if (!to->to_initval)
629 to->to_initval = 60 * HZ;
630 if (to->to_initval > NFS_MAX_TCP_TIMEOUT)
631 to->to_initval = NFS_MAX_TCP_TIMEOUT;
632 to->to_increment = to->to_initval;
633 to->to_maxval = to->to_initval + (to->to_increment * to->to_retries);
634 to->to_exponential = 0;
635 break;
636 case IPPROTO_UDP:
637 default:
638 if (!to->to_initval)
639 to->to_initval = 11 * HZ / 10;
640 if (to->to_initval > NFS_MAX_UDP_TIMEOUT)
641 to->to_initval = NFS_MAX_UDP_TIMEOUT;
642 to->to_maxval = NFS_MAX_UDP_TIMEOUT;
643 to->to_exponential = 1;
644 break;
645 }
646}
647
648/*
649 * Create an RPC client handle.
650 */
651static struct rpc_clnt *
652nfs_create_client(struct nfs_server *server, const struct nfs_mount_data *data)
653{
654 struct rpc_timeout timeparms;
655 struct rpc_xprt *xprt = NULL;
656 struct rpc_clnt *clnt = NULL;
657 int proto = (data->flags & NFS_MOUNT_TCP) ? IPPROTO_TCP : IPPROTO_UDP;
658
659 nfs_init_timeout_values(&timeparms, proto, data->timeo, data->retrans);
660
661 server->retrans_timeo = timeparms.to_initval;
662 server->retrans_count = timeparms.to_retries;
663
664 /* create transport and client */
665 xprt = xprt_create_proto(proto, &server->addr, &timeparms);
666 if (IS_ERR(xprt)) {
667 dprintk("%s: cannot create RPC transport. Error = %ld\n",
668 __FUNCTION__, PTR_ERR(xprt));
669 return (struct rpc_clnt *)xprt;
670 }
671 clnt = rpc_create_client(xprt, server->hostname, &nfs_program,
672 server->rpc_ops->version, data->pseudoflavor);
673 if (IS_ERR(clnt)) {
674 dprintk("%s: cannot create RPC client. Error = %ld\n",
675 __FUNCTION__, PTR_ERR(xprt));
676 goto out_fail;
677 }
678
679 clnt->cl_intr = 1;
680 clnt->cl_softrtry = 1;
681
682 return clnt;
683
684out_fail:
685 return clnt;
686}
687
688/*
689 * Clone a server record
690 */
691static struct nfs_server *nfs_clone_server(struct super_block *sb, struct nfs_clone_mount *data)
692{
693 struct nfs_server *server = NFS_SB(sb);
694 struct nfs_server *parent = NFS_SB(data->sb);
695 struct inode *root_inode;
696 struct nfs_fsinfo fsinfo;
697 void *err = ERR_PTR(-ENOMEM);
698
699 sb->s_op = data->sb->s_op;
700 sb->s_blocksize = data->sb->s_blocksize;
701 sb->s_blocksize_bits = data->sb->s_blocksize_bits;
702 sb->s_maxbytes = data->sb->s_maxbytes;
703
704 server->client_sys = server->client_acl = ERR_PTR(-EINVAL);
705 server->io_stats = nfs_alloc_iostats();
706 if (server->io_stats == NULL)
707 goto out;
708
709 server->client = rpc_clone_client(parent->client);
710 if (IS_ERR((err = server->client)))
711 goto out;
712
713 if (!IS_ERR(parent->client_sys)) {
714 server->client_sys = rpc_clone_client(parent->client_sys);
715 if (IS_ERR((err = server->client_sys)))
716 goto out;
717 }
718 if (!IS_ERR(parent->client_acl)) {
719 server->client_acl = rpc_clone_client(parent->client_acl);
720 if (IS_ERR((err = server->client_acl)))
721 goto out;
722 }
723 root_inode = nfs_fhget(sb, data->fh, data->fattr);
724 if (!root_inode)
725 goto out;
726 sb->s_root = d_alloc_root(root_inode);
727 if (!sb->s_root)
728 goto out_put_root;
729 fsinfo.fattr = data->fattr;
730 if (NFS_PROTO(root_inode)->fsinfo(server, data->fh, &fsinfo) == 0)
731 nfs_super_set_maxbytes(sb, fsinfo.maxfilesize);
732 sb->s_root->d_op = server->rpc_ops->dentry_ops;
733 sb->s_flags |= MS_ACTIVE;
734 return server;
735out_put_root:
736 iput(root_inode);
737out:
738 return err;
739}
740
741/*
742 * Copy an existing superblock and attach revised data
743 */
744static struct super_block *nfs_clone_generic_sb(struct nfs_clone_mount *data,
745 struct super_block *(*fill_sb)(struct nfs_server *, struct nfs_clone_mount *),
746 struct nfs_server *(*fill_server)(struct super_block *, struct nfs_clone_mount *))
747{
748 struct nfs_server *server;
749 struct nfs_server *parent = NFS_SB(data->sb);
750 struct super_block *sb = ERR_PTR(-EINVAL);
751 void *err = ERR_PTR(-ENOMEM);
752 char *hostname;
753 int len;
754
755 server = kmalloc(sizeof(struct nfs_server), GFP_KERNEL);
756 if (server == NULL)
757 goto out_err;
758 memcpy(server, parent, sizeof(*server));
759 hostname = (data->hostname != NULL) ? data->hostname : parent->hostname;
760 len = strlen(hostname) + 1;
761 server->hostname = kmalloc(len, GFP_KERNEL);
762 if (server->hostname == NULL)
763 goto free_server;
764 memcpy(server->hostname, hostname, len);
765 if (rpciod_up() != 0)
766 goto free_hostname;
767
768 sb = fill_sb(server, data);
769 if (IS_ERR((err = sb)) || sb->s_root)
770 goto kill_rpciod;
771
772 server = fill_server(sb, data);
773 if (IS_ERR((err = server)))
774 goto out_deactivate;
775 return sb;
776out_deactivate:
777 up_write(&sb->s_umount);
778 deactivate_super(sb);
779 return (struct super_block *)err;
780kill_rpciod:
781 rpciod_down();
782free_hostname:
783 kfree(server->hostname);
784free_server:
785 kfree(server);
786out_err:
787 return (struct super_block *)err;
788}
789
790/*
791 * Set up an NFS2/3 superblock
792 *
793 * The way this works is that the mount process passes a structure
794 * in the data argument which contains the server's IP address
795 * and the root file handle obtained from the server's mount
796 * daemon. We stash these away in the private superblock fields.
797 */
798static int
799nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data, int silent)
800{
801 struct nfs_server *server;
802 rpc_authflavor_t authflavor;
803
804 server = NFS_SB(sb);
805 sb->s_blocksize_bits = 0;
806 sb->s_blocksize = 0;
807 if (data->bsize)
808 sb->s_blocksize = nfs_block_size(data->bsize, &sb->s_blocksize_bits);
809 if (data->rsize)
810 server->rsize = nfs_block_size(data->rsize, NULL);
811 if (data->wsize)
812 server->wsize = nfs_block_size(data->wsize, NULL);
813 server->flags = data->flags & NFS_MOUNT_FLAGMASK;
814
815 server->acregmin = data->acregmin*HZ;
816 server->acregmax = data->acregmax*HZ;
817 server->acdirmin = data->acdirmin*HZ;
818 server->acdirmax = data->acdirmax*HZ;
819
820 /* Start lockd here, before we might error out */
821 if (!(server->flags & NFS_MOUNT_NONLM))
822 lockd_up();
823
824 server->namelen = data->namlen;
825 server->hostname = kmalloc(strlen(data->hostname) + 1, GFP_KERNEL);
826 if (!server->hostname)
827 return -ENOMEM;
828 strcpy(server->hostname, data->hostname);
829
830 /* Check NFS protocol revision and initialize RPC op vector
831 * and file handle pool. */
832#ifdef CONFIG_NFS_V3
833 if (server->flags & NFS_MOUNT_VER3) {
834 server->rpc_ops = &nfs_v3_clientops;
835 server->caps |= NFS_CAP_READDIRPLUS;
836 } else {
837 server->rpc_ops = &nfs_v2_clientops;
838 }
839#else
840 server->rpc_ops = &nfs_v2_clientops;
841#endif
842
843 /* Fill in pseudoflavor for mount version < 5 */
844 if (!(data->flags & NFS_MOUNT_SECFLAVOUR))
845 data->pseudoflavor = RPC_AUTH_UNIX;
846 authflavor = data->pseudoflavor; /* save for sb_init() */
847 /* XXX maybe we want to add a server->pseudoflavor field */
848
849 /* Create RPC client handles */
850 server->client = nfs_create_client(server, data);
851 if (IS_ERR(server->client))
852 return PTR_ERR(server->client);
853 /* RFC 2623, sec 2.3.2 */
854 if (authflavor != RPC_AUTH_UNIX) {
855 struct rpc_auth *auth;
856
857 server->client_sys = rpc_clone_client(server->client);
858 if (IS_ERR(server->client_sys))
859 return PTR_ERR(server->client_sys);
860 auth = rpcauth_create(RPC_AUTH_UNIX, server->client_sys);
861 if (IS_ERR(auth))
862 return PTR_ERR(auth);
863 } else {
864 atomic_inc(&server->client->cl_count);
865 server->client_sys = server->client;
866 }
867 if (server->flags & NFS_MOUNT_VER3) {
868#ifdef CONFIG_NFS_V3_ACL
869 if (!(server->flags & NFS_MOUNT_NOACL)) {
870 server->client_acl = rpc_bind_new_program(server->client, &nfsacl_program, 3);
871 /* No errors! Assume that Sun nfsacls are supported */
872 if (!IS_ERR(server->client_acl))
873 server->caps |= NFS_CAP_ACLS;
874 }
875#else
876 server->flags &= ~NFS_MOUNT_NOACL;
877#endif /* CONFIG_NFS_V3_ACL */
878 /*
879 * The VFS shouldn't apply the umask to mode bits. We will
880 * do so ourselves when necessary.
881 */
882 sb->s_flags |= MS_POSIXACL;
883 if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN)
884 server->namelen = NFS3_MAXNAMLEN;
885 sb->s_time_gran = 1;
886 } else {
887 if (server->namelen == 0 || server->namelen > NFS2_MAXNAMLEN)
888 server->namelen = NFS2_MAXNAMLEN;
889 }
890
891 sb->s_op = &nfs_sops;
892 return nfs_sb_init(sb, authflavor);
893}
894
895static int nfs_set_super(struct super_block *s, void *data)
896{
897 s->s_fs_info = data;
898 return set_anon_super(s, data);
899}
900
901static int nfs_compare_super(struct super_block *sb, void *data)
902{
903 struct nfs_server *server = data;
904 struct nfs_server *old = NFS_SB(sb);
905
906 if (old->addr.sin_addr.s_addr != server->addr.sin_addr.s_addr)
907 return 0;
908 if (old->addr.sin_port != server->addr.sin_port)
909 return 0;
910 return !nfs_compare_fh(&old->fh, &server->fh);
911}
912
913static struct super_block *nfs_get_sb(struct file_system_type *fs_type,
914 int flags, const char *dev_name, void *raw_data)
915{
916 int error;
917 struct nfs_server *server = NULL;
918 struct super_block *s;
919 struct nfs_fh *root;
920 struct nfs_mount_data *data = raw_data;
921
922 s = ERR_PTR(-EINVAL);
923 if (data == NULL) {
924 dprintk("%s: missing data argument\n", __FUNCTION__);
925 goto out_err;
926 }
927 if (data->version <= 0 || data->version > NFS_MOUNT_VERSION) {
928 dprintk("%s: bad mount version\n", __FUNCTION__);
929 goto out_err;
930 }
931 switch (data->version) {
932 case 1:
933 data->namlen = 0;
934 case 2:
935 data->bsize = 0;
936 case 3:
937 if (data->flags & NFS_MOUNT_VER3) {
938 dprintk("%s: mount structure version %d does not support NFSv3\n",
939 __FUNCTION__,
940 data->version);
941 goto out_err;
942 }
943 data->root.size = NFS2_FHSIZE;
944 memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE);
945 case 4:
946 if (data->flags & NFS_MOUNT_SECFLAVOUR) {
947 dprintk("%s: mount structure version %d does not support strong security\n",
948 __FUNCTION__,
949 data->version);
950 goto out_err;
951 }
952 case 5:
953 memset(data->context, 0, sizeof(data->context));
954 }
955#ifndef CONFIG_NFS_V3
956 /* If NFSv3 is not compiled in, return -EPROTONOSUPPORT */
957 s = ERR_PTR(-EPROTONOSUPPORT);
958 if (data->flags & NFS_MOUNT_VER3) {
959 dprintk("%s: NFSv3 not compiled into kernel\n", __FUNCTION__);
960 goto out_err;
961 }
962#endif /* CONFIG_NFS_V3 */
963
964 s = ERR_PTR(-ENOMEM);
965 server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL);
966 if (!server)
967 goto out_err;
968 /* Zero out the NFS state stuff */
969 init_nfsv4_state(server);
970 server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL);
971
972 root = &server->fh;
973 if (data->flags & NFS_MOUNT_VER3)
974 root->size = data->root.size;
975 else
976 root->size = NFS2_FHSIZE;
977 s = ERR_PTR(-EINVAL);
978 if (root->size > sizeof(root->data)) {
979 dprintk("%s: invalid root filehandle\n", __FUNCTION__);
980 goto out_err;
981 }
982 memcpy(root->data, data->root.data, root->size);
983
984 /* We now require that the mount process passes the remote address */
985 memcpy(&server->addr, &data->addr, sizeof(server->addr));
986 if (server->addr.sin_addr.s_addr == INADDR_ANY) {
987 dprintk("%s: mount program didn't pass remote address!\n",
988 __FUNCTION__);
989 goto out_err;
990 }
991
992 /* Fire up rpciod if not yet running */
993 s = ERR_PTR(rpciod_up());
994 if (IS_ERR(s)) {
995 dprintk("%s: couldn't start rpciod! Error = %ld\n",
996 __FUNCTION__, PTR_ERR(s));
997 goto out_err;
998 }
999
1000 s = sget(fs_type, nfs_compare_super, nfs_set_super, server);
1001 if (IS_ERR(s) || s->s_root)
1002 goto out_rpciod_down;
1003
1004 s->s_flags = flags;
1005
1006 error = nfs_fill_super(s, data, flags & MS_SILENT ? 1 : 0);
1007 if (error) {
1008 up_write(&s->s_umount);
1009 deactivate_super(s);
1010 return ERR_PTR(error);
1011 }
1012 s->s_flags |= MS_ACTIVE;
1013 return s;
1014out_rpciod_down:
1015 rpciod_down();
1016out_err:
1017 kfree(server);
1018 return s;
1019}
1020
1021static void nfs_kill_super(struct super_block *s)
1022{
1023 struct nfs_server *server = NFS_SB(s);
1024
1025 kill_anon_super(s);
1026
1027 if (!IS_ERR(server->client))
1028 rpc_shutdown_client(server->client);
1029 if (!IS_ERR(server->client_sys))
1030 rpc_shutdown_client(server->client_sys);
1031 if (!IS_ERR(server->client_acl))
1032 rpc_shutdown_client(server->client_acl);
1033
1034 if (!(server->flags & NFS_MOUNT_NONLM))
1035 lockd_down(); /* release rpc.lockd */
1036
1037 rpciod_down(); /* release rpciod */
1038
1039 nfs_free_iostats(server->io_stats);
1040 kfree(server->hostname);
1041 kfree(server);
1042 nfs_release_automount_timer();
1043}
1044
1045static struct super_block *nfs_clone_sb(struct nfs_server *server, struct nfs_clone_mount *data)
1046{
1047 struct super_block *sb;
1048
1049 server->fsid = data->fattr->fsid;
1050 nfs_copy_fh(&server->fh, data->fh);
1051 sb = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server);
1052 if (!IS_ERR(sb) && sb->s_root == NULL && !(server->flags & NFS_MOUNT_NONLM))
1053 lockd_up();
1054 return sb;
1055}
1056
1057static struct super_block *nfs_clone_nfs_sb(struct file_system_type *fs_type,
1058 int flags, const char *dev_name, void *raw_data)
1059{
1060 struct nfs_clone_mount *data = raw_data;
1061 return nfs_clone_generic_sb(data, nfs_clone_sb, nfs_clone_server);
1062}
1063
1064#ifdef CONFIG_NFS_V4
1065static struct rpc_clnt *nfs4_create_client(struct nfs_server *server,
1066 struct rpc_timeout *timeparms, int proto, rpc_authflavor_t flavor)
1067{
1068 struct nfs4_client *clp;
1069 struct rpc_xprt *xprt = NULL;
1070 struct rpc_clnt *clnt = NULL;
1071 int err = -EIO;
1072
1073 clp = nfs4_get_client(&server->addr.sin_addr);
1074 if (!clp) {
1075 dprintk("%s: failed to create NFS4 client.\n", __FUNCTION__);
1076 return ERR_PTR(err);
1077 }
1078
1079 /* Now create transport and client */
1080 down_write(&clp->cl_sem);
1081 if (IS_ERR(clp->cl_rpcclient)) {
1082 xprt = xprt_create_proto(proto, &server->addr, timeparms);
1083 if (IS_ERR(xprt)) {
1084 up_write(&clp->cl_sem);
1085 err = PTR_ERR(xprt);
1086 dprintk("%s: cannot create RPC transport. Error = %d\n",
1087 __FUNCTION__, err);
1088 goto out_fail;
1089 }
1090 /* Bind to a reserved port! */
1091 xprt->resvport = 1;
1092 clnt = rpc_create_client(xprt, server->hostname, &nfs_program,
1093 server->rpc_ops->version, flavor);
1094 if (IS_ERR(clnt)) {
1095 up_write(&clp->cl_sem);
1096 err = PTR_ERR(clnt);
1097 dprintk("%s: cannot create RPC client. Error = %d\n",
1098 __FUNCTION__, err);
1099 goto out_fail;
1100 }
1101 clnt->cl_intr = 1;
1102 clnt->cl_softrtry = 1;
1103 clp->cl_rpcclient = clnt;
1104 memcpy(clp->cl_ipaddr, server->ip_addr, sizeof(clp->cl_ipaddr));
1105 nfs_idmap_new(clp);
1106 }
1107 list_add_tail(&server->nfs4_siblings, &clp->cl_superblocks);
1108 clnt = rpc_clone_client(clp->cl_rpcclient);
1109 if (!IS_ERR(clnt))
1110 server->nfs4_state = clp;
1111 up_write(&clp->cl_sem);
1112 clp = NULL;
1113
1114 if (IS_ERR(clnt)) {
1115 dprintk("%s: cannot create RPC client. Error = %d\n",
1116 __FUNCTION__, err);
1117 return clnt;
1118 }
1119
1120 if (server->nfs4_state->cl_idmap == NULL) {
1121 dprintk("%s: failed to create idmapper.\n", __FUNCTION__);
1122 return ERR_PTR(-ENOMEM);
1123 }
1124
1125 if (clnt->cl_auth->au_flavor != flavor) {
1126 struct rpc_auth *auth;
1127
1128 auth = rpcauth_create(flavor, clnt);
1129 if (IS_ERR(auth)) {
1130 dprintk("%s: couldn't create credcache!\n", __FUNCTION__);
1131 return (struct rpc_clnt *)auth;
1132 }
1133 }
1134 return clnt;
1135
1136 out_fail:
1137 if (clp)
1138 nfs4_put_client(clp);
1139 return ERR_PTR(err);
1140}
1141
1142/*
1143 * Set up an NFS4 superblock
1144 */
1145static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data, int silent)
1146{
1147 struct nfs_server *server;
1148 struct rpc_timeout timeparms;
1149 rpc_authflavor_t authflavour;
1150 int err = -EIO;
1151
1152 sb->s_blocksize_bits = 0;
1153 sb->s_blocksize = 0;
1154 server = NFS_SB(sb);
1155 if (data->rsize != 0)
1156 server->rsize = nfs_block_size(data->rsize, NULL);
1157 if (data->wsize != 0)
1158 server->wsize = nfs_block_size(data->wsize, NULL);
1159 server->flags = data->flags & NFS_MOUNT_FLAGMASK;
1160 server->caps = NFS_CAP_ATOMIC_OPEN;
1161
1162 server->acregmin = data->acregmin*HZ;
1163 server->acregmax = data->acregmax*HZ;
1164 server->acdirmin = data->acdirmin*HZ;
1165 server->acdirmax = data->acdirmax*HZ;
1166
1167 server->rpc_ops = &nfs_v4_clientops;
1168
1169 nfs_init_timeout_values(&timeparms, data->proto, data->timeo, data->retrans);
1170
1171 server->retrans_timeo = timeparms.to_initval;
1172 server->retrans_count = timeparms.to_retries;
1173
1174 /* Now create transport and client */
1175 authflavour = RPC_AUTH_UNIX;
1176 if (data->auth_flavourlen != 0) {
1177 if (data->auth_flavourlen != 1) {
1178 dprintk("%s: Invalid number of RPC auth flavours %d.\n",
1179 __FUNCTION__, data->auth_flavourlen);
1180 err = -EINVAL;
1181 goto out_fail;
1182 }
1183 if (copy_from_user(&authflavour, data->auth_flavours, sizeof(authflavour))) {
1184 err = -EFAULT;
1185 goto out_fail;
1186 }
1187 }
1188
1189 server->client = nfs4_create_client(server, &timeparms, data->proto, authflavour);
1190 if (IS_ERR(server->client)) {
1191 err = PTR_ERR(server->client);
1192 dprintk("%s: cannot create RPC client. Error = %d\n",
1193 __FUNCTION__, err);
1194 goto out_fail;
1195 }
1196
1197 sb->s_time_gran = 1;
1198
1199 sb->s_op = &nfs4_sops;
1200 err = nfs_sb_init(sb, authflavour);
1201
1202 out_fail:
1203 return err;
1204}
1205
1206static int nfs4_compare_super(struct super_block *sb, void *data)
1207{
1208 struct nfs_server *server = data;
1209 struct nfs_server *old = NFS_SB(sb);
1210
1211 if (strcmp(server->hostname, old->hostname) != 0)
1212 return 0;
1213 if (strcmp(server->mnt_path, old->mnt_path) != 0)
1214 return 0;
1215 return 1;
1216}
1217
1218static void *
1219nfs_copy_user_string(char *dst, struct nfs_string *src, int maxlen)
1220{
1221 void *p = NULL;
1222
1223 if (!src->len)
1224 return ERR_PTR(-EINVAL);
1225 if (src->len < maxlen)
1226 maxlen = src->len;
1227 if (dst == NULL) {
1228 p = dst = kmalloc(maxlen + 1, GFP_KERNEL);
1229 if (p == NULL)
1230 return ERR_PTR(-ENOMEM);
1231 }
1232 if (copy_from_user(dst, src->data, maxlen)) {
1233 kfree(p);
1234 return ERR_PTR(-EFAULT);
1235 }
1236 dst[maxlen] = '\0';
1237 return dst;
1238}
1239
1240static struct super_block *nfs4_get_sb(struct file_system_type *fs_type,
1241 int flags, const char *dev_name, void *raw_data)
1242{
1243 int error;
1244 struct nfs_server *server;
1245 struct super_block *s;
1246 struct nfs4_mount_data *data = raw_data;
1247 void *p;
1248
1249 if (data == NULL) {
1250 dprintk("%s: missing data argument\n", __FUNCTION__);
1251 return ERR_PTR(-EINVAL);
1252 }
1253 if (data->version <= 0 || data->version > NFS4_MOUNT_VERSION) {
1254 dprintk("%s: bad mount version\n", __FUNCTION__);
1255 return ERR_PTR(-EINVAL);
1256 }
1257
1258 server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL);
1259 if (!server)
1260 return ERR_PTR(-ENOMEM);
1261 /* Zero out the NFS state stuff */
1262 init_nfsv4_state(server);
1263 server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL);
1264
1265 p = nfs_copy_user_string(NULL, &data->hostname, 256);
1266 if (IS_ERR(p))
1267 goto out_err;
1268 server->hostname = p;
1269
1270 p = nfs_copy_user_string(NULL, &data->mnt_path, 1024);
1271 if (IS_ERR(p))
1272 goto out_err;
1273 server->mnt_path = p;
1274
1275 p = nfs_copy_user_string(server->ip_addr, &data->client_addr,
1276 sizeof(server->ip_addr) - 1);
1277 if (IS_ERR(p))
1278 goto out_err;
1279
1280 /* We now require that the mount process passes the remote address */
1281 if (data->host_addrlen != sizeof(server->addr)) {
1282 s = ERR_PTR(-EINVAL);
1283 goto out_free;
1284 }
1285 if (copy_from_user(&server->addr, data->host_addr, sizeof(server->addr))) {
1286 s = ERR_PTR(-EFAULT);
1287 goto out_free;
1288 }
1289 if (server->addr.sin_family != AF_INET ||
1290 server->addr.sin_addr.s_addr == INADDR_ANY) {
1291 dprintk("%s: mount program didn't pass remote IP address!\n",
1292 __FUNCTION__);
1293 s = ERR_PTR(-EINVAL);
1294 goto out_free;
1295 }
1296
1297 /* Fire up rpciod if not yet running */
1298 s = ERR_PTR(rpciod_up());
1299 if (IS_ERR(s)) {
1300 dprintk("%s: couldn't start rpciod! Error = %ld\n",
1301 __FUNCTION__, PTR_ERR(s));
1302 goto out_free;
1303 }
1304
1305 s = sget(fs_type, nfs4_compare_super, nfs_set_super, server);
1306
1307 if (IS_ERR(s) || s->s_root)
1308 goto out_free;
1309
1310 s->s_flags = flags;
1311
1312 error = nfs4_fill_super(s, data, flags & MS_SILENT ? 1 : 0);
1313 if (error) {
1314 up_write(&s->s_umount);
1315 deactivate_super(s);
1316 return ERR_PTR(error);
1317 }
1318 s->s_flags |= MS_ACTIVE;
1319 return s;
1320out_err:
1321 s = (struct super_block *)p;
1322out_free:
1323 kfree(server->mnt_path);
1324 kfree(server->hostname);
1325 kfree(server);
1326 return s;
1327}
1328
1329static void nfs4_kill_super(struct super_block *sb)
1330{
1331 struct nfs_server *server = NFS_SB(sb);
1332
1333 nfs_return_all_delegations(sb);
1334 kill_anon_super(sb);
1335
1336 nfs4_renewd_prepare_shutdown(server);
1337
1338 if (server->client != NULL && !IS_ERR(server->client))
1339 rpc_shutdown_client(server->client);
1340
1341 destroy_nfsv4_state(server);
1342
1343 rpciod_down();
1344
1345 nfs_free_iostats(server->io_stats);
1346 kfree(server->hostname);
1347 kfree(server);
1348 nfs_release_automount_timer();
1349}
1350
1351/*
1352 * Constructs the SERVER-side path
1353 */
1354static inline char *nfs4_dup_path(const struct dentry *dentry)
1355{
1356 char *page = (char *) __get_free_page(GFP_USER);
1357 char *path;
1358
1359 path = nfs4_path(dentry, page, PAGE_SIZE);
1360 if (!IS_ERR(path)) {
1361 int len = PAGE_SIZE + page - path;
1362 char *tmp = path;
1363
1364 path = kmalloc(len, GFP_KERNEL);
1365 if (path)
1366 memcpy(path, tmp, len);
1367 else
1368 path = ERR_PTR(-ENOMEM);
1369 }
1370 free_page((unsigned long)page);
1371 return path;
1372}
1373
1374static struct super_block *nfs4_clone_sb(struct nfs_server *server, struct nfs_clone_mount *data)
1375{
1376 const struct dentry *dentry = data->dentry;
1377 struct nfs4_client *clp = server->nfs4_state;
1378 struct super_block *sb;
1379
1380 server->fsid = data->fattr->fsid;
1381 nfs_copy_fh(&server->fh, data->fh);
1382 server->mnt_path = nfs4_dup_path(dentry);
1383 if (IS_ERR(server->mnt_path)) {
1384 sb = (struct super_block *)server->mnt_path;
1385 goto err;
1386 }
1387 sb = sget(&nfs4_fs_type, nfs4_compare_super, nfs_set_super, server);
1388 if (IS_ERR(sb) || sb->s_root)
1389 goto free_path;
1390 nfs4_server_capabilities(server, &server->fh);
1391
1392 down_write(&clp->cl_sem);
1393 atomic_inc(&clp->cl_count);
1394 list_add_tail(&server->nfs4_siblings, &clp->cl_superblocks);
1395 up_write(&clp->cl_sem);
1396 return sb;
1397free_path:
1398 kfree(server->mnt_path);
1399err:
1400 server->mnt_path = NULL;
1401 return sb;
1402}
1403
1404static struct super_block *nfs_clone_nfs4_sb(struct file_system_type *fs_type,
1405 int flags, const char *dev_name, void *raw_data)
1406{
1407 struct nfs_clone_mount *data = raw_data;
1408 return nfs_clone_generic_sb(data, nfs4_clone_sb, nfs_clone_server);
1409}
1410
1411static struct super_block *nfs4_referral_sb(struct nfs_server *server, struct nfs_clone_mount *data)
1412{
1413 struct super_block *sb = ERR_PTR(-ENOMEM);
1414 int len;
1415
1416 len = strlen(data->mnt_path) + 1;
1417 server->mnt_path = kmalloc(len, GFP_KERNEL);
1418 if (server->mnt_path == NULL)
1419 goto err;
1420 memcpy(server->mnt_path, data->mnt_path, len);
1421 memcpy(&server->addr, data->addr, sizeof(struct sockaddr_in));
1422
1423 sb = sget(&nfs4_fs_type, nfs4_compare_super, nfs_set_super, server);
1424 if (IS_ERR(sb) || sb->s_root)
1425 goto free_path;
1426 return sb;
1427free_path:
1428 kfree(server->mnt_path);
1429err:
1430 server->mnt_path = NULL;
1431 return sb;
1432}
1433
1434static struct nfs_server *nfs4_referral_server(struct super_block *sb, struct nfs_clone_mount *data)
1435{
1436 struct nfs_server *server = NFS_SB(sb);
1437 struct rpc_timeout timeparms;
1438 int proto, timeo, retrans;
1439 void *err;
1440
1441 proto = IPPROTO_TCP;
1442 /* Since we are following a referral and there may be alternatives,
1443 set the timeouts and retries to low values */
1444 timeo = 2;
1445 retrans = 1;
1446 nfs_init_timeout_values(&timeparms, proto, timeo, retrans);
1447
1448 server->client = nfs4_create_client(server, &timeparms, proto, data->authflavor);
1449 if (IS_ERR((err = server->client)))
1450 goto out_err;
1451
1452 sb->s_time_gran = 1;
1453 sb->s_op = &nfs4_sops;
1454 err = ERR_PTR(nfs_sb_init(sb, data->authflavor));
1455 if (!IS_ERR(err))
1456 return server;
1457out_err:
1458 return (struct nfs_server *)err;
1459}
1460
1461static struct super_block *nfs_referral_nfs4_sb(struct file_system_type *fs_type,
1462 int flags, const char *dev_name, void *raw_data)
1463{
1464 struct nfs_clone_mount *data = raw_data;
1465 return nfs_clone_generic_sb(data, nfs4_referral_sb, nfs4_referral_server);
1466}
1467
1468#endif