[MTD] [MAPS] ck804xrom warning fix
[linux-2.6/openmoko-kernel.git] / fs / nfs / super.c
blob28108c82b88742d6e325a0736f820bf8e044910e
1 /*
2 * linux/fs/nfs/super.c
4 * Copyright (C) 1992 Rick Sladkey
6 * nfs superblock handling functions
8 * Modularised by Alan Cox <Alan.Cox@linux.org>, while hacking some
9 * experimental NFS changes. Modularisation taken straight from SYS5 fs.
11 * Change to nfs_read_super() to permit NFS mounts to multi-homed hosts.
12 * J.S.Peatfield@damtp.cam.ac.uk
14 * Split from inode.c by David Howells <dhowells@redhat.com>
16 * - superblocks are indexed on server only - all inodes, dentries, etc. associated with a
17 * particular server are held in the same superblock
18 * - NFS superblocks can have several effective roots to the dentry tree
19 * - directory type roots are spliced into the tree when a path from one root reaches the root
20 * of another (see nfs_lookup())
23 #include <linux/module.h>
24 #include <linux/init.h>
26 #include <linux/time.h>
27 #include <linux/kernel.h>
28 #include <linux/mm.h>
29 #include <linux/string.h>
30 #include <linux/stat.h>
31 #include <linux/errno.h>
32 #include <linux/unistd.h>
33 #include <linux/sunrpc/clnt.h>
34 #include <linux/sunrpc/stats.h>
35 #include <linux/sunrpc/metrics.h>
36 #include <linux/nfs_fs.h>
37 #include <linux/nfs_mount.h>
38 #include <linux/nfs4_mount.h>
39 #include <linux/lockd/bind.h>
40 #include <linux/smp_lock.h>
41 #include <linux/seq_file.h>
42 #include <linux/mount.h>
43 #include <linux/nfs_idmap.h>
44 #include <linux/vfs.h>
45 #include <linux/inet.h>
46 #include <linux/nfs_xdr.h>
48 #include <asm/system.h>
49 #include <asm/uaccess.h>
51 #include "nfs4_fs.h"
52 #include "callback.h"
53 #include "delegation.h"
54 #include "iostat.h"
55 #include "internal.h"
57 #define NFSDBG_FACILITY NFSDBG_VFS
59 static void nfs_umount_begin(struct vfsmount *, int);
60 static int nfs_statfs(struct dentry *, struct kstatfs *);
61 static int nfs_show_options(struct seq_file *, struct vfsmount *);
62 static int nfs_show_stats(struct seq_file *, struct vfsmount *);
63 static int nfs_get_sb(struct file_system_type *, int, const char *, void *, struct vfsmount *);
64 static int nfs_xdev_get_sb(struct file_system_type *fs_type,
65 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);
66 static void nfs_kill_super(struct super_block *);
68 static struct file_system_type nfs_fs_type = {
69 .owner = THIS_MODULE,
70 .name = "nfs",
71 .get_sb = nfs_get_sb,
72 .kill_sb = nfs_kill_super,
73 .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
76 struct file_system_type nfs_xdev_fs_type = {
77 .owner = THIS_MODULE,
78 .name = "nfs",
79 .get_sb = nfs_xdev_get_sb,
80 .kill_sb = nfs_kill_super,
81 .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
84 static struct super_operations nfs_sops = {
85 .alloc_inode = nfs_alloc_inode,
86 .destroy_inode = nfs_destroy_inode,
87 .write_inode = nfs_write_inode,
88 .statfs = nfs_statfs,
89 .clear_inode = nfs_clear_inode,
90 .umount_begin = nfs_umount_begin,
91 .show_options = nfs_show_options,
92 .show_stats = nfs_show_stats,
95 #ifdef CONFIG_NFS_V4
96 static int nfs4_get_sb(struct file_system_type *fs_type,
97 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);
98 static int nfs4_xdev_get_sb(struct file_system_type *fs_type,
99 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);
100 static int nfs4_referral_get_sb(struct file_system_type *fs_type,
101 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);
102 static void nfs4_kill_super(struct super_block *sb);
104 static struct file_system_type nfs4_fs_type = {
105 .owner = THIS_MODULE,
106 .name = "nfs4",
107 .get_sb = nfs4_get_sb,
108 .kill_sb = nfs4_kill_super,
109 .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
112 struct file_system_type nfs4_xdev_fs_type = {
113 .owner = THIS_MODULE,
114 .name = "nfs4",
115 .get_sb = nfs4_xdev_get_sb,
116 .kill_sb = nfs4_kill_super,
117 .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
120 struct file_system_type nfs4_referral_fs_type = {
121 .owner = THIS_MODULE,
122 .name = "nfs4",
123 .get_sb = nfs4_referral_get_sb,
124 .kill_sb = nfs4_kill_super,
125 .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
128 static struct super_operations nfs4_sops = {
129 .alloc_inode = nfs_alloc_inode,
130 .destroy_inode = nfs_destroy_inode,
131 .write_inode = nfs_write_inode,
132 .statfs = nfs_statfs,
133 .clear_inode = nfs4_clear_inode,
134 .umount_begin = nfs_umount_begin,
135 .show_options = nfs_show_options,
136 .show_stats = nfs_show_stats,
138 #endif
140 static struct shrinker *acl_shrinker;
143 * Register the NFS filesystems
145 int __init register_nfs_fs(void)
147 int ret;
149 ret = register_filesystem(&nfs_fs_type);
150 if (ret < 0)
151 goto error_0;
153 #ifdef CONFIG_NFS_V4
154 ret = nfs_register_sysctl();
155 if (ret < 0)
156 goto error_1;
157 ret = register_filesystem(&nfs4_fs_type);
158 if (ret < 0)
159 goto error_2;
160 #endif
161 acl_shrinker = set_shrinker(DEFAULT_SEEKS, nfs_access_cache_shrinker);
162 return 0;
164 #ifdef CONFIG_NFS_V4
165 error_2:
166 nfs_unregister_sysctl();
167 error_1:
168 unregister_filesystem(&nfs_fs_type);
169 #endif
170 error_0:
171 return ret;
175 * Unregister the NFS filesystems
177 void __exit unregister_nfs_fs(void)
179 if (acl_shrinker != NULL)
180 remove_shrinker(acl_shrinker);
181 #ifdef CONFIG_NFS_V4
182 unregister_filesystem(&nfs4_fs_type);
183 nfs_unregister_sysctl();
184 #endif
185 unregister_filesystem(&nfs_fs_type);
189 * Deliver file system statistics to userspace
191 static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf)
193 struct nfs_server *server = NFS_SB(dentry->d_sb);
194 unsigned char blockbits;
195 unsigned long blockres;
196 struct nfs_fh *fh = NFS_FH(dentry->d_inode);
197 struct nfs_fattr fattr;
198 struct nfs_fsstat res = {
199 .fattr = &fattr,
201 int error;
203 lock_kernel();
205 error = server->nfs_client->rpc_ops->statfs(server, fh, &res);
206 buf->f_type = NFS_SUPER_MAGIC;
207 if (error < 0)
208 goto out_err;
211 * Current versions of glibc do not correctly handle the
212 * case where f_frsize != f_bsize. Eventually we want to
213 * report the value of wtmult in this field.
215 buf->f_frsize = dentry->d_sb->s_blocksize;
218 * On most *nix systems, f_blocks, f_bfree, and f_bavail
219 * are reported in units of f_frsize. Linux hasn't had
220 * an f_frsize field in its statfs struct until recently,
221 * thus historically Linux's sys_statfs reports these
222 * fields in units of f_bsize.
224 buf->f_bsize = dentry->d_sb->s_blocksize;
225 blockbits = dentry->d_sb->s_blocksize_bits;
226 blockres = (1 << blockbits) - 1;
227 buf->f_blocks = (res.tbytes + blockres) >> blockbits;
228 buf->f_bfree = (res.fbytes + blockres) >> blockbits;
229 buf->f_bavail = (res.abytes + blockres) >> blockbits;
231 buf->f_files = res.tfiles;
232 buf->f_ffree = res.afiles;
234 buf->f_namelen = server->namelen;
235 out:
236 unlock_kernel();
237 return 0;
239 out_err:
240 dprintk("%s: statfs error = %d\n", __FUNCTION__, -error);
241 buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1;
242 goto out;
247 * Map the security flavour number to a name
249 static const char *nfs_pseudoflavour_to_name(rpc_authflavor_t flavour)
251 static const struct {
252 rpc_authflavor_t flavour;
253 const char *str;
254 } sec_flavours[] = {
255 { RPC_AUTH_NULL, "null" },
256 { RPC_AUTH_UNIX, "sys" },
257 { RPC_AUTH_GSS_KRB5, "krb5" },
258 { RPC_AUTH_GSS_KRB5I, "krb5i" },
259 { RPC_AUTH_GSS_KRB5P, "krb5p" },
260 { RPC_AUTH_GSS_LKEY, "lkey" },
261 { RPC_AUTH_GSS_LKEYI, "lkeyi" },
262 { RPC_AUTH_GSS_LKEYP, "lkeyp" },
263 { RPC_AUTH_GSS_SPKM, "spkm" },
264 { RPC_AUTH_GSS_SPKMI, "spkmi" },
265 { RPC_AUTH_GSS_SPKMP, "spkmp" },
266 { -1, "unknown" }
268 int i;
270 for (i=0; sec_flavours[i].flavour != -1; i++) {
271 if (sec_flavours[i].flavour == flavour)
272 break;
274 return sec_flavours[i].str;
278 * Describe the mount options in force on this server representation
280 static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, int showdefaults)
282 static const struct proc_nfs_info {
283 int flag;
284 const char *str;
285 const char *nostr;
286 } nfs_info[] = {
287 { NFS_MOUNT_SOFT, ",soft", ",hard" },
288 { NFS_MOUNT_INTR, ",intr", "" },
289 { NFS_MOUNT_NOCTO, ",nocto", "" },
290 { NFS_MOUNT_NOAC, ",noac", "" },
291 { NFS_MOUNT_NONLM, ",nolock", "" },
292 { NFS_MOUNT_NOACL, ",noacl", "" },
293 { 0, NULL, NULL }
295 const struct proc_nfs_info *nfs_infop;
296 struct nfs_client *clp = nfss->nfs_client;
297 char buf[12];
298 const char *proto;
300 seq_printf(m, ",vers=%d", clp->rpc_ops->version);
301 seq_printf(m, ",rsize=%d", nfss->rsize);
302 seq_printf(m, ",wsize=%d", nfss->wsize);
303 if (nfss->acregmin != 3*HZ || showdefaults)
304 seq_printf(m, ",acregmin=%d", nfss->acregmin/HZ);
305 if (nfss->acregmax != 60*HZ || showdefaults)
306 seq_printf(m, ",acregmax=%d", nfss->acregmax/HZ);
307 if (nfss->acdirmin != 30*HZ || showdefaults)
308 seq_printf(m, ",acdirmin=%d", nfss->acdirmin/HZ);
309 if (nfss->acdirmax != 60*HZ || showdefaults)
310 seq_printf(m, ",acdirmax=%d", nfss->acdirmax/HZ);
311 for (nfs_infop = nfs_info; nfs_infop->flag; nfs_infop++) {
312 if (nfss->flags & nfs_infop->flag)
313 seq_puts(m, nfs_infop->str);
314 else
315 seq_puts(m, nfs_infop->nostr);
317 switch (nfss->client->cl_xprt->prot) {
318 case IPPROTO_TCP:
319 proto = "tcp";
320 break;
321 case IPPROTO_UDP:
322 proto = "udp";
323 break;
324 default:
325 snprintf(buf, sizeof(buf), "%u", nfss->client->cl_xprt->prot);
326 proto = buf;
328 seq_printf(m, ",proto=%s", proto);
329 seq_printf(m, ",timeo=%lu", 10U * clp->retrans_timeo / HZ);
330 seq_printf(m, ",retrans=%u", clp->retrans_count);
331 seq_printf(m, ",sec=%s", nfs_pseudoflavour_to_name(nfss->client->cl_auth->au_flavor));
335 * Describe the mount options on this VFS mountpoint
337 static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt)
339 struct nfs_server *nfss = NFS_SB(mnt->mnt_sb);
341 nfs_show_mount_options(m, nfss, 0);
343 seq_puts(m, ",addr=");
344 seq_escape(m, nfss->nfs_client->cl_hostname, " \t\n\\");
346 return 0;
350 * Present statistical information for this VFS mountpoint
352 static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt)
354 int i, cpu;
355 struct nfs_server *nfss = NFS_SB(mnt->mnt_sb);
356 struct rpc_auth *auth = nfss->client->cl_auth;
357 struct nfs_iostats totals = { };
359 seq_printf(m, "statvers=%s", NFS_IOSTAT_VERS);
362 * Display all mount option settings
364 seq_printf(m, "\n\topts:\t");
365 seq_puts(m, mnt->mnt_sb->s_flags & MS_RDONLY ? "ro" : "rw");
366 seq_puts(m, mnt->mnt_sb->s_flags & MS_SYNCHRONOUS ? ",sync" : "");
367 seq_puts(m, mnt->mnt_sb->s_flags & MS_NOATIME ? ",noatime" : "");
368 seq_puts(m, mnt->mnt_sb->s_flags & MS_NODIRATIME ? ",nodiratime" : "");
369 nfs_show_mount_options(m, nfss, 1);
371 seq_printf(m, "\n\tage:\t%lu", (jiffies - nfss->mount_time) / HZ);
373 seq_printf(m, "\n\tcaps:\t");
374 seq_printf(m, "caps=0x%x", nfss->caps);
375 seq_printf(m, ",wtmult=%d", nfss->wtmult);
376 seq_printf(m, ",dtsize=%d", nfss->dtsize);
377 seq_printf(m, ",bsize=%d", nfss->bsize);
378 seq_printf(m, ",namelen=%d", nfss->namelen);
380 #ifdef CONFIG_NFS_V4
381 if (nfss->nfs_client->cl_nfsversion == 4) {
382 seq_printf(m, "\n\tnfsv4:\t");
383 seq_printf(m, "bm0=0x%x", nfss->attr_bitmask[0]);
384 seq_printf(m, ",bm1=0x%x", nfss->attr_bitmask[1]);
385 seq_printf(m, ",acl=0x%x", nfss->acl_bitmask);
387 #endif
390 * Display security flavor in effect for this mount
392 seq_printf(m, "\n\tsec:\tflavor=%d", auth->au_ops->au_flavor);
393 if (auth->au_flavor)
394 seq_printf(m, ",pseudoflavor=%d", auth->au_flavor);
397 * Display superblock I/O counters
399 for_each_possible_cpu(cpu) {
400 struct nfs_iostats *stats;
402 preempt_disable();
403 stats = per_cpu_ptr(nfss->io_stats, cpu);
405 for (i = 0; i < __NFSIOS_COUNTSMAX; i++)
406 totals.events[i] += stats->events[i];
407 for (i = 0; i < __NFSIOS_BYTESMAX; i++)
408 totals.bytes[i] += stats->bytes[i];
410 preempt_enable();
413 seq_printf(m, "\n\tevents:\t");
414 for (i = 0; i < __NFSIOS_COUNTSMAX; i++)
415 seq_printf(m, "%lu ", totals.events[i]);
416 seq_printf(m, "\n\tbytes:\t");
417 for (i = 0; i < __NFSIOS_BYTESMAX; i++)
418 seq_printf(m, "%Lu ", totals.bytes[i]);
419 seq_printf(m, "\n");
421 rpc_print_iostats(m, nfss->client);
423 return 0;
427 * Begin unmount by attempting to remove all automounted mountpoints we added
428 * in response to xdev traversals and referrals
430 static void nfs_umount_begin(struct vfsmount *vfsmnt, int flags)
432 shrink_submounts(vfsmnt, &nfs_automount_list);
436 * Validate the NFS2/NFS3 mount data
437 * - fills in the mount root filehandle
439 static int nfs_validate_mount_data(struct nfs_mount_data *data,
440 struct nfs_fh *mntfh)
442 if (data == NULL) {
443 dprintk("%s: missing data argument\n", __FUNCTION__);
444 return -EINVAL;
447 if (data->version <= 0 || data->version > NFS_MOUNT_VERSION) {
448 dprintk("%s: bad mount version\n", __FUNCTION__);
449 return -EINVAL;
452 switch (data->version) {
453 case 1:
454 data->namlen = 0;
455 case 2:
456 data->bsize = 0;
457 case 3:
458 if (data->flags & NFS_MOUNT_VER3) {
459 dprintk("%s: mount structure version %d does not support NFSv3\n",
460 __FUNCTION__,
461 data->version);
462 return -EINVAL;
464 data->root.size = NFS2_FHSIZE;
465 memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE);
466 case 4:
467 if (data->flags & NFS_MOUNT_SECFLAVOUR) {
468 dprintk("%s: mount structure version %d does not support strong security\n",
469 __FUNCTION__,
470 data->version);
471 return -EINVAL;
473 case 5:
474 memset(data->context, 0, sizeof(data->context));
477 /* Set the pseudoflavor */
478 if (!(data->flags & NFS_MOUNT_SECFLAVOUR))
479 data->pseudoflavor = RPC_AUTH_UNIX;
481 #ifndef CONFIG_NFS_V3
482 /* If NFSv3 is not compiled in, return -EPROTONOSUPPORT */
483 if (data->flags & NFS_MOUNT_VER3) {
484 dprintk("%s: NFSv3 not compiled into kernel\n", __FUNCTION__);
485 return -EPROTONOSUPPORT;
487 #endif /* CONFIG_NFS_V3 */
489 /* We now require that the mount process passes the remote address */
490 if (data->addr.sin_addr.s_addr == INADDR_ANY) {
491 dprintk("%s: mount program didn't pass remote address!\n",
492 __FUNCTION__);
493 return -EINVAL;
496 /* Prepare the root filehandle */
497 if (data->flags & NFS_MOUNT_VER3)
498 mntfh->size = data->root.size;
499 else
500 mntfh->size = NFS2_FHSIZE;
502 if (mntfh->size > sizeof(mntfh->data)) {
503 dprintk("%s: invalid root filehandle\n", __FUNCTION__);
504 return -EINVAL;
507 memcpy(mntfh->data, data->root.data, mntfh->size);
508 if (mntfh->size < sizeof(mntfh->data))
509 memset(mntfh->data + mntfh->size, 0,
510 sizeof(mntfh->data) - mntfh->size);
512 return 0;
516 * Initialise the common bits of the superblock
518 static inline void nfs_initialise_sb(struct super_block *sb)
520 struct nfs_server *server = NFS_SB(sb);
522 sb->s_magic = NFS_SUPER_MAGIC;
524 /* We probably want something more informative here */
525 snprintf(sb->s_id, sizeof(sb->s_id),
526 "%x:%x", MAJOR(sb->s_dev), MINOR(sb->s_dev));
528 if (sb->s_blocksize == 0)
529 sb->s_blocksize = nfs_block_bits(server->wsize,
530 &sb->s_blocksize_bits);
532 if (server->flags & NFS_MOUNT_NOAC)
533 sb->s_flags |= MS_SYNCHRONOUS;
535 nfs_super_set_maxbytes(sb, server->maxfilesize);
539 * Finish setting up an NFS2/3 superblock
541 static void nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data)
543 struct nfs_server *server = NFS_SB(sb);
545 sb->s_blocksize_bits = 0;
546 sb->s_blocksize = 0;
547 if (data->bsize)
548 sb->s_blocksize = nfs_block_size(data->bsize, &sb->s_blocksize_bits);
550 if (server->flags & NFS_MOUNT_VER3) {
551 /* The VFS shouldn't apply the umask to mode bits. We will do
552 * so ourselves when necessary.
554 sb->s_flags |= MS_POSIXACL;
555 sb->s_time_gran = 1;
558 sb->s_op = &nfs_sops;
559 nfs_initialise_sb(sb);
563 * Finish setting up a cloned NFS2/3 superblock
565 static void nfs_clone_super(struct super_block *sb,
566 const struct super_block *old_sb)
568 struct nfs_server *server = NFS_SB(sb);
570 sb->s_blocksize_bits = old_sb->s_blocksize_bits;
571 sb->s_blocksize = old_sb->s_blocksize;
572 sb->s_maxbytes = old_sb->s_maxbytes;
574 if (server->flags & NFS_MOUNT_VER3) {
575 /* The VFS shouldn't apply the umask to mode bits. We will do
576 * so ourselves when necessary.
578 sb->s_flags |= MS_POSIXACL;
579 sb->s_time_gran = 1;
582 sb->s_op = old_sb->s_op;
583 nfs_initialise_sb(sb);
586 static int nfs_set_super(struct super_block *s, void *_server)
588 struct nfs_server *server = _server;
589 int ret;
591 s->s_fs_info = server;
592 ret = set_anon_super(s, server);
593 if (ret == 0)
594 server->s_dev = s->s_dev;
595 return ret;
598 static int nfs_compare_super(struct super_block *sb, void *data)
600 struct nfs_server *server = data, *old = NFS_SB(sb);
602 if (old->nfs_client != server->nfs_client)
603 return 0;
604 if (memcmp(&old->fsid, &server->fsid, sizeof(old->fsid)) != 0)
605 return 0;
606 return 1;
609 static int nfs_get_sb(struct file_system_type *fs_type,
610 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
612 struct nfs_server *server = NULL;
613 struct super_block *s;
614 struct nfs_fh mntfh;
615 struct nfs_mount_data *data = raw_data;
616 struct dentry *mntroot;
617 int error;
619 /* Validate the mount data */
620 error = nfs_validate_mount_data(data, &mntfh);
621 if (error < 0)
622 return error;
624 /* Get a volume representation */
625 server = nfs_create_server(data, &mntfh);
626 if (IS_ERR(server)) {
627 error = PTR_ERR(server);
628 goto out_err_noserver;
631 /* Get a superblock - note that we may end up sharing one that already exists */
632 s = sget(fs_type, nfs_compare_super, nfs_set_super, server);
633 if (IS_ERR(s)) {
634 error = PTR_ERR(s);
635 goto out_err_nosb;
638 if (s->s_fs_info != server) {
639 nfs_free_server(server);
640 server = NULL;
643 if (!s->s_root) {
644 /* initial superblock/root creation */
645 s->s_flags = flags;
646 nfs_fill_super(s, data);
649 mntroot = nfs_get_root(s, &mntfh);
650 if (IS_ERR(mntroot)) {
651 error = PTR_ERR(mntroot);
652 goto error_splat_super;
655 s->s_flags |= MS_ACTIVE;
656 mnt->mnt_sb = s;
657 mnt->mnt_root = mntroot;
658 return 0;
660 out_err_nosb:
661 nfs_free_server(server);
662 out_err_noserver:
663 return error;
665 error_splat_super:
666 up_write(&s->s_umount);
667 deactivate_super(s);
668 return error;
672 * Destroy an NFS2/3 superblock
674 static void nfs_kill_super(struct super_block *s)
676 struct nfs_server *server = NFS_SB(s);
678 kill_anon_super(s);
679 nfs_free_server(server);
683 * Clone an NFS2/3 server record on xdev traversal (FSID-change)
685 static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags,
686 const char *dev_name, void *raw_data,
687 struct vfsmount *mnt)
689 struct nfs_clone_mount *data = raw_data;
690 struct super_block *s;
691 struct nfs_server *server;
692 struct dentry *mntroot;
693 int error;
695 dprintk("--> nfs_xdev_get_sb()\n");
697 /* create a new volume representation */
698 server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr);
699 if (IS_ERR(server)) {
700 error = PTR_ERR(server);
701 goto out_err_noserver;
704 /* Get a superblock - note that we may end up sharing one that already exists */
705 s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server);
706 if (IS_ERR(s)) {
707 error = PTR_ERR(s);
708 goto out_err_nosb;
711 if (s->s_fs_info != server) {
712 nfs_free_server(server);
713 server = NULL;
716 if (!s->s_root) {
717 /* initial superblock/root creation */
718 s->s_flags = flags;
719 nfs_clone_super(s, data->sb);
722 mntroot = nfs_get_root(s, data->fh);
723 if (IS_ERR(mntroot)) {
724 error = PTR_ERR(mntroot);
725 goto error_splat_super;
728 s->s_flags |= MS_ACTIVE;
729 mnt->mnt_sb = s;
730 mnt->mnt_root = mntroot;
732 dprintk("<-- nfs_xdev_get_sb() = 0\n");
733 return 0;
735 out_err_nosb:
736 nfs_free_server(server);
737 out_err_noserver:
738 dprintk("<-- nfs_xdev_get_sb() = %d [error]\n", error);
739 return error;
741 error_splat_super:
742 up_write(&s->s_umount);
743 deactivate_super(s);
744 dprintk("<-- nfs_xdev_get_sb() = %d [splat]\n", error);
745 return error;
748 #ifdef CONFIG_NFS_V4
751 * Finish setting up a cloned NFS4 superblock
753 static void nfs4_clone_super(struct super_block *sb,
754 const struct super_block *old_sb)
756 sb->s_blocksize_bits = old_sb->s_blocksize_bits;
757 sb->s_blocksize = old_sb->s_blocksize;
758 sb->s_maxbytes = old_sb->s_maxbytes;
759 sb->s_time_gran = 1;
760 sb->s_op = old_sb->s_op;
761 nfs_initialise_sb(sb);
765 * Set up an NFS4 superblock
767 static void nfs4_fill_super(struct super_block *sb)
769 sb->s_time_gran = 1;
770 sb->s_op = &nfs4_sops;
771 nfs_initialise_sb(sb);
774 static void *nfs_copy_user_string(char *dst, struct nfs_string *src, int maxlen)
776 void *p = NULL;
778 if (!src->len)
779 return ERR_PTR(-EINVAL);
780 if (src->len < maxlen)
781 maxlen = src->len;
782 if (dst == NULL) {
783 p = dst = kmalloc(maxlen + 1, GFP_KERNEL);
784 if (p == NULL)
785 return ERR_PTR(-ENOMEM);
787 if (copy_from_user(dst, src->data, maxlen)) {
788 kfree(p);
789 return ERR_PTR(-EFAULT);
791 dst[maxlen] = '\0';
792 return dst;
796 * Get the superblock for an NFS4 mountpoint
798 static int nfs4_get_sb(struct file_system_type *fs_type,
799 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
801 struct nfs4_mount_data *data = raw_data;
802 struct super_block *s;
803 struct nfs_server *server;
804 struct sockaddr_in addr;
805 rpc_authflavor_t authflavour;
806 struct nfs_fh mntfh;
807 struct dentry *mntroot;
808 char *mntpath = NULL, *hostname = NULL, ip_addr[16];
809 void *p;
810 int error;
812 if (data == NULL) {
813 dprintk("%s: missing data argument\n", __FUNCTION__);
814 return -EINVAL;
816 if (data->version <= 0 || data->version > NFS4_MOUNT_VERSION) {
817 dprintk("%s: bad mount version\n", __FUNCTION__);
818 return -EINVAL;
821 /* We now require that the mount process passes the remote address */
822 if (data->host_addrlen != sizeof(addr))
823 return -EINVAL;
825 if (copy_from_user(&addr, data->host_addr, sizeof(addr)))
826 return -EFAULT;
828 if (addr.sin_family != AF_INET ||
829 addr.sin_addr.s_addr == INADDR_ANY
831 dprintk("%s: mount program didn't pass remote IP address!\n",
832 __FUNCTION__);
833 return -EINVAL;
835 /* RFC3530: The default port for NFS is 2049 */
836 if (addr.sin_port == 0)
837 addr.sin_port = htons(NFS_PORT);
839 /* Grab the authentication type */
840 authflavour = RPC_AUTH_UNIX;
841 if (data->auth_flavourlen != 0) {
842 if (data->auth_flavourlen != 1) {
843 dprintk("%s: Invalid number of RPC auth flavours %d.\n",
844 __FUNCTION__, data->auth_flavourlen);
845 error = -EINVAL;
846 goto out_err_noserver;
849 if (copy_from_user(&authflavour, data->auth_flavours,
850 sizeof(authflavour))) {
851 error = -EFAULT;
852 goto out_err_noserver;
856 p = nfs_copy_user_string(NULL, &data->hostname, 256);
857 if (IS_ERR(p))
858 goto out_err;
859 hostname = p;
861 p = nfs_copy_user_string(NULL, &data->mnt_path, 1024);
862 if (IS_ERR(p))
863 goto out_err;
864 mntpath = p;
866 dprintk("MNTPATH: %s\n", mntpath);
868 p = nfs_copy_user_string(ip_addr, &data->client_addr,
869 sizeof(ip_addr) - 1);
870 if (IS_ERR(p))
871 goto out_err;
873 /* Get a volume representation */
874 server = nfs4_create_server(data, hostname, &addr, mntpath, ip_addr,
875 authflavour, &mntfh);
876 if (IS_ERR(server)) {
877 error = PTR_ERR(server);
878 goto out_err_noserver;
881 /* Get a superblock - note that we may end up sharing one that already exists */
882 s = sget(fs_type, nfs_compare_super, nfs_set_super, server);
883 if (IS_ERR(s)) {
884 error = PTR_ERR(s);
885 goto out_free;
888 if (s->s_fs_info != server) {
889 nfs_free_server(server);
890 server = NULL;
893 if (!s->s_root) {
894 /* initial superblock/root creation */
895 s->s_flags = flags;
896 nfs4_fill_super(s);
899 mntroot = nfs4_get_root(s, &mntfh);
900 if (IS_ERR(mntroot)) {
901 error = PTR_ERR(mntroot);
902 goto error_splat_super;
905 s->s_flags |= MS_ACTIVE;
906 mnt->mnt_sb = s;
907 mnt->mnt_root = mntroot;
908 kfree(mntpath);
909 kfree(hostname);
910 return 0;
912 out_err:
913 error = PTR_ERR(p);
914 goto out_err_noserver;
916 out_free:
917 nfs_free_server(server);
918 out_err_noserver:
919 kfree(mntpath);
920 kfree(hostname);
921 return error;
923 error_splat_super:
924 up_write(&s->s_umount);
925 deactivate_super(s);
926 goto out_err_noserver;
929 static void nfs4_kill_super(struct super_block *sb)
931 struct nfs_server *server = NFS_SB(sb);
933 nfs_return_all_delegations(sb);
934 kill_anon_super(sb);
936 nfs4_renewd_prepare_shutdown(server);
937 nfs_free_server(server);
941 * Clone an NFS4 server record on xdev traversal (FSID-change)
943 static int nfs4_xdev_get_sb(struct file_system_type *fs_type, int flags,
944 const char *dev_name, void *raw_data,
945 struct vfsmount *mnt)
947 struct nfs_clone_mount *data = raw_data;
948 struct super_block *s;
949 struct nfs_server *server;
950 struct dentry *mntroot;
951 int error;
953 dprintk("--> nfs4_xdev_get_sb()\n");
955 /* create a new volume representation */
956 server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr);
957 if (IS_ERR(server)) {
958 error = PTR_ERR(server);
959 goto out_err_noserver;
962 /* Get a superblock - note that we may end up sharing one that already exists */
963 s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server);
964 if (IS_ERR(s)) {
965 error = PTR_ERR(s);
966 goto out_err_nosb;
969 if (s->s_fs_info != server) {
970 nfs_free_server(server);
971 server = NULL;
974 if (!s->s_root) {
975 /* initial superblock/root creation */
976 s->s_flags = flags;
977 nfs4_clone_super(s, data->sb);
980 mntroot = nfs4_get_root(s, data->fh);
981 if (IS_ERR(mntroot)) {
982 error = PTR_ERR(mntroot);
983 goto error_splat_super;
986 s->s_flags |= MS_ACTIVE;
987 mnt->mnt_sb = s;
988 mnt->mnt_root = mntroot;
990 dprintk("<-- nfs4_xdev_get_sb() = 0\n");
991 return 0;
993 out_err_nosb:
994 nfs_free_server(server);
995 out_err_noserver:
996 dprintk("<-- nfs4_xdev_get_sb() = %d [error]\n", error);
997 return error;
999 error_splat_super:
1000 up_write(&s->s_umount);
1001 deactivate_super(s);
1002 dprintk("<-- nfs4_xdev_get_sb() = %d [splat]\n", error);
1003 return error;
1007 * Create an NFS4 server record on referral traversal
1009 static int nfs4_referral_get_sb(struct file_system_type *fs_type, int flags,
1010 const char *dev_name, void *raw_data,
1011 struct vfsmount *mnt)
1013 struct nfs_clone_mount *data = raw_data;
1014 struct super_block *s;
1015 struct nfs_server *server;
1016 struct dentry *mntroot;
1017 struct nfs_fh mntfh;
1018 int error;
1020 dprintk("--> nfs4_referral_get_sb()\n");
1022 /* create a new volume representation */
1023 server = nfs4_create_referral_server(data, &mntfh);
1024 if (IS_ERR(server)) {
1025 error = PTR_ERR(server);
1026 goto out_err_noserver;
1029 /* Get a superblock - note that we may end up sharing one that already exists */
1030 s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server);
1031 if (IS_ERR(s)) {
1032 error = PTR_ERR(s);
1033 goto out_err_nosb;
1036 if (s->s_fs_info != server) {
1037 nfs_free_server(server);
1038 server = NULL;
1041 if (!s->s_root) {
1042 /* initial superblock/root creation */
1043 s->s_flags = flags;
1044 nfs4_fill_super(s);
1047 mntroot = nfs4_get_root(s, data->fh);
1048 if (IS_ERR(mntroot)) {
1049 error = PTR_ERR(mntroot);
1050 goto error_splat_super;
1053 s->s_flags |= MS_ACTIVE;
1054 mnt->mnt_sb = s;
1055 mnt->mnt_root = mntroot;
1057 dprintk("<-- nfs4_referral_get_sb() = 0\n");
1058 return 0;
1060 out_err_nosb:
1061 nfs_free_server(server);
1062 out_err_noserver:
1063 dprintk("<-- nfs4_referral_get_sb() = %d [error]\n", error);
1064 return error;
1066 error_splat_super:
1067 up_write(&s->s_umount);
1068 deactivate_super(s);
1069 dprintk("<-- nfs4_referral_get_sb() = %d [splat]\n", error);
1070 return error;
1073 #endif /* CONFIG_NFS_V4 */