]> bbs.cooldavid.org Git - net-next-2.6.git/blame - fs/nfs/super.c
NFS: Add dentry materialisation op
[net-next-2.6.git] / fs / nfs / super.c
CommitLineData
f7b422b1
DH
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);
816724e6 110static int nfs_statfs(struct dentry *, struct kstatfs *);
f7b422b1
DH
111static int nfs_show_options(struct seq_file *, struct vfsmount *);
112static int nfs_show_stats(struct seq_file *, struct vfsmount *);
816724e6
TM
113static int nfs_get_sb(struct file_system_type *, int, const char *, void *, struct vfsmount *);
114static int nfs_clone_nfs_sb(struct file_system_type *fs_type,
115 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);
f7b422b1
DH
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
816724e6
TM
146static int nfs4_get_sb(struct file_system_type *fs_type,
147 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);
148static int nfs_clone_nfs4_sb(struct file_system_type *fs_type,
149 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);
150static int nfs_referral_nfs4_sb(struct file_system_type *fs_type,
151 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);
f7b422b1
DH
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
6ab86aa1 190#ifdef CONFIG_NFS_V4
f7b422b1
DH
191static const int nfs_set_port_min = 0;
192static const int nfs_set_port_max = 65535;
193
194static int param_set_port(const char *val, struct kernel_param *kp)
195{
196 char *endp;
197 int num = simple_strtol(val, &endp, 0);
198 if (endp == val || *endp || num < nfs_set_port_min || num > nfs_set_port_max)
199 return -EINVAL;
200 *((int *)kp->arg) = num;
201 return 0;
202}
203
204module_param_call(callback_tcpport, param_set_port, param_get_int,
205 &nfs_callback_set_tcpport, 0644);
6ab86aa1 206#endif
f7b422b1 207
6ab86aa1 208#ifdef CONFIG_NFS_V4
f7b422b1
DH
209static int param_set_idmap_timeout(const char *val, struct kernel_param *kp)
210{
211 char *endp;
212 int num = simple_strtol(val, &endp, 0);
213 int jif = num * HZ;
214 if (endp == val || *endp || num < 0 || jif < num)
215 return -EINVAL;
216 *((int *)kp->arg) = jif;
217 return 0;
218}
219
220module_param_call(idmap_cache_timeout, param_set_idmap_timeout, param_get_int,
221 &nfs_idmap_cache_timeout, 0644);
6ab86aa1 222#endif
f7b422b1 223
979df72e
TM
224static struct shrinker *acl_shrinker;
225
f7b422b1
DH
226/*
227 * Register the NFS filesystems
228 */
229int __init register_nfs_fs(void)
230{
231 int ret;
232
233 ret = register_filesystem(&nfs_fs_type);
234 if (ret < 0)
235 goto error_0;
236
237#ifdef CONFIG_NFS_V4
238 ret = nfs_register_sysctl();
239 if (ret < 0)
240 goto error_1;
241 ret = register_filesystem(&nfs4_fs_type);
242 if (ret < 0)
243 goto error_2;
244#endif
979df72e 245 acl_shrinker = set_shrinker(DEFAULT_SEEKS, nfs_access_cache_shrinker);
f7b422b1
DH
246 return 0;
247
248#ifdef CONFIG_NFS_V4
249error_2:
250 nfs_unregister_sysctl();
251error_1:
252 unregister_filesystem(&nfs_fs_type);
253#endif
254error_0:
255 return ret;
256}
257
258/*
259 * Unregister the NFS filesystems
260 */
261void __exit unregister_nfs_fs(void)
262{
979df72e
TM
263 if (acl_shrinker != NULL)
264 remove_shrinker(acl_shrinker);
f7b422b1
DH
265#ifdef CONFIG_NFS_V4
266 unregister_filesystem(&nfs4_fs_type);
267 nfs_unregister_sysctl();
268#endif
269 unregister_filesystem(&nfs_fs_type);
270}
271
272/*
273 * Deliver file system statistics to userspace
274 */
816724e6 275static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf)
f7b422b1 276{
816724e6 277 struct super_block *sb = dentry->d_sb;
f7b422b1
DH
278 struct nfs_server *server = NFS_SB(sb);
279 unsigned char blockbits;
280 unsigned long blockres;
281 struct nfs_fh *rootfh = NFS_FH(sb->s_root->d_inode);
282 struct nfs_fattr fattr;
283 struct nfs_fsstat res = {
284 .fattr = &fattr,
285 };
286 int error;
287
288 lock_kernel();
289
290 error = server->rpc_ops->statfs(server, rootfh, &res);
291 buf->f_type = NFS_SUPER_MAGIC;
292 if (error < 0)
293 goto out_err;
294
295 /*
296 * Current versions of glibc do not correctly handle the
297 * case where f_frsize != f_bsize. Eventually we want to
298 * report the value of wtmult in this field.
299 */
300 buf->f_frsize = sb->s_blocksize;
301
302 /*
303 * On most *nix systems, f_blocks, f_bfree, and f_bavail
304 * are reported in units of f_frsize. Linux hasn't had
305 * an f_frsize field in its statfs struct until recently,
306 * thus historically Linux's sys_statfs reports these
307 * fields in units of f_bsize.
308 */
309 buf->f_bsize = sb->s_blocksize;
310 blockbits = sb->s_blocksize_bits;
311 blockres = (1 << blockbits) - 1;
312 buf->f_blocks = (res.tbytes + blockres) >> blockbits;
313 buf->f_bfree = (res.fbytes + blockres) >> blockbits;
314 buf->f_bavail = (res.abytes + blockres) >> blockbits;
315
316 buf->f_files = res.tfiles;
317 buf->f_ffree = res.afiles;
318
319 buf->f_namelen = server->namelen;
320 out:
321 unlock_kernel();
322 return 0;
323
324 out_err:
325 dprintk("%s: statfs error = %d\n", __FUNCTION__, -error);
326 buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1;
327 goto out;
328
329}
330
81039f1f
TM
331static const char *nfs_pseudoflavour_to_name(rpc_authflavor_t flavour)
332{
333 static struct {
334 rpc_authflavor_t flavour;
335 const char *str;
336 } sec_flavours[] = {
337 { RPC_AUTH_NULL, "null" },
338 { RPC_AUTH_UNIX, "sys" },
339 { RPC_AUTH_GSS_KRB5, "krb5" },
340 { RPC_AUTH_GSS_KRB5I, "krb5i" },
341 { RPC_AUTH_GSS_KRB5P, "krb5p" },
342 { RPC_AUTH_GSS_LKEY, "lkey" },
343 { RPC_AUTH_GSS_LKEYI, "lkeyi" },
344 { RPC_AUTH_GSS_LKEYP, "lkeyp" },
345 { RPC_AUTH_GSS_SPKM, "spkm" },
346 { RPC_AUTH_GSS_SPKMI, "spkmi" },
347 { RPC_AUTH_GSS_SPKMP, "spkmp" },
348 { -1, "unknown" }
349 };
350 int i;
351
352 for (i=0; sec_flavours[i].flavour != -1; i++) {
353 if (sec_flavours[i].flavour == flavour)
354 break;
355 }
356 return sec_flavours[i].str;
357}
358
f7b422b1
DH
359/*
360 * Describe the mount options in force on this server representation
361 */
362static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, int showdefaults)
363{
364 static struct proc_nfs_info {
365 int flag;
366 char *str;
367 char *nostr;
368 } nfs_info[] = {
369 { NFS_MOUNT_SOFT, ",soft", ",hard" },
370 { NFS_MOUNT_INTR, ",intr", "" },
371 { NFS_MOUNT_NOCTO, ",nocto", "" },
372 { NFS_MOUNT_NOAC, ",noac", "" },
373 { NFS_MOUNT_NONLM, ",nolock", "" },
374 { NFS_MOUNT_NOACL, ",noacl", "" },
375 { 0, NULL, NULL }
376 };
377 struct proc_nfs_info *nfs_infop;
378 char buf[12];
379 char *proto;
380
381 seq_printf(m, ",vers=%d", nfss->rpc_ops->version);
382 seq_printf(m, ",rsize=%d", nfss->rsize);
383 seq_printf(m, ",wsize=%d", nfss->wsize);
384 if (nfss->acregmin != 3*HZ || showdefaults)
385 seq_printf(m, ",acregmin=%d", nfss->acregmin/HZ);
386 if (nfss->acregmax != 60*HZ || showdefaults)
387 seq_printf(m, ",acregmax=%d", nfss->acregmax/HZ);
388 if (nfss->acdirmin != 30*HZ || showdefaults)
389 seq_printf(m, ",acdirmin=%d", nfss->acdirmin/HZ);
390 if (nfss->acdirmax != 60*HZ || showdefaults)
391 seq_printf(m, ",acdirmax=%d", nfss->acdirmax/HZ);
392 for (nfs_infop = nfs_info; nfs_infop->flag; nfs_infop++) {
393 if (nfss->flags & nfs_infop->flag)
394 seq_puts(m, nfs_infop->str);
395 else
396 seq_puts(m, nfs_infop->nostr);
397 }
398 switch (nfss->client->cl_xprt->prot) {
399 case IPPROTO_TCP:
400 proto = "tcp";
401 break;
402 case IPPROTO_UDP:
403 proto = "udp";
404 break;
405 default:
406 snprintf(buf, sizeof(buf), "%u", nfss->client->cl_xprt->prot);
407 proto = buf;
408 }
409 seq_printf(m, ",proto=%s", proto);
410 seq_printf(m, ",timeo=%lu", 10U * nfss->retrans_timeo / HZ);
411 seq_printf(m, ",retrans=%u", nfss->retrans_count);
81039f1f 412 seq_printf(m, ",sec=%s", nfs_pseudoflavour_to_name(nfss->client->cl_auth->au_flavor));
f7b422b1
DH
413}
414
415/*
416 * Describe the mount options on this VFS mountpoint
417 */
418static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt)
419{
420 struct nfs_server *nfss = NFS_SB(mnt->mnt_sb);
421
422 nfs_show_mount_options(m, nfss, 0);
423
424 seq_puts(m, ",addr=");
425 seq_escape(m, nfss->hostname, " \t\n\\");
426
427 return 0;
428}
429
430/*
431 * Present statistical information for this VFS mountpoint
432 */
433static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt)
434{
435 int i, cpu;
436 struct nfs_server *nfss = NFS_SB(mnt->mnt_sb);
437 struct rpc_auth *auth = nfss->client->cl_auth;
438 struct nfs_iostats totals = { };
439
440 seq_printf(m, "statvers=%s", NFS_IOSTAT_VERS);
441
442 /*
443 * Display all mount option settings
444 */
445 seq_printf(m, "\n\topts:\t");
446 seq_puts(m, mnt->mnt_sb->s_flags & MS_RDONLY ? "ro" : "rw");
447 seq_puts(m, mnt->mnt_sb->s_flags & MS_SYNCHRONOUS ? ",sync" : "");
448 seq_puts(m, mnt->mnt_sb->s_flags & MS_NOATIME ? ",noatime" : "");
449 seq_puts(m, mnt->mnt_sb->s_flags & MS_NODIRATIME ? ",nodiratime" : "");
450 nfs_show_mount_options(m, nfss, 1);
451
452 seq_printf(m, "\n\tage:\t%lu", (jiffies - nfss->mount_time) / HZ);
453
454 seq_printf(m, "\n\tcaps:\t");
455 seq_printf(m, "caps=0x%x", nfss->caps);
456 seq_printf(m, ",wtmult=%d", nfss->wtmult);
457 seq_printf(m, ",dtsize=%d", nfss->dtsize);
458 seq_printf(m, ",bsize=%d", nfss->bsize);
459 seq_printf(m, ",namelen=%d", nfss->namelen);
460
461#ifdef CONFIG_NFS_V4
462 if (nfss->rpc_ops->version == 4) {
463 seq_printf(m, "\n\tnfsv4:\t");
464 seq_printf(m, "bm0=0x%x", nfss->attr_bitmask[0]);
465 seq_printf(m, ",bm1=0x%x", nfss->attr_bitmask[1]);
466 seq_printf(m, ",acl=0x%x", nfss->acl_bitmask);
467 }
468#endif
469
470 /*
471 * Display security flavor in effect for this mount
472 */
473 seq_printf(m, "\n\tsec:\tflavor=%d", auth->au_ops->au_flavor);
474 if (auth->au_flavor)
475 seq_printf(m, ",pseudoflavor=%d", auth->au_flavor);
476
477 /*
478 * Display superblock I/O counters
479 */
480 for_each_possible_cpu(cpu) {
481 struct nfs_iostats *stats;
482
483 preempt_disable();
484 stats = per_cpu_ptr(nfss->io_stats, cpu);
485
486 for (i = 0; i < __NFSIOS_COUNTSMAX; i++)
487 totals.events[i] += stats->events[i];
488 for (i = 0; i < __NFSIOS_BYTESMAX; i++)
489 totals.bytes[i] += stats->bytes[i];
490
491 preempt_enable();
492 }
493
494 seq_printf(m, "\n\tevents:\t");
495 for (i = 0; i < __NFSIOS_COUNTSMAX; i++)
496 seq_printf(m, "%lu ", totals.events[i]);
497 seq_printf(m, "\n\tbytes:\t");
498 for (i = 0; i < __NFSIOS_BYTESMAX; i++)
499 seq_printf(m, "%Lu ", totals.bytes[i]);
500 seq_printf(m, "\n");
501
502 rpc_print_iostats(m, nfss->client);
503
504 return 0;
505}
506
507/*
508 * Begin unmount by attempting to remove all automounted mountpoints we added
509 * in response to traversals
510 */
511static void nfs_umount_begin(struct vfsmount *vfsmnt, int flags)
512{
513 struct nfs_server *server;
514 struct rpc_clnt *rpc;
515
516 shrink_submounts(vfsmnt, &nfs_automount_list);
517 if (!(flags & MNT_FORCE))
518 return;
519 /* -EIO all pending I/O */
520 server = NFS_SB(vfsmnt->mnt_sb);
521 rpc = server->client;
522 if (!IS_ERR(rpc))
523 rpc_killall_tasks(rpc);
524 rpc = server->client_acl;
525 if (!IS_ERR(rpc))
526 rpc_killall_tasks(rpc);
527}
528
529/*
530 * Obtain the root inode of the file system.
531 */
532static struct inode *
533nfs_get_root(struct super_block *sb, struct nfs_fh *rootfh, struct nfs_fsinfo *fsinfo)
534{
535 struct nfs_server *server = NFS_SB(sb);
536 int error;
537
538 error = server->rpc_ops->getroot(server, rootfh, fsinfo);
539 if (error < 0) {
540 dprintk("nfs_get_root: getattr error = %d\n", -error);
541 return ERR_PTR(error);
542 }
543
544 server->fsid = fsinfo->fattr->fsid;
545 return nfs_fhget(sb, rootfh, fsinfo->fattr);
546}
547
548/*
549 * Do NFS version-independent mount processing, and sanity checking
550 */
551static int
552nfs_sb_init(struct super_block *sb, rpc_authflavor_t authflavor)
553{
554 struct nfs_server *server;
555 struct inode *root_inode;
556 struct nfs_fattr fattr;
557 struct nfs_fsinfo fsinfo = {
558 .fattr = &fattr,
559 };
560 struct nfs_pathconf pathinfo = {
561 .fattr = &fattr,
562 };
563 int no_root_error = 0;
564 unsigned long max_rpc_payload;
565
566 /* We probably want something more informative here */
567 snprintf(sb->s_id, sizeof(sb->s_id), "%x:%x", MAJOR(sb->s_dev), MINOR(sb->s_dev));
568
569 server = NFS_SB(sb);
570
571 sb->s_magic = NFS_SUPER_MAGIC;
572
573 server->io_stats = nfs_alloc_iostats();
574 if (server->io_stats == NULL)
575 return -ENOMEM;
576
577 root_inode = nfs_get_root(sb, &server->fh, &fsinfo);
578 /* Did getting the root inode fail? */
579 if (IS_ERR(root_inode)) {
580 no_root_error = PTR_ERR(root_inode);
581 goto out_no_root;
582 }
583 sb->s_root = d_alloc_root(root_inode);
584 if (!sb->s_root) {
585 no_root_error = -ENOMEM;
586 goto out_no_root;
587 }
588 sb->s_root->d_op = server->rpc_ops->dentry_ops;
589
590 /* mount time stamp, in seconds */
591 server->mount_time = jiffies;
592
593 /* Get some general file system info */
594 if (server->namelen == 0 &&
595 server->rpc_ops->pathconf(server, &server->fh, &pathinfo) >= 0)
596 server->namelen = pathinfo.max_namelen;
597 /* Work out a lot of parameters */
598 if (server->rsize == 0)
599 server->rsize = nfs_block_size(fsinfo.rtpref, NULL);
600 if (server->wsize == 0)
601 server->wsize = nfs_block_size(fsinfo.wtpref, NULL);
602
603 if (fsinfo.rtmax >= 512 && server->rsize > fsinfo.rtmax)
604 server->rsize = nfs_block_size(fsinfo.rtmax, NULL);
605 if (fsinfo.wtmax >= 512 && server->wsize > fsinfo.wtmax)
606 server->wsize = nfs_block_size(fsinfo.wtmax, NULL);
607
608 max_rpc_payload = nfs_block_size(rpc_max_payload(server->client), NULL);
609 if (server->rsize > max_rpc_payload)
610 server->rsize = max_rpc_payload;
611 if (server->rsize > NFS_MAX_FILE_IO_SIZE)
612 server->rsize = NFS_MAX_FILE_IO_SIZE;
613 server->rpages = (server->rsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
614
615 if (server->wsize > max_rpc_payload)
616 server->wsize = max_rpc_payload;
617 if (server->wsize > NFS_MAX_FILE_IO_SIZE)
618 server->wsize = NFS_MAX_FILE_IO_SIZE;
619 server->wpages = (server->wsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
620
621 if (sb->s_blocksize == 0)
622 sb->s_blocksize = nfs_block_bits(server->wsize,
623 &sb->s_blocksize_bits);
624 server->wtmult = nfs_block_bits(fsinfo.wtmult, NULL);
625
626 server->dtsize = nfs_block_size(fsinfo.dtpref, NULL);
627 if (server->dtsize > PAGE_CACHE_SIZE)
628 server->dtsize = PAGE_CACHE_SIZE;
629 if (server->dtsize > server->rsize)
630 server->dtsize = server->rsize;
631
632 if (server->flags & NFS_MOUNT_NOAC) {
633 server->acregmin = server->acregmax = 0;
634 server->acdirmin = server->acdirmax = 0;
635 sb->s_flags |= MS_SYNCHRONOUS;
636 }
637 server->backing_dev_info.ra_pages = server->rpages * NFS_MAX_READAHEAD;
638
639 nfs_super_set_maxbytes(sb, fsinfo.maxfilesize);
640
641 server->client->cl_intr = (server->flags & NFS_MOUNT_INTR) ? 1 : 0;
642 server->client->cl_softrtry = (server->flags & NFS_MOUNT_SOFT) ? 1 : 0;
643
644 /* We're airborne Set socket buffersize */
645 rpc_setbufsize(server->client, server->wsize + 100, server->rsize + 100);
646 return 0;
647 /* Yargs. It didn't work out. */
648out_no_root:
649 dprintk("nfs_sb_init: get root inode failed: errno %d\n", -no_root_error);
650 if (!IS_ERR(root_inode))
651 iput(root_inode);
652 return no_root_error;
653}
654
655/*
656 * Initialise the timeout values for a connection
657 */
658static void nfs_init_timeout_values(struct rpc_timeout *to, int proto, unsigned int timeo, unsigned int retrans)
659{
660 to->to_initval = timeo * HZ / 10;
661 to->to_retries = retrans;
662 if (!to->to_retries)
663 to->to_retries = 2;
664
665 switch (proto) {
666 case IPPROTO_TCP:
667 if (!to->to_initval)
668 to->to_initval = 60 * HZ;
669 if (to->to_initval > NFS_MAX_TCP_TIMEOUT)
670 to->to_initval = NFS_MAX_TCP_TIMEOUT;
671 to->to_increment = to->to_initval;
672 to->to_maxval = to->to_initval + (to->to_increment * to->to_retries);
673 to->to_exponential = 0;
674 break;
675 case IPPROTO_UDP:
676 default:
677 if (!to->to_initval)
678 to->to_initval = 11 * HZ / 10;
679 if (to->to_initval > NFS_MAX_UDP_TIMEOUT)
680 to->to_initval = NFS_MAX_UDP_TIMEOUT;
681 to->to_maxval = NFS_MAX_UDP_TIMEOUT;
682 to->to_exponential = 1;
683 break;
684 }
685}
686
687/*
688 * Create an RPC client handle.
689 */
690static struct rpc_clnt *
691nfs_create_client(struct nfs_server *server, const struct nfs_mount_data *data)
692{
693 struct rpc_timeout timeparms;
694 struct rpc_xprt *xprt = NULL;
695 struct rpc_clnt *clnt = NULL;
696 int proto = (data->flags & NFS_MOUNT_TCP) ? IPPROTO_TCP : IPPROTO_UDP;
697
698 nfs_init_timeout_values(&timeparms, proto, data->timeo, data->retrans);
699
700 server->retrans_timeo = timeparms.to_initval;
701 server->retrans_count = timeparms.to_retries;
702
703 /* create transport and client */
704 xprt = xprt_create_proto(proto, &server->addr, &timeparms);
705 if (IS_ERR(xprt)) {
706 dprintk("%s: cannot create RPC transport. Error = %ld\n",
707 __FUNCTION__, PTR_ERR(xprt));
708 return (struct rpc_clnt *)xprt;
709 }
710 clnt = rpc_create_client(xprt, server->hostname, &nfs_program,
711 server->rpc_ops->version, data->pseudoflavor);
712 if (IS_ERR(clnt)) {
713 dprintk("%s: cannot create RPC client. Error = %ld\n",
714 __FUNCTION__, PTR_ERR(xprt));
715 goto out_fail;
716 }
717
718 clnt->cl_intr = 1;
719 clnt->cl_softrtry = 1;
720
721 return clnt;
722
723out_fail:
724 return clnt;
725}
726
727/*
728 * Clone a server record
729 */
730static struct nfs_server *nfs_clone_server(struct super_block *sb, struct nfs_clone_mount *data)
731{
732 struct nfs_server *server = NFS_SB(sb);
733 struct nfs_server *parent = NFS_SB(data->sb);
734 struct inode *root_inode;
735 struct nfs_fsinfo fsinfo;
736 void *err = ERR_PTR(-ENOMEM);
737
738 sb->s_op = data->sb->s_op;
739 sb->s_blocksize = data->sb->s_blocksize;
740 sb->s_blocksize_bits = data->sb->s_blocksize_bits;
741 sb->s_maxbytes = data->sb->s_maxbytes;
742
743 server->client_sys = server->client_acl = ERR_PTR(-EINVAL);
744 server->io_stats = nfs_alloc_iostats();
745 if (server->io_stats == NULL)
746 goto out;
747
748 server->client = rpc_clone_client(parent->client);
749 if (IS_ERR((err = server->client)))
750 goto out;
751
752 if (!IS_ERR(parent->client_sys)) {
753 server->client_sys = rpc_clone_client(parent->client_sys);
754 if (IS_ERR((err = server->client_sys)))
755 goto out;
756 }
757 if (!IS_ERR(parent->client_acl)) {
758 server->client_acl = rpc_clone_client(parent->client_acl);
759 if (IS_ERR((err = server->client_acl)))
760 goto out;
761 }
762 root_inode = nfs_fhget(sb, data->fh, data->fattr);
763 if (!root_inode)
764 goto out;
765 sb->s_root = d_alloc_root(root_inode);
766 if (!sb->s_root)
767 goto out_put_root;
768 fsinfo.fattr = data->fattr;
769 if (NFS_PROTO(root_inode)->fsinfo(server, data->fh, &fsinfo) == 0)
770 nfs_super_set_maxbytes(sb, fsinfo.maxfilesize);
771 sb->s_root->d_op = server->rpc_ops->dentry_ops;
772 sb->s_flags |= MS_ACTIVE;
773 return server;
774out_put_root:
775 iput(root_inode);
776out:
777 return err;
778}
779
780/*
781 * Copy an existing superblock and attach revised data
782 */
816724e6 783static int nfs_clone_generic_sb(struct nfs_clone_mount *data,
f7b422b1 784 struct super_block *(*fill_sb)(struct nfs_server *, struct nfs_clone_mount *),
816724e6
TM
785 struct nfs_server *(*fill_server)(struct super_block *, struct nfs_clone_mount *),
786 struct vfsmount *mnt)
f7b422b1
DH
787{
788 struct nfs_server *server;
789 struct nfs_server *parent = NFS_SB(data->sb);
790 struct super_block *sb = ERR_PTR(-EINVAL);
f7b422b1 791 char *hostname;
816724e6 792 int error = -ENOMEM;
f7b422b1
DH
793 int len;
794
795 server = kmalloc(sizeof(struct nfs_server), GFP_KERNEL);
796 if (server == NULL)
797 goto out_err;
798 memcpy(server, parent, sizeof(*server));
799 hostname = (data->hostname != NULL) ? data->hostname : parent->hostname;
800 len = strlen(hostname) + 1;
801 server->hostname = kmalloc(len, GFP_KERNEL);
802 if (server->hostname == NULL)
803 goto free_server;
804 memcpy(server->hostname, hostname, len);
816724e6
TM
805 error = rpciod_up();
806 if (error != 0)
f7b422b1
DH
807 goto free_hostname;
808
809 sb = fill_sb(server, data);
816724e6
TM
810 if (IS_ERR(sb)) {
811 error = PTR_ERR(sb);
f7b422b1 812 goto kill_rpciod;
816724e6
TM
813 }
814
815 if (sb->s_root)
816 goto out_rpciod_down;
f7b422b1
DH
817
818 server = fill_server(sb, data);
816724e6
TM
819 if (IS_ERR(server)) {
820 error = PTR_ERR(server);
f7b422b1 821 goto out_deactivate;
816724e6
TM
822 }
823 return simple_set_mnt(mnt, sb);
f7b422b1
DH
824out_deactivate:
825 up_write(&sb->s_umount);
826 deactivate_super(sb);
816724e6
TM
827 return error;
828out_rpciod_down:
829 rpciod_down();
830 kfree(server->hostname);
831 kfree(server);
832 return simple_set_mnt(mnt, sb);
f7b422b1
DH
833kill_rpciod:
834 rpciod_down();
835free_hostname:
836 kfree(server->hostname);
837free_server:
838 kfree(server);
839out_err:
816724e6 840 return error;
f7b422b1
DH
841}
842
843/*
844 * Set up an NFS2/3 superblock
845 *
846 * The way this works is that the mount process passes a structure
847 * in the data argument which contains the server's IP address
848 * and the root file handle obtained from the server's mount
849 * daemon. We stash these away in the private superblock fields.
850 */
851static int
852nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data, int silent)
853{
854 struct nfs_server *server;
855 rpc_authflavor_t authflavor;
856
857 server = NFS_SB(sb);
858 sb->s_blocksize_bits = 0;
859 sb->s_blocksize = 0;
860 if (data->bsize)
861 sb->s_blocksize = nfs_block_size(data->bsize, &sb->s_blocksize_bits);
862 if (data->rsize)
863 server->rsize = nfs_block_size(data->rsize, NULL);
864 if (data->wsize)
865 server->wsize = nfs_block_size(data->wsize, NULL);
866 server->flags = data->flags & NFS_MOUNT_FLAGMASK;
867
868 server->acregmin = data->acregmin*HZ;
869 server->acregmax = data->acregmax*HZ;
870 server->acdirmin = data->acdirmin*HZ;
871 server->acdirmax = data->acdirmax*HZ;
872
873 /* Start lockd here, before we might error out */
874 if (!(server->flags & NFS_MOUNT_NONLM))
875 lockd_up();
876
877 server->namelen = data->namlen;
878 server->hostname = kmalloc(strlen(data->hostname) + 1, GFP_KERNEL);
879 if (!server->hostname)
880 return -ENOMEM;
881 strcpy(server->hostname, data->hostname);
882
883 /* Check NFS protocol revision and initialize RPC op vector
884 * and file handle pool. */
885#ifdef CONFIG_NFS_V3
886 if (server->flags & NFS_MOUNT_VER3) {
887 server->rpc_ops = &nfs_v3_clientops;
888 server->caps |= NFS_CAP_READDIRPLUS;
889 } else {
890 server->rpc_ops = &nfs_v2_clientops;
891 }
892#else
893 server->rpc_ops = &nfs_v2_clientops;
894#endif
895
896 /* Fill in pseudoflavor for mount version < 5 */
897 if (!(data->flags & NFS_MOUNT_SECFLAVOUR))
898 data->pseudoflavor = RPC_AUTH_UNIX;
899 authflavor = data->pseudoflavor; /* save for sb_init() */
900 /* XXX maybe we want to add a server->pseudoflavor field */
901
902 /* Create RPC client handles */
903 server->client = nfs_create_client(server, data);
904 if (IS_ERR(server->client))
905 return PTR_ERR(server->client);
906 /* RFC 2623, sec 2.3.2 */
907 if (authflavor != RPC_AUTH_UNIX) {
908 struct rpc_auth *auth;
909
910 server->client_sys = rpc_clone_client(server->client);
911 if (IS_ERR(server->client_sys))
912 return PTR_ERR(server->client_sys);
913 auth = rpcauth_create(RPC_AUTH_UNIX, server->client_sys);
914 if (IS_ERR(auth))
915 return PTR_ERR(auth);
916 } else {
917 atomic_inc(&server->client->cl_count);
918 server->client_sys = server->client;
919 }
920 if (server->flags & NFS_MOUNT_VER3) {
921#ifdef CONFIG_NFS_V3_ACL
922 if (!(server->flags & NFS_MOUNT_NOACL)) {
923 server->client_acl = rpc_bind_new_program(server->client, &nfsacl_program, 3);
924 /* No errors! Assume that Sun nfsacls are supported */
925 if (!IS_ERR(server->client_acl))
926 server->caps |= NFS_CAP_ACLS;
927 }
928#else
929 server->flags &= ~NFS_MOUNT_NOACL;
930#endif /* CONFIG_NFS_V3_ACL */
931 /*
932 * The VFS shouldn't apply the umask to mode bits. We will
933 * do so ourselves when necessary.
934 */
935 sb->s_flags |= MS_POSIXACL;
936 if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN)
937 server->namelen = NFS3_MAXNAMLEN;
938 sb->s_time_gran = 1;
939 } else {
940 if (server->namelen == 0 || server->namelen > NFS2_MAXNAMLEN)
941 server->namelen = NFS2_MAXNAMLEN;
942 }
943
944 sb->s_op = &nfs_sops;
945 return nfs_sb_init(sb, authflavor);
946}
947
948static int nfs_set_super(struct super_block *s, void *data)
949{
950 s->s_fs_info = data;
951 return set_anon_super(s, data);
952}
953
954static int nfs_compare_super(struct super_block *sb, void *data)
955{
956 struct nfs_server *server = data;
957 struct nfs_server *old = NFS_SB(sb);
958
959 if (old->addr.sin_addr.s_addr != server->addr.sin_addr.s_addr)
960 return 0;
961 if (old->addr.sin_port != server->addr.sin_port)
962 return 0;
963 return !nfs_compare_fh(&old->fh, &server->fh);
964}
965
816724e6
TM
966static int nfs_get_sb(struct file_system_type *fs_type,
967 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
f7b422b1
DH
968{
969 int error;
970 struct nfs_server *server = NULL;
971 struct super_block *s;
972 struct nfs_fh *root;
973 struct nfs_mount_data *data = raw_data;
974
816724e6 975 error = -EINVAL;
f7b422b1
DH
976 if (data == NULL) {
977 dprintk("%s: missing data argument\n", __FUNCTION__);
816724e6 978 goto out_err_noserver;
f7b422b1
DH
979 }
980 if (data->version <= 0 || data->version > NFS_MOUNT_VERSION) {
981 dprintk("%s: bad mount version\n", __FUNCTION__);
816724e6 982 goto out_err_noserver;
f7b422b1
DH
983 }
984 switch (data->version) {
985 case 1:
986 data->namlen = 0;
987 case 2:
988 data->bsize = 0;
989 case 3:
990 if (data->flags & NFS_MOUNT_VER3) {
991 dprintk("%s: mount structure version %d does not support NFSv3\n",
992 __FUNCTION__,
993 data->version);
816724e6 994 goto out_err_noserver;
f7b422b1
DH
995 }
996 data->root.size = NFS2_FHSIZE;
997 memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE);
998 case 4:
999 if (data->flags & NFS_MOUNT_SECFLAVOUR) {
1000 dprintk("%s: mount structure version %d does not support strong security\n",
1001 __FUNCTION__,
1002 data->version);
816724e6 1003 goto out_err_noserver;
f7b422b1
DH
1004 }
1005 case 5:
1006 memset(data->context, 0, sizeof(data->context));
1007 }
1008#ifndef CONFIG_NFS_V3
1009 /* If NFSv3 is not compiled in, return -EPROTONOSUPPORT */
816724e6 1010 error = -EPROTONOSUPPORT;
f7b422b1
DH
1011 if (data->flags & NFS_MOUNT_VER3) {
1012 dprintk("%s: NFSv3 not compiled into kernel\n", __FUNCTION__);
816724e6 1013 goto out_err_noserver;
f7b422b1
DH
1014 }
1015#endif /* CONFIG_NFS_V3 */
1016
816724e6 1017 error = -ENOMEM;
f7b422b1
DH
1018 server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL);
1019 if (!server)
816724e6 1020 goto out_err_noserver;
f7b422b1
DH
1021 /* Zero out the NFS state stuff */
1022 init_nfsv4_state(server);
1023 server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL);
1024
1025 root = &server->fh;
1026 if (data->flags & NFS_MOUNT_VER3)
1027 root->size = data->root.size;
1028 else
1029 root->size = NFS2_FHSIZE;
816724e6 1030 error = -EINVAL;
f7b422b1
DH
1031 if (root->size > sizeof(root->data)) {
1032 dprintk("%s: invalid root filehandle\n", __FUNCTION__);
1033 goto out_err;
1034 }
1035 memcpy(root->data, data->root.data, root->size);
1036
1037 /* We now require that the mount process passes the remote address */
1038 memcpy(&server->addr, &data->addr, sizeof(server->addr));
1039 if (server->addr.sin_addr.s_addr == INADDR_ANY) {
1040 dprintk("%s: mount program didn't pass remote address!\n",
1041 __FUNCTION__);
1042 goto out_err;
1043 }
1044
1045 /* Fire up rpciod if not yet running */
816724e6
TM
1046 error = rpciod_up();
1047 if (error < 0) {
1048 dprintk("%s: couldn't start rpciod! Error = %d\n",
1049 __FUNCTION__, error);
f7b422b1
DH
1050 goto out_err;
1051 }
1052
1053 s = sget(fs_type, nfs_compare_super, nfs_set_super, server);
816724e6
TM
1054 if (IS_ERR(s)) {
1055 error = PTR_ERR(s);
1056 goto out_err_rpciod;
1057 }
1058
1059 if (s->s_root)
f7b422b1
DH
1060 goto out_rpciod_down;
1061
1062 s->s_flags = flags;
1063
1064 error = nfs_fill_super(s, data, flags & MS_SILENT ? 1 : 0);
1065 if (error) {
1066 up_write(&s->s_umount);
1067 deactivate_super(s);
816724e6 1068 return error;
f7b422b1
DH
1069 }
1070 s->s_flags |= MS_ACTIVE;
816724e6
TM
1071 return simple_set_mnt(mnt, s);
1072
f7b422b1
DH
1073out_rpciod_down:
1074 rpciod_down();
816724e6
TM
1075 kfree(server);
1076 return simple_set_mnt(mnt, s);
1077
1078out_err_rpciod:
1079 rpciod_down();
f7b422b1
DH
1080out_err:
1081 kfree(server);
816724e6
TM
1082out_err_noserver:
1083 return error;
f7b422b1
DH
1084}
1085
1086static void nfs_kill_super(struct super_block *s)
1087{
1088 struct nfs_server *server = NFS_SB(s);
1089
1090 kill_anon_super(s);
1091
1092 if (!IS_ERR(server->client))
1093 rpc_shutdown_client(server->client);
1094 if (!IS_ERR(server->client_sys))
1095 rpc_shutdown_client(server->client_sys);
1096 if (!IS_ERR(server->client_acl))
1097 rpc_shutdown_client(server->client_acl);
1098
1099 if (!(server->flags & NFS_MOUNT_NONLM))
1100 lockd_down(); /* release rpc.lockd */
1101
1102 rpciod_down(); /* release rpciod */
1103
1104 nfs_free_iostats(server->io_stats);
1105 kfree(server->hostname);
1106 kfree(server);
1107 nfs_release_automount_timer();
1108}
1109
1110static struct super_block *nfs_clone_sb(struct nfs_server *server, struct nfs_clone_mount *data)
1111{
1112 struct super_block *sb;
1113
1114 server->fsid = data->fattr->fsid;
1115 nfs_copy_fh(&server->fh, data->fh);
1116 sb = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server);
1117 if (!IS_ERR(sb) && sb->s_root == NULL && !(server->flags & NFS_MOUNT_NONLM))
1118 lockd_up();
1119 return sb;
1120}
1121
816724e6
TM
1122static int nfs_clone_nfs_sb(struct file_system_type *fs_type,
1123 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
f7b422b1
DH
1124{
1125 struct nfs_clone_mount *data = raw_data;
816724e6 1126 return nfs_clone_generic_sb(data, nfs_clone_sb, nfs_clone_server, mnt);
f7b422b1
DH
1127}
1128
1129#ifdef CONFIG_NFS_V4
1130static struct rpc_clnt *nfs4_create_client(struct nfs_server *server,
1131 struct rpc_timeout *timeparms, int proto, rpc_authflavor_t flavor)
1132{
1133 struct nfs4_client *clp;
1134 struct rpc_xprt *xprt = NULL;
1135 struct rpc_clnt *clnt = NULL;
1136 int err = -EIO;
1137
1138 clp = nfs4_get_client(&server->addr.sin_addr);
1139 if (!clp) {
1140 dprintk("%s: failed to create NFS4 client.\n", __FUNCTION__);
1141 return ERR_PTR(err);
1142 }
1143
1144 /* Now create transport and client */
1145 down_write(&clp->cl_sem);
1146 if (IS_ERR(clp->cl_rpcclient)) {
1147 xprt = xprt_create_proto(proto, &server->addr, timeparms);
1148 if (IS_ERR(xprt)) {
1149 up_write(&clp->cl_sem);
1150 err = PTR_ERR(xprt);
1151 dprintk("%s: cannot create RPC transport. Error = %d\n",
1152 __FUNCTION__, err);
1153 goto out_fail;
1154 }
1155 /* Bind to a reserved port! */
1156 xprt->resvport = 1;
1157 clnt = rpc_create_client(xprt, server->hostname, &nfs_program,
1158 server->rpc_ops->version, flavor);
1159 if (IS_ERR(clnt)) {
1160 up_write(&clp->cl_sem);
1161 err = PTR_ERR(clnt);
1162 dprintk("%s: cannot create RPC client. Error = %d\n",
1163 __FUNCTION__, err);
1164 goto out_fail;
1165 }
1166 clnt->cl_intr = 1;
1167 clnt->cl_softrtry = 1;
1168 clp->cl_rpcclient = clnt;
1169 memcpy(clp->cl_ipaddr, server->ip_addr, sizeof(clp->cl_ipaddr));
1170 nfs_idmap_new(clp);
1171 }
1172 list_add_tail(&server->nfs4_siblings, &clp->cl_superblocks);
1173 clnt = rpc_clone_client(clp->cl_rpcclient);
1174 if (!IS_ERR(clnt))
1175 server->nfs4_state = clp;
1176 up_write(&clp->cl_sem);
1177 clp = NULL;
1178
1179 if (IS_ERR(clnt)) {
1180 dprintk("%s: cannot create RPC client. Error = %d\n",
1181 __FUNCTION__, err);
1182 return clnt;
1183 }
1184
1185 if (server->nfs4_state->cl_idmap == NULL) {
1186 dprintk("%s: failed to create idmapper.\n", __FUNCTION__);
1187 return ERR_PTR(-ENOMEM);
1188 }
1189
1190 if (clnt->cl_auth->au_flavor != flavor) {
1191 struct rpc_auth *auth;
1192
1193 auth = rpcauth_create(flavor, clnt);
1194 if (IS_ERR(auth)) {
1195 dprintk("%s: couldn't create credcache!\n", __FUNCTION__);
1196 return (struct rpc_clnt *)auth;
1197 }
1198 }
1199 return clnt;
1200
1201 out_fail:
1202 if (clp)
1203 nfs4_put_client(clp);
1204 return ERR_PTR(err);
1205}
1206
1207/*
1208 * Set up an NFS4 superblock
1209 */
1210static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data, int silent)
1211{
1212 struct nfs_server *server;
1213 struct rpc_timeout timeparms;
1214 rpc_authflavor_t authflavour;
1215 int err = -EIO;
1216
1217 sb->s_blocksize_bits = 0;
1218 sb->s_blocksize = 0;
1219 server = NFS_SB(sb);
1220 if (data->rsize != 0)
1221 server->rsize = nfs_block_size(data->rsize, NULL);
1222 if (data->wsize != 0)
1223 server->wsize = nfs_block_size(data->wsize, NULL);
1224 server->flags = data->flags & NFS_MOUNT_FLAGMASK;
1225 server->caps = NFS_CAP_ATOMIC_OPEN;
1226
1227 server->acregmin = data->acregmin*HZ;
1228 server->acregmax = data->acregmax*HZ;
1229 server->acdirmin = data->acdirmin*HZ;
1230 server->acdirmax = data->acdirmax*HZ;
1231
1232 server->rpc_ops = &nfs_v4_clientops;
1233
1234 nfs_init_timeout_values(&timeparms, data->proto, data->timeo, data->retrans);
1235
1236 server->retrans_timeo = timeparms.to_initval;
1237 server->retrans_count = timeparms.to_retries;
1238
1239 /* Now create transport and client */
1240 authflavour = RPC_AUTH_UNIX;
1241 if (data->auth_flavourlen != 0) {
1242 if (data->auth_flavourlen != 1) {
1243 dprintk("%s: Invalid number of RPC auth flavours %d.\n",
1244 __FUNCTION__, data->auth_flavourlen);
1245 err = -EINVAL;
1246 goto out_fail;
1247 }
1248 if (copy_from_user(&authflavour, data->auth_flavours, sizeof(authflavour))) {
1249 err = -EFAULT;
1250 goto out_fail;
1251 }
1252 }
1253
1254 server->client = nfs4_create_client(server, &timeparms, data->proto, authflavour);
1255 if (IS_ERR(server->client)) {
1256 err = PTR_ERR(server->client);
1257 dprintk("%s: cannot create RPC client. Error = %d\n",
1258 __FUNCTION__, err);
1259 goto out_fail;
1260 }
1261
1262 sb->s_time_gran = 1;
1263
1264 sb->s_op = &nfs4_sops;
1265 err = nfs_sb_init(sb, authflavour);
1266
1267 out_fail:
1268 return err;
1269}
1270
1271static int nfs4_compare_super(struct super_block *sb, void *data)
1272{
1273 struct nfs_server *server = data;
1274 struct nfs_server *old = NFS_SB(sb);
1275
1276 if (strcmp(server->hostname, old->hostname) != 0)
1277 return 0;
1278 if (strcmp(server->mnt_path, old->mnt_path) != 0)
1279 return 0;
1280 return 1;
1281}
1282
1283static void *
1284nfs_copy_user_string(char *dst, struct nfs_string *src, int maxlen)
1285{
1286 void *p = NULL;
1287
1288 if (!src->len)
1289 return ERR_PTR(-EINVAL);
1290 if (src->len < maxlen)
1291 maxlen = src->len;
1292 if (dst == NULL) {
1293 p = dst = kmalloc(maxlen + 1, GFP_KERNEL);
1294 if (p == NULL)
1295 return ERR_PTR(-ENOMEM);
1296 }
1297 if (copy_from_user(dst, src->data, maxlen)) {
1298 kfree(p);
1299 return ERR_PTR(-EFAULT);
1300 }
1301 dst[maxlen] = '\0';
1302 return dst;
1303}
1304
816724e6
TM
1305static int nfs4_get_sb(struct file_system_type *fs_type,
1306 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
f7b422b1
DH
1307{
1308 int error;
1309 struct nfs_server *server;
1310 struct super_block *s;
1311 struct nfs4_mount_data *data = raw_data;
1312 void *p;
1313
1314 if (data == NULL) {
1315 dprintk("%s: missing data argument\n", __FUNCTION__);
816724e6 1316 return -EINVAL;
f7b422b1
DH
1317 }
1318 if (data->version <= 0 || data->version > NFS4_MOUNT_VERSION) {
1319 dprintk("%s: bad mount version\n", __FUNCTION__);
816724e6 1320 return -EINVAL;
f7b422b1
DH
1321 }
1322
1323 server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL);
1324 if (!server)
816724e6 1325 return -ENOMEM;
f7b422b1
DH
1326 /* Zero out the NFS state stuff */
1327 init_nfsv4_state(server);
1328 server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL);
1329
1330 p = nfs_copy_user_string(NULL, &data->hostname, 256);
1331 if (IS_ERR(p))
1332 goto out_err;
1333 server->hostname = p;
1334
1335 p = nfs_copy_user_string(NULL, &data->mnt_path, 1024);
1336 if (IS_ERR(p))
1337 goto out_err;
1338 server->mnt_path = p;
1339
1340 p = nfs_copy_user_string(server->ip_addr, &data->client_addr,
1341 sizeof(server->ip_addr) - 1);
1342 if (IS_ERR(p))
1343 goto out_err;
1344
1345 /* We now require that the mount process passes the remote address */
1346 if (data->host_addrlen != sizeof(server->addr)) {
816724e6 1347 error = -EINVAL;
f7b422b1
DH
1348 goto out_free;
1349 }
1350 if (copy_from_user(&server->addr, data->host_addr, sizeof(server->addr))) {
816724e6 1351 error = -EFAULT;
f7b422b1
DH
1352 goto out_free;
1353 }
1354 if (server->addr.sin_family != AF_INET ||
1355 server->addr.sin_addr.s_addr == INADDR_ANY) {
1356 dprintk("%s: mount program didn't pass remote IP address!\n",
1357 __FUNCTION__);
816724e6 1358 error = -EINVAL;
f7b422b1
DH
1359 goto out_free;
1360 }
1361
1362 /* Fire up rpciod if not yet running */
816724e6
TM
1363 error = rpciod_up();
1364 if (error < 0) {
1365 dprintk("%s: couldn't start rpciod! Error = %d\n",
1366 __FUNCTION__, error);
f7b422b1
DH
1367 goto out_free;
1368 }
1369
1370 s = sget(fs_type, nfs4_compare_super, nfs_set_super, server);
1371
816724e6
TM
1372 if (IS_ERR(s)) {
1373 error = PTR_ERR(s);
f7b422b1 1374 goto out_free;
816724e6
TM
1375 }
1376
1377 if (s->s_root) {
1378 kfree(server->mnt_path);
1379 kfree(server->hostname);
1380 kfree(server);
1381 return simple_set_mnt(mnt, s);
1382 }
f7b422b1
DH
1383
1384 s->s_flags = flags;
1385
1386 error = nfs4_fill_super(s, data, flags & MS_SILENT ? 1 : 0);
1387 if (error) {
1388 up_write(&s->s_umount);
1389 deactivate_super(s);
816724e6 1390 return error;
f7b422b1
DH
1391 }
1392 s->s_flags |= MS_ACTIVE;
816724e6 1393 return simple_set_mnt(mnt, s);
f7b422b1 1394out_err:
816724e6 1395 error = PTR_ERR(p);
f7b422b1
DH
1396out_free:
1397 kfree(server->mnt_path);
1398 kfree(server->hostname);
1399 kfree(server);
816724e6 1400 return error;
f7b422b1
DH
1401}
1402
1403static void nfs4_kill_super(struct super_block *sb)
1404{
1405 struct nfs_server *server = NFS_SB(sb);
1406
1407 nfs_return_all_delegations(sb);
1408 kill_anon_super(sb);
1409
1410 nfs4_renewd_prepare_shutdown(server);
1411
1412 if (server->client != NULL && !IS_ERR(server->client))
1413 rpc_shutdown_client(server->client);
1414
1415 destroy_nfsv4_state(server);
1416
1417 rpciod_down();
1418
1419 nfs_free_iostats(server->io_stats);
1420 kfree(server->hostname);
1421 kfree(server);
1422 nfs_release_automount_timer();
1423}
1424
1425/*
1426 * Constructs the SERVER-side path
1427 */
1428static inline char *nfs4_dup_path(const struct dentry *dentry)
1429{
1430 char *page = (char *) __get_free_page(GFP_USER);
1431 char *path;
1432
1433 path = nfs4_path(dentry, page, PAGE_SIZE);
1434 if (!IS_ERR(path)) {
1435 int len = PAGE_SIZE + page - path;
1436 char *tmp = path;
1437
1438 path = kmalloc(len, GFP_KERNEL);
1439 if (path)
1440 memcpy(path, tmp, len);
1441 else
1442 path = ERR_PTR(-ENOMEM);
1443 }
1444 free_page((unsigned long)page);
1445 return path;
1446}
1447
1448static struct super_block *nfs4_clone_sb(struct nfs_server *server, struct nfs_clone_mount *data)
1449{
1450 const struct dentry *dentry = data->dentry;
1451 struct nfs4_client *clp = server->nfs4_state;
1452 struct super_block *sb;
1453
1454 server->fsid = data->fattr->fsid;
1455 nfs_copy_fh(&server->fh, data->fh);
1456 server->mnt_path = nfs4_dup_path(dentry);
1457 if (IS_ERR(server->mnt_path)) {
1458 sb = (struct super_block *)server->mnt_path;
1459 goto err;
1460 }
1461 sb = sget(&nfs4_fs_type, nfs4_compare_super, nfs_set_super, server);
1462 if (IS_ERR(sb) || sb->s_root)
1463 goto free_path;
1464 nfs4_server_capabilities(server, &server->fh);
1465
1466 down_write(&clp->cl_sem);
1467 atomic_inc(&clp->cl_count);
1468 list_add_tail(&server->nfs4_siblings, &clp->cl_superblocks);
1469 up_write(&clp->cl_sem);
1470 return sb;
1471free_path:
1472 kfree(server->mnt_path);
1473err:
1474 server->mnt_path = NULL;
1475 return sb;
1476}
1477
816724e6
TM
1478static int nfs_clone_nfs4_sb(struct file_system_type *fs_type,
1479 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
f7b422b1
DH
1480{
1481 struct nfs_clone_mount *data = raw_data;
816724e6 1482 return nfs_clone_generic_sb(data, nfs4_clone_sb, nfs_clone_server, mnt);
f7b422b1
DH
1483}
1484
1485static struct super_block *nfs4_referral_sb(struct nfs_server *server, struct nfs_clone_mount *data)
1486{
1487 struct super_block *sb = ERR_PTR(-ENOMEM);
1488 int len;
1489
1490 len = strlen(data->mnt_path) + 1;
1491 server->mnt_path = kmalloc(len, GFP_KERNEL);
1492 if (server->mnt_path == NULL)
1493 goto err;
1494 memcpy(server->mnt_path, data->mnt_path, len);
1495 memcpy(&server->addr, data->addr, sizeof(struct sockaddr_in));
1496
1497 sb = sget(&nfs4_fs_type, nfs4_compare_super, nfs_set_super, server);
1498 if (IS_ERR(sb) || sb->s_root)
1499 goto free_path;
1500 return sb;
1501free_path:
1502 kfree(server->mnt_path);
1503err:
1504 server->mnt_path = NULL;
1505 return sb;
1506}
1507
1508static struct nfs_server *nfs4_referral_server(struct super_block *sb, struct nfs_clone_mount *data)
1509{
1510 struct nfs_server *server = NFS_SB(sb);
1511 struct rpc_timeout timeparms;
1512 int proto, timeo, retrans;
1513 void *err;
1514
1515 proto = IPPROTO_TCP;
1516 /* Since we are following a referral and there may be alternatives,
1517 set the timeouts and retries to low values */
1518 timeo = 2;
1519 retrans = 1;
1520 nfs_init_timeout_values(&timeparms, proto, timeo, retrans);
1521
1522 server->client = nfs4_create_client(server, &timeparms, proto, data->authflavor);
1523 if (IS_ERR((err = server->client)))
1524 goto out_err;
1525
1526 sb->s_time_gran = 1;
1527 sb->s_op = &nfs4_sops;
1528 err = ERR_PTR(nfs_sb_init(sb, data->authflavor));
1529 if (!IS_ERR(err))
1530 return server;
1531out_err:
1532 return (struct nfs_server *)err;
1533}
1534
816724e6
TM
1535static int nfs_referral_nfs4_sb(struct file_system_type *fs_type,
1536 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
f7b422b1
DH
1537{
1538 struct nfs_clone_mount *data = raw_data;
816724e6 1539 return nfs_clone_generic_sb(data, nfs4_referral_sb, nfs4_referral_server, mnt);
f7b422b1
DH
1540}
1541
1542#endif