aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/super.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/super.c')
-rw-r--r--fs/nfs/super.c1207
1 files changed, 444 insertions, 763 deletions
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 5842d510d732..867b5dcd3a40 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -13,6 +13,11 @@
13 * 13 *
14 * Split from inode.c by David Howells <dhowells@redhat.com> 14 * Split from inode.c by David Howells <dhowells@redhat.com>
15 * 15 *
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())
16 */ 21 */
17 22
18#include <linux/config.h> 23#include <linux/config.h>
@@ -52,20 +57,12 @@
52 57
53#define NFSDBG_FACILITY NFSDBG_VFS 58#define NFSDBG_FACILITY NFSDBG_VFS
54 59
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
63static void nfs_umount_begin(struct vfsmount *, int); 60static void nfs_umount_begin(struct vfsmount *, int);
64static int nfs_statfs(struct dentry *, struct kstatfs *); 61static int nfs_statfs(struct dentry *, struct kstatfs *);
65static int nfs_show_options(struct seq_file *, struct vfsmount *); 62static int nfs_show_options(struct seq_file *, struct vfsmount *);
66static int nfs_show_stats(struct seq_file *, struct vfsmount *); 63static int nfs_show_stats(struct seq_file *, struct vfsmount *);
67static int nfs_get_sb(struct file_system_type *, int, const char *, void *, struct vfsmount *); 64static int nfs_get_sb(struct file_system_type *, int, const char *, void *, struct vfsmount *);
68static int nfs_clone_nfs_sb(struct file_system_type *fs_type, 65static int nfs_xdev_get_sb(struct file_system_type *fs_type,
69 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); 66 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);
70static void nfs_kill_super(struct super_block *); 67static void nfs_kill_super(struct super_block *);
71 68
@@ -77,10 +74,10 @@ static struct file_system_type nfs_fs_type = {
77 .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, 74 .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
78}; 75};
79 76
80struct file_system_type clone_nfs_fs_type = { 77struct file_system_type nfs_xdev_fs_type = {
81 .owner = THIS_MODULE, 78 .owner = THIS_MODULE,
82 .name = "nfs", 79 .name = "nfs",
83 .get_sb = nfs_clone_nfs_sb, 80 .get_sb = nfs_xdev_get_sb,
84 .kill_sb = nfs_kill_super, 81 .kill_sb = nfs_kill_super,
85 .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, 82 .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
86}; 83};
@@ -99,10 +96,10 @@ static struct super_operations nfs_sops = {
99#ifdef CONFIG_NFS_V4 96#ifdef CONFIG_NFS_V4
100static int nfs4_get_sb(struct file_system_type *fs_type, 97static int nfs4_get_sb(struct file_system_type *fs_type,
101 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); 98 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);
102static int nfs_clone_nfs4_sb(struct file_system_type *fs_type, 99static int nfs4_xdev_get_sb(struct file_system_type *fs_type,
103 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); 100 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);
104static int nfs_referral_nfs4_sb(struct file_system_type *fs_type, 101static int nfs4_referral_get_sb(struct file_system_type *fs_type,
105 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); 102 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);
106static void nfs4_kill_super(struct super_block *sb); 103static void nfs4_kill_super(struct super_block *sb);
107 104
108static struct file_system_type nfs4_fs_type = { 105static struct file_system_type nfs4_fs_type = {
@@ -113,18 +110,18 @@ static struct file_system_type nfs4_fs_type = {
113 .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, 110 .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
114}; 111};
115 112
116struct file_system_type clone_nfs4_fs_type = { 113struct file_system_type nfs4_xdev_fs_type = {
117 .owner = THIS_MODULE, 114 .owner = THIS_MODULE,
118 .name = "nfs4", 115 .name = "nfs4",
119 .get_sb = nfs_clone_nfs4_sb, 116 .get_sb = nfs4_xdev_get_sb,
120 .kill_sb = nfs4_kill_super, 117 .kill_sb = nfs4_kill_super,
121 .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, 118 .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
122}; 119};
123 120
124struct file_system_type nfs_referral_nfs4_fs_type = { 121struct file_system_type nfs4_referral_fs_type = {
125 .owner = THIS_MODULE, 122 .owner = THIS_MODULE,
126 .name = "nfs4", 123 .name = "nfs4",
127 .get_sb = nfs_referral_nfs4_sb, 124 .get_sb = nfs4_referral_get_sb,
128 .kill_sb = nfs4_kill_super, 125 .kill_sb = nfs4_kill_super,
129 .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, 126 .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
130}; 127};
@@ -345,7 +342,7 @@ static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt)
345 nfs_show_mount_options(m, nfss, 0); 342 nfs_show_mount_options(m, nfss, 0);
346 343
347 seq_puts(m, ",addr="); 344 seq_puts(m, ",addr=");
348 seq_escape(m, nfss->hostname, " \t\n\\"); 345 seq_escape(m, nfss->nfs_client->cl_hostname, " \t\n\\");
349 346
350 return 0; 347 return 0;
351} 348}
@@ -429,714 +426,351 @@ static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt)
429 426
430/* 427/*
431 * Begin unmount by attempting to remove all automounted mountpoints we added 428 * Begin unmount by attempting to remove all automounted mountpoints we added
432 * in response to traversals 429 * in response to xdev traversals and referrals
433 */ 430 */
434static void nfs_umount_begin(struct vfsmount *vfsmnt, int flags) 431static void nfs_umount_begin(struct vfsmount *vfsmnt, int flags)
435{ 432{
436 struct nfs_server *server;
437 struct rpc_clnt *rpc;
438
439 shrink_submounts(vfsmnt, &nfs_automount_list); 433 shrink_submounts(vfsmnt, &nfs_automount_list);
440 if (!(flags & MNT_FORCE))
441 return;
442 /* -EIO all pending I/O */
443 server = NFS_SB(vfsmnt->mnt_sb);
444 rpc = server->client;
445 if (!IS_ERR(rpc))
446 rpc_killall_tasks(rpc);
447 rpc = server->client_acl;
448 if (!IS_ERR(rpc))
449 rpc_killall_tasks(rpc);
450} 434}
451 435
452/* 436/*
453 * Obtain the root inode of the file system. 437 * Validate the NFS2/NFS3 mount data
438 * - fills in the mount root filehandle
454 */ 439 */
455static struct inode * 440static int nfs_validate_mount_data(struct nfs_mount_data *data,
456nfs_get_root(struct super_block *sb, struct nfs_fh *rootfh, struct nfs_fsinfo *fsinfo) 441 struct nfs_fh *mntfh)
457{ 442{
458 struct nfs_server *server = NFS_SB(sb); 443 if (data == NULL) {
459 int error; 444 dprintk("%s: missing data argument\n", __FUNCTION__);
460 445 return -EINVAL;
461 error = server->nfs_client->rpc_ops->getroot(server, rootfh, fsinfo);
462 if (error < 0) {
463 dprintk("nfs_get_root: getattr error = %d\n", -error);
464 return ERR_PTR(error);
465 } 446 }
466 447
467 server->fsid = fsinfo->fattr->fsid; 448 if (data->version <= 0 || data->version > NFS_MOUNT_VERSION) {
468 return nfs_fhget(sb, rootfh, fsinfo->fattr); 449 dprintk("%s: bad mount version\n", __FUNCTION__);
469} 450 return -EINVAL;
470 451 }
471/*
472 * Do NFS version-independent mount processing, and sanity checking
473 */
474static int
475nfs_sb_init(struct super_block *sb, rpc_authflavor_t authflavor)
476{
477 struct nfs_server *server;
478 struct inode *root_inode;
479 struct nfs_fattr fattr;
480 struct nfs_fsinfo fsinfo = {
481 .fattr = &fattr,
482 };
483 struct nfs_pathconf pathinfo = {
484 .fattr = &fattr,
485 };
486 int no_root_error = 0;
487 unsigned long max_rpc_payload;
488
489 /* We probably want something more informative here */
490 snprintf(sb->s_id, sizeof(sb->s_id), "%x:%x", MAJOR(sb->s_dev), MINOR(sb->s_dev));
491
492 server = NFS_SB(sb);
493
494 sb->s_magic = NFS_SUPER_MAGIC;
495
496 server->io_stats = nfs_alloc_iostats();
497 if (server->io_stats == NULL)
498 return -ENOMEM;
499 452
500 root_inode = nfs_get_root(sb, &server->fh, &fsinfo); 453 switch (data->version) {
501 /* Did getting the root inode fail? */ 454 case 1:
502 if (IS_ERR(root_inode)) { 455 data->namlen = 0;
503 no_root_error = PTR_ERR(root_inode); 456 case 2:
504 goto out_no_root; 457 data->bsize = 0;
458 case 3:
459 if (data->flags & NFS_MOUNT_VER3) {
460 dprintk("%s: mount structure version %d does not support NFSv3\n",
461 __FUNCTION__,
462 data->version);
463 return -EINVAL;
464 }
465 data->root.size = NFS2_FHSIZE;
466 memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE);
467 case 4:
468 if (data->flags & NFS_MOUNT_SECFLAVOUR) {
469 dprintk("%s: mount structure version %d does not support strong security\n",
470 __FUNCTION__,
471 data->version);
472 return -EINVAL;
473 }
474 /* Fill in pseudoflavor for mount version < 5 */
475 data->pseudoflavor = RPC_AUTH_UNIX;
476 case 5:
477 memset(data->context, 0, sizeof(data->context));
505 } 478 }
506 sb->s_root = d_alloc_root(root_inode); 479
507 if (!sb->s_root) { 480#ifndef CONFIG_NFS_V3
508 no_root_error = -ENOMEM; 481 /* If NFSv3 is not compiled in, return -EPROTONOSUPPORT */
509 goto out_no_root; 482 if (data->flags & NFS_MOUNT_VER3) {
483 dprintk("%s: NFSv3 not compiled into kernel\n", __FUNCTION__);
484 return -EPROTONOSUPPORT;
510 } 485 }
511 sb->s_root->d_op = server->nfs_client->rpc_ops->dentry_ops; 486#endif /* CONFIG_NFS_V3 */
512
513 /* mount time stamp, in seconds */
514 server->mount_time = jiffies;
515
516 /* Get some general file system info */
517 if (server->namelen == 0 &&
518 server->nfs_client->rpc_ops->pathconf(server, &server->fh, &pathinfo) >= 0)
519 server->namelen = pathinfo.max_namelen;
520 /* Work out a lot of parameters */
521 if (server->rsize == 0)
522 server->rsize = nfs_block_size(fsinfo.rtpref, NULL);
523 if (server->wsize == 0)
524 server->wsize = nfs_block_size(fsinfo.wtpref, NULL);
525
526 if (fsinfo.rtmax >= 512 && server->rsize > fsinfo.rtmax)
527 server->rsize = nfs_block_size(fsinfo.rtmax, NULL);
528 if (fsinfo.wtmax >= 512 && server->wsize > fsinfo.wtmax)
529 server->wsize = nfs_block_size(fsinfo.wtmax, NULL);
530
531 max_rpc_payload = nfs_block_size(rpc_max_payload(server->client), NULL);
532 if (server->rsize > max_rpc_payload)
533 server->rsize = max_rpc_payload;
534 if (server->rsize > NFS_MAX_FILE_IO_SIZE)
535 server->rsize = NFS_MAX_FILE_IO_SIZE;
536 server->rpages = (server->rsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
537
538 if (server->wsize > max_rpc_payload)
539 server->wsize = max_rpc_payload;
540 if (server->wsize > NFS_MAX_FILE_IO_SIZE)
541 server->wsize = NFS_MAX_FILE_IO_SIZE;
542 server->wpages = (server->wsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
543 487
544 if (sb->s_blocksize == 0) 488 /* We now require that the mount process passes the remote address */
545 sb->s_blocksize = nfs_block_bits(server->wsize, 489 if (data->addr.sin_addr.s_addr == INADDR_ANY) {
546 &sb->s_blocksize_bits); 490 dprintk("%s: mount program didn't pass remote address!\n",
547 server->wtmult = nfs_block_bits(fsinfo.wtmult, NULL); 491 __FUNCTION__);
548 492 return -EINVAL;
549 server->dtsize = nfs_block_size(fsinfo.dtpref, NULL);
550 if (server->dtsize > PAGE_CACHE_SIZE)
551 server->dtsize = PAGE_CACHE_SIZE;
552 if (server->dtsize > server->rsize)
553 server->dtsize = server->rsize;
554
555 if (server->flags & NFS_MOUNT_NOAC) {
556 server->acregmin = server->acregmax = 0;
557 server->acdirmin = server->acdirmax = 0;
558 sb->s_flags |= MS_SYNCHRONOUS;
559 } 493 }
560 server->backing_dev_info.ra_pages = server->rpages * NFS_MAX_READAHEAD;
561 494
562 nfs_super_set_maxbytes(sb, fsinfo.maxfilesize); 495 /* Prepare the root filehandle */
496 if (data->flags & NFS_MOUNT_VER3)
497 mntfh->size = data->root.size;
498 else
499 mntfh->size = NFS2_FHSIZE;
563 500
564 server->client->cl_intr = (server->flags & NFS_MOUNT_INTR) ? 1 : 0; 501 if (mntfh->size > sizeof(mntfh->data)) {
565 server->client->cl_softrtry = (server->flags & NFS_MOUNT_SOFT) ? 1 : 0; 502 dprintk("%s: invalid root filehandle\n", __FUNCTION__);
503 return -EINVAL;
504 }
505
506 memcpy(mntfh->data, data->root.data, mntfh->size);
507 if (mntfh->size < sizeof(mntfh->data))
508 memset(mntfh->data + mntfh->size, 0,
509 sizeof(mntfh->data) - mntfh->size);
566 510
567 /* We're airborne Set socket buffersize */
568 rpc_setbufsize(server->client, server->wsize + 100, server->rsize + 100);
569 return 0; 511 return 0;
570 /* Yargs. It didn't work out. */
571out_no_root:
572 dprintk("nfs_sb_init: get root inode failed: errno %d\n", -no_root_error);
573 if (!IS_ERR(root_inode))
574 iput(root_inode);
575 return no_root_error;
576} 512}
577 513
578/* 514/*
579 * Create an RPC client handle. 515 * Initialise the common bits of the superblock
580 */ 516 */
581static struct rpc_clnt * 517static inline void nfs_initialise_sb(struct super_block *sb)
582nfs_create_client(struct nfs_server *server, const struct nfs_mount_data *data)
583{ 518{
584 struct nfs_client *clp; 519 struct nfs_server *server = NFS_SB(sb);
585 struct rpc_clnt *clnt;
586 int proto = (data->flags & NFS_MOUNT_TCP) ? IPPROTO_TCP : IPPROTO_UDP;
587 int nfsversion = 2;
588 int err;
589
590#ifdef CONFIG_NFS_V3
591 if (server->flags & NFS_MOUNT_VER3)
592 nfsversion = 3;
593#endif
594
595 clp = nfs_get_client(server->hostname, &server->addr, nfsversion);
596 if (!clp) {
597 dprintk("%s: failed to create NFS4 client.\n", __FUNCTION__);
598 return ERR_PTR(PTR_ERR(clp));
599 }
600
601 if (clp->cl_cons_state == NFS_CS_INITING) {
602 /* Check NFS protocol revision and initialize RPC op
603 * vector and file handle pool. */
604#ifdef CONFIG_NFS_V3
605 if (nfsversion == 3) {
606 clp->rpc_ops = &nfs_v3_clientops;
607 server->caps |= NFS_CAP_READDIRPLUS;
608 } else {
609 clp->rpc_ops = &nfs_v2_clientops;
610 }
611#else
612 clp->rpc_ops = &nfs_v2_clientops;
613#endif
614
615 /* create transport and client */
616 err = nfs_create_rpc_client(clp, proto, data->timeo,
617 data->retrans, RPC_AUTH_UNIX);
618 if (err < 0)
619 goto client_init_error;
620
621 nfs_mark_client_ready(clp, 0);
622 }
623 520
624 /* create an nfs_server-specific client */ 521 sb->s_magic = NFS_SUPER_MAGIC;
625 clnt = rpc_clone_client(clp->cl_rpcclient);
626 if (IS_ERR(clnt)) {
627 dprintk("%s: couldn't create rpc_client!\n", __FUNCTION__);
628 nfs_put_client(clp);
629 return ERR_PTR(PTR_ERR(clnt));
630 }
631 522
632 if (data->pseudoflavor != clp->cl_rpcclient->cl_auth->au_flavor) { 523 /* We probably want something more informative here */
633 struct rpc_auth *auth; 524 snprintf(sb->s_id, sizeof(sb->s_id),
525 "%x:%x", MAJOR(sb->s_dev), MINOR(sb->s_dev));
634 526
635 auth = rpcauth_create(data->pseudoflavor, server->client); 527 if (sb->s_blocksize == 0)
636 if (IS_ERR(auth)) { 528 sb->s_blocksize = nfs_block_bits(server->wsize,
637 dprintk("%s: couldn't create credcache!\n", __FUNCTION__); 529 &sb->s_blocksize_bits);
638 return ERR_PTR(PTR_ERR(auth));
639 }
640 }
641 530
642 server->nfs_client = clp; 531 if (server->flags & NFS_MOUNT_NOAC)
643 return clnt; 532 sb->s_flags |= MS_SYNCHRONOUS;
644 533
645client_init_error: 534 nfs_super_set_maxbytes(sb, server->maxfilesize);
646 nfs_mark_client_ready(clp, err);
647 nfs_put_client(clp);
648 return ERR_PTR(err);
649} 535}
650 536
651/* 537/*
652 * Clone a server record 538 * Finish setting up an NFS2/3 superblock
653 */ 539 */
654static struct nfs_server *nfs_clone_server(struct super_block *sb, struct nfs_clone_mount *data) 540static void nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data)
655{ 541{
656 struct nfs_server *server = NFS_SB(sb); 542 struct nfs_server *server = NFS_SB(sb);
657 struct nfs_server *parent = NFS_SB(data->sb);
658 struct inode *root_inode;
659 struct nfs_fsinfo fsinfo;
660 void *err = ERR_PTR(-ENOMEM);
661
662 sb->s_op = data->sb->s_op;
663 sb->s_blocksize = data->sb->s_blocksize;
664 sb->s_blocksize_bits = data->sb->s_blocksize_bits;
665 sb->s_maxbytes = data->sb->s_maxbytes;
666
667 server->client_acl = ERR_PTR(-EINVAL);
668 server->io_stats = nfs_alloc_iostats();
669 if (server->io_stats == NULL)
670 goto out;
671
672 server->client = rpc_clone_client(parent->client);
673 if (IS_ERR((err = server->client)))
674 goto out;
675
676 if (!IS_ERR(parent->client_acl)) {
677 server->client_acl = rpc_clone_client(parent->client_acl);
678 if (IS_ERR((err = server->client_acl)))
679 goto out;
680 }
681 root_inode = nfs_fhget(sb, data->fh, data->fattr);
682 if (!root_inode)
683 goto out;
684 sb->s_root = d_alloc_root(root_inode);
685 if (!sb->s_root)
686 goto out_put_root;
687 fsinfo.fattr = data->fattr;
688 if (NFS_PROTO(root_inode)->fsinfo(server, data->fh, &fsinfo) == 0)
689 nfs_super_set_maxbytes(sb, fsinfo.maxfilesize);
690 sb->s_root->d_op = server->nfs_client->rpc_ops->dentry_ops;
691 sb->s_flags |= MS_ACTIVE;
692 return server;
693out_put_root:
694 iput(root_inode);
695out:
696 return err;
697}
698
699/*
700 * Copy an existing superblock and attach revised data
701 */
702static int nfs_clone_generic_sb(struct nfs_clone_mount *data,
703 struct super_block *(*fill_sb)(struct nfs_server *, struct nfs_clone_mount *),
704 struct nfs_server *(*fill_server)(struct super_block *, struct nfs_clone_mount *),
705 struct vfsmount *mnt)
706{
707 struct nfs_server *server;
708 struct nfs_server *parent = NFS_SB(data->sb);
709 struct super_block *sb = ERR_PTR(-EINVAL);
710 char *hostname;
711 int error = -ENOMEM;
712 int len;
713
714 server = kmalloc(sizeof(struct nfs_server), GFP_KERNEL);
715 if (server == NULL)
716 goto out_err;
717 memcpy(server, parent, sizeof(*server));
718 atomic_inc(&server->nfs_client->cl_count);
719 hostname = (data->hostname != NULL) ? data->hostname : parent->hostname;
720 len = strlen(hostname) + 1;
721 server->hostname = kmalloc(len, GFP_KERNEL);
722 if (server->hostname == NULL)
723 goto free_server;
724 memcpy(server->hostname, hostname, len);
725
726 sb = fill_sb(server, data);
727 if (IS_ERR(sb)) {
728 error = PTR_ERR(sb);
729 goto free_hostname;
730 }
731 543
732 if (sb->s_root) 544 sb->s_blocksize_bits = 0;
733 goto out_share; 545 sb->s_blocksize = 0;
546 if (data->bsize)
547 sb->s_blocksize = nfs_block_size(data->bsize, &sb->s_blocksize_bits);
734 548
735 server = fill_server(sb, data); 549 if (server->flags & NFS_MOUNT_VER3) {
736 if (IS_ERR(server)) { 550 /* The VFS shouldn't apply the umask to mode bits. We will do
737 error = PTR_ERR(server); 551 * so ourselves when necessary.
738 goto out_deactivate; 552 */
553 sb->s_flags |= MS_POSIXACL;
554 sb->s_time_gran = 1;
739 } 555 }
740 return simple_set_mnt(mnt, sb); 556
741out_deactivate: 557 sb->s_op = &nfs_sops;
742 up_write(&sb->s_umount); 558 nfs_initialise_sb(sb);
743 deactivate_super(sb);
744 return error;
745out_share:
746 kfree(server->hostname);
747 nfs_put_client(server->nfs_client);
748 kfree(server);
749 return simple_set_mnt(mnt, sb);
750free_hostname:
751 kfree(server->hostname);
752free_server:
753 nfs_put_client(server->nfs_client);
754 kfree(server);
755out_err:
756 return error;
757} 559}
758 560
759/* 561/*
760 * Set up an NFS2/3 superblock 562 * Finish setting up a cloned NFS2/3 superblock
761 *
762 * The way this works is that the mount process passes a structure
763 * in the data argument which contains the server's IP address
764 * and the root file handle obtained from the server's mount
765 * daemon. We stash these away in the private superblock fields.
766 */ 563 */
767static int 564static void nfs_clone_super(struct super_block *sb,
768nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data, int silent) 565 const struct super_block *old_sb)
769{ 566{
770 struct nfs_server *server; 567 struct nfs_server *server = NFS_SB(sb);
771 rpc_authflavor_t authflavor; 568
569 sb->s_blocksize_bits = old_sb->s_blocksize_bits;
570 sb->s_blocksize = old_sb->s_blocksize;
571 sb->s_maxbytes = old_sb->s_maxbytes;
772 572
773 server = NFS_SB(sb);
774 sb->s_blocksize_bits = 0;
775 sb->s_blocksize = 0;
776 if (data->bsize)
777 sb->s_blocksize = nfs_block_size(data->bsize, &sb->s_blocksize_bits);
778 if (data->rsize)
779 server->rsize = nfs_block_size(data->rsize, NULL);
780 if (data->wsize)
781 server->wsize = nfs_block_size(data->wsize, NULL);
782 server->flags = data->flags & NFS_MOUNT_FLAGMASK;
783
784 server->acregmin = data->acregmin*HZ;
785 server->acregmax = data->acregmax*HZ;
786 server->acdirmin = data->acdirmin*HZ;
787 server->acdirmax = data->acdirmax*HZ;
788
789 /* Start lockd here, before we might error out */
790 if (!(server->flags & NFS_MOUNT_NONLM))
791 lockd_up();
792
793 server->namelen = data->namlen;
794 server->hostname = kmalloc(strlen(data->hostname) + 1, GFP_KERNEL);
795 if (!server->hostname)
796 return -ENOMEM;
797 strcpy(server->hostname, data->hostname);
798
799 /* Fill in pseudoflavor for mount version < 5 */
800 if (!(data->flags & NFS_MOUNT_SECFLAVOUR))
801 data->pseudoflavor = RPC_AUTH_UNIX;
802 authflavor = data->pseudoflavor; /* save for sb_init() */
803 /* XXX maybe we want to add a server->pseudoflavor field */
804
805 /* Create RPC client handles */
806 server->client = nfs_create_client(server, data);
807 if (IS_ERR(server->client))
808 return PTR_ERR(server->client);
809
810 /* RFC 2623, sec 2.3.2 */
811 if (server->flags & NFS_MOUNT_VER3) { 573 if (server->flags & NFS_MOUNT_VER3) {
812#ifdef CONFIG_NFS_V3_ACL 574 /* The VFS shouldn't apply the umask to mode bits. We will do
813 if (!(server->flags & NFS_MOUNT_NOACL)) { 575 * so ourselves when necessary.
814 server->client_acl = rpc_bind_new_program(server->client, &nfsacl_program, 3);
815 /* No errors! Assume that Sun nfsacls are supported */
816 if (!IS_ERR(server->client_acl))
817 server->caps |= NFS_CAP_ACLS;
818 }
819#else
820 server->flags &= ~NFS_MOUNT_NOACL;
821#endif /* CONFIG_NFS_V3_ACL */
822 /*
823 * The VFS shouldn't apply the umask to mode bits. We will
824 * do so ourselves when necessary.
825 */ 576 */
826 sb->s_flags |= MS_POSIXACL; 577 sb->s_flags |= MS_POSIXACL;
827 if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN)
828 server->namelen = NFS3_MAXNAMLEN;
829 sb->s_time_gran = 1; 578 sb->s_time_gran = 1;
830 } else {
831 if (server->namelen == 0 || server->namelen > NFS2_MAXNAMLEN)
832 server->namelen = NFS2_MAXNAMLEN;
833 } 579 }
834 580
835 sb->s_op = &nfs_sops; 581 sb->s_op = old_sb->s_op;
836 return nfs_sb_init(sb, authflavor); 582 nfs_initialise_sb(sb);
837} 583}
838 584
839static int nfs_set_super(struct super_block *s, void *data) 585static int nfs_set_super(struct super_block *s, void *_server)
840{ 586{
841 s->s_fs_info = data; 587 struct nfs_server *server = _server;
842 return set_anon_super(s, data); 588 int ret;
589
590 s->s_fs_info = server;
591 ret = set_anon_super(s, server);
592 if (ret == 0)
593 server->s_dev = s->s_dev;
594 return ret;
843} 595}
844 596
845static int nfs_compare_super(struct super_block *sb, void *data) 597static int nfs_compare_super(struct super_block *sb, void *data)
846{ 598{
847 struct nfs_server *server = data; 599 struct nfs_server *server = data, *old = NFS_SB(sb);
848 struct nfs_server *old = NFS_SB(sb);
849 600
850 if (old->addr.sin_addr.s_addr != server->addr.sin_addr.s_addr) 601 if (old->nfs_client != server->nfs_client)
851 return 0; 602 return 0;
852 if (old->addr.sin_port != server->addr.sin_port) 603 if (memcmp(&old->fsid, &server->fsid, sizeof(old->fsid)) != 0)
853 return 0; 604 return 0;
854 return !nfs_compare_fh(&old->fh, &server->fh); 605 return 1;
855} 606}
856 607
857static int nfs_get_sb(struct file_system_type *fs_type, 608static int nfs_get_sb(struct file_system_type *fs_type,
858 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) 609 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
859{ 610{
860 int error;
861 struct nfs_server *server = NULL; 611 struct nfs_server *server = NULL;
862 struct super_block *s; 612 struct super_block *s;
863 struct nfs_fh *root; 613 struct nfs_fh mntfh;
864 struct nfs_mount_data *data = raw_data; 614 struct nfs_mount_data *data = raw_data;
615 struct dentry *mntroot;
616 int error;
865 617
866 error = -EINVAL; 618 /* Validate the mount data */
867 if (data == NULL) { 619 error = nfs_validate_mount_data(data, &mntfh);
868 dprintk("%s: missing data argument\n", __FUNCTION__); 620 if (error < 0)
869 goto out_err_noserver; 621 return error;
870 }
871 if (data->version <= 0 || data->version > NFS_MOUNT_VERSION) {
872 dprintk("%s: bad mount version\n", __FUNCTION__);
873 goto out_err_noserver;
874 }
875 switch (data->version) {
876 case 1:
877 data->namlen = 0;
878 case 2:
879 data->bsize = 0;
880 case 3:
881 if (data->flags & NFS_MOUNT_VER3) {
882 dprintk("%s: mount structure version %d does not support NFSv3\n",
883 __FUNCTION__,
884 data->version);
885 goto out_err_noserver;
886 }
887 data->root.size = NFS2_FHSIZE;
888 memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE);
889 case 4:
890 if (data->flags & NFS_MOUNT_SECFLAVOUR) {
891 dprintk("%s: mount structure version %d does not support strong security\n",
892 __FUNCTION__,
893 data->version);
894 goto out_err_noserver;
895 }
896 case 5:
897 memset(data->context, 0, sizeof(data->context));
898 }
899#ifndef CONFIG_NFS_V3
900 /* If NFSv3 is not compiled in, return -EPROTONOSUPPORT */
901 error = -EPROTONOSUPPORT;
902 if (data->flags & NFS_MOUNT_VER3) {
903 dprintk("%s: NFSv3 not compiled into kernel\n", __FUNCTION__);
904 goto out_err_noserver;
905 }
906#endif /* CONFIG_NFS_V3 */
907 622
908 error = -ENOMEM; 623 /* Get a volume representation */
909 server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL); 624 server = nfs_create_server(data, &mntfh);
910 if (!server) 625 if (IS_ERR(server)) {
626 error = PTR_ERR(server);
911 goto out_err_noserver; 627 goto out_err_noserver;
912 /* Zero out the NFS state stuff */
913 init_nfsv4_state(server);
914 server->client = server->client_acl = ERR_PTR(-EINVAL);
915
916 root = &server->fh;
917 if (data->flags & NFS_MOUNT_VER3)
918 root->size = data->root.size;
919 else
920 root->size = NFS2_FHSIZE;
921 error = -EINVAL;
922 if (root->size > sizeof(root->data)) {
923 dprintk("%s: invalid root filehandle\n", __FUNCTION__);
924 goto out_err;
925 }
926 memcpy(root->data, data->root.data, root->size);
927
928 /* We now require that the mount process passes the remote address */
929 memcpy(&server->addr, &data->addr, sizeof(server->addr));
930 if (server->addr.sin_addr.s_addr == INADDR_ANY) {
931 dprintk("%s: mount program didn't pass remote address!\n",
932 __FUNCTION__);
933 goto out_err;
934 } 628 }
935 629
630 /* Get a superblock - note that we may end up sharing one that already exists */
936 s = sget(fs_type, nfs_compare_super, nfs_set_super, server); 631 s = sget(fs_type, nfs_compare_super, nfs_set_super, server);
937 if (IS_ERR(s)) { 632 if (IS_ERR(s)) {
938 error = PTR_ERR(s); 633 error = PTR_ERR(s);
939 goto out_err; 634 goto out_err_nosb;
940 } 635 }
941 636
942 if (s->s_root) 637 if (s->s_fs_info != server) {
943 goto out_share; 638 nfs_free_server(server);
639 server = NULL;
640 }
944 641
945 s->s_flags = flags; 642 if (!s->s_root) {
643 /* initial superblock/root creation */
644 s->s_flags = flags;
645 nfs_fill_super(s, data);
646 }
946 647
947 error = nfs_fill_super(s, data, flags & MS_SILENT ? 1 : 0); 648 mntroot = nfs_get_root(s, &mntfh);
948 if (error) { 649 if (IS_ERR(mntroot)) {
949 up_write(&s->s_umount); 650 error = PTR_ERR(mntroot);
950 deactivate_super(s); 651 goto error_splat_super;
951 return error;
952 } 652 }
953 s->s_flags |= MS_ACTIVE;
954 return simple_set_mnt(mnt, s);
955 653
956out_share: 654 s->s_flags |= MS_ACTIVE;
957 kfree(server); 655 mnt->mnt_sb = s;
958 return simple_set_mnt(mnt, s); 656 mnt->mnt_root = mntroot;
657 return 0;
959 658
960out_err: 659out_err_nosb:
961 kfree(server); 660 nfs_free_server(server);
962out_err_noserver: 661out_err_noserver:
963 return error; 662 return error;
663
664error_splat_super:
665 up_write(&s->s_umount);
666 deactivate_super(s);
667 return error;
964} 668}
965 669
670/*
671 * Destroy an NFS2/3 superblock
672 */
966static void nfs_kill_super(struct super_block *s) 673static void nfs_kill_super(struct super_block *s)
967{ 674{
968 struct nfs_server *server = NFS_SB(s); 675 struct nfs_server *server = NFS_SB(s);
969 676
970 kill_anon_super(s); 677 kill_anon_super(s);
971 678 nfs_free_server(server);
972 if (!IS_ERR(server->client))
973 rpc_shutdown_client(server->client);
974 if (!IS_ERR(server->client_acl))
975 rpc_shutdown_client(server->client_acl);
976
977 if (!(server->flags & NFS_MOUNT_NONLM))
978 lockd_down(); /* release rpc.lockd */
979
980 nfs_free_iostats(server->io_stats);
981 kfree(server->hostname);
982 nfs_put_client(server->nfs_client);
983 kfree(server);
984 nfs_release_automount_timer();
985} 679}
986 680
987static struct super_block *nfs_clone_sb(struct nfs_server *server, struct nfs_clone_mount *data) 681/*
988{ 682 * Clone an NFS2/3 server record on xdev traversal (FSID-change)
989 struct super_block *sb; 683 */
990 684static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags,
991 server->fsid = data->fattr->fsid; 685 const char *dev_name, void *raw_data,
992 nfs_copy_fh(&server->fh, data->fh); 686 struct vfsmount *mnt)
993 sb = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server);
994 if (!IS_ERR(sb) && sb->s_root == NULL && !(server->flags & NFS_MOUNT_NONLM))
995 lockd_up();
996 return sb;
997}
998
999static int nfs_clone_nfs_sb(struct file_system_type *fs_type,
1000 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
1001{ 687{
1002 struct nfs_clone_mount *data = raw_data; 688 struct nfs_clone_mount *data = raw_data;
1003 return nfs_clone_generic_sb(data, nfs_clone_sb, nfs_clone_server, mnt); 689 struct super_block *s;
1004} 690 struct nfs_server *server;
691 struct dentry *mntroot;
692 int error;
1005 693
1006#ifdef CONFIG_NFS_V4 694 dprintk("--> nfs_xdev_get_sb()\n");
1007static struct rpc_clnt *nfs4_create_client(struct nfs_server *server,
1008 int timeo, int retrans, int proto, rpc_authflavor_t flavor)
1009{
1010 struct nfs_client *clp;
1011 struct rpc_clnt *clnt = NULL;
1012 int err = -EIO;
1013
1014 clp = nfs_get_client(server->hostname, &server->addr, 4);
1015 if (!clp) {
1016 dprintk("%s: failed to create NFS4 client.\n", __FUNCTION__);
1017 return ERR_PTR(err);
1018 }
1019 695
1020 /* Now create transport and client */ 696 /* create a new volume representation */
1021 if (clp->cl_cons_state == NFS_CS_INITING) { 697 server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr);
1022 clp->rpc_ops = &nfs_v4_clientops; 698 if (IS_ERR(server)) {
699 error = PTR_ERR(server);
700 goto out_err_noserver;
701 }
1023 702
1024 err = nfs_create_rpc_client(clp, proto, timeo, retrans, flavor); 703 /* Get a superblock - note that we may end up sharing one that already exists */
1025 if (err < 0) 704 s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server);
1026 goto client_init_error; 705 if (IS_ERR(s)) {
706 error = PTR_ERR(s);
707 goto out_err_nosb;
708 }
1027 709
1028 memcpy(clp->cl_ipaddr, server->ip_addr, sizeof(clp->cl_ipaddr)); 710 if (s->s_fs_info != server) {
1029 err = nfs_idmap_new(clp); 711 nfs_free_server(server);
1030 if (err < 0) { 712 server = NULL;
1031 dprintk("%s: failed to create idmapper.\n",
1032 __FUNCTION__);
1033 goto client_init_error;
1034 }
1035 __set_bit(NFS_CS_IDMAP, &clp->cl_res_state);
1036 nfs_mark_client_ready(clp, 0);
1037 } 713 }
1038 714
1039 clnt = rpc_clone_client(clp->cl_rpcclient); 715 if (!s->s_root) {
716 /* initial superblock/root creation */
717 s->s_flags = flags;
718 nfs_clone_super(s, data->sb);
719 }
1040 720
1041 if (IS_ERR(clnt)) { 721 mntroot = nfs_get_root(s, data->fh);
1042 dprintk("%s: cannot create RPC client. Error = %d\n", 722 if (IS_ERR(mntroot)) {
1043 __FUNCTION__, err); 723 error = PTR_ERR(mntroot);
1044 return clnt; 724 goto error_splat_super;
1045 } 725 }
1046 726
1047 if (clnt->cl_auth->au_flavor != flavor) { 727 s->s_flags |= MS_ACTIVE;
1048 struct rpc_auth *auth; 728 mnt->mnt_sb = s;
729 mnt->mnt_root = mntroot;
1049 730
1050 auth = rpcauth_create(flavor, clnt); 731 dprintk("<-- nfs_xdev_get_sb() = 0\n");
1051 if (IS_ERR(auth)) { 732 return 0;
1052 dprintk("%s: couldn't create credcache!\n", __FUNCTION__);
1053 return (struct rpc_clnt *)auth;
1054 }
1055 }
1056 733
1057 server->nfs_client = clp; 734out_err_nosb:
1058 down_write(&clp->cl_sem); 735 nfs_free_server(server);
1059 list_add_tail(&server->nfs4_siblings, &clp->cl_superblocks); 736out_err_noserver:
1060 up_write(&clp->cl_sem); 737 dprintk("<-- nfs_xdev_get_sb() = %d [error]\n", error);
1061 return clnt; 738 return error;
1062 739
1063client_init_error: 740error_splat_super:
1064 nfs_mark_client_ready(clp, err); 741 up_write(&s->s_umount);
1065 nfs_put_client(clp); 742 deactivate_super(s);
1066 return ERR_PTR(err); 743 dprintk("<-- nfs_xdev_get_sb() = %d [splat]\n", error);
744 return error;
1067} 745}
1068 746
747#ifdef CONFIG_NFS_V4
748
1069/* 749/*
1070 * Set up an NFS4 superblock 750 * Finish setting up a cloned NFS4 superblock
1071 */ 751 */
1072static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data, int silent) 752static void nfs4_clone_super(struct super_block *sb,
753 const struct super_block *old_sb)
1073{ 754{
1074 struct nfs_server *server; 755 sb->s_blocksize_bits = old_sb->s_blocksize_bits;
1075 rpc_authflavor_t authflavour; 756 sb->s_blocksize = old_sb->s_blocksize;
1076 int err = -EIO; 757 sb->s_maxbytes = old_sb->s_maxbytes;
1077
1078 sb->s_blocksize_bits = 0;
1079 sb->s_blocksize = 0;
1080 server = NFS_SB(sb);
1081 if (data->rsize != 0)
1082 server->rsize = nfs_block_size(data->rsize, NULL);
1083 if (data->wsize != 0)
1084 server->wsize = nfs_block_size(data->wsize, NULL);
1085 server->flags = data->flags & NFS_MOUNT_FLAGMASK;
1086 server->caps = NFS_CAP_ATOMIC_OPEN;
1087
1088 server->acregmin = data->acregmin*HZ;
1089 server->acregmax = data->acregmax*HZ;
1090 server->acdirmin = data->acdirmin*HZ;
1091 server->acdirmax = data->acdirmax*HZ;
1092
1093 /* Now create transport and client */
1094 authflavour = RPC_AUTH_UNIX;
1095 if (data->auth_flavourlen != 0) {
1096 if (data->auth_flavourlen != 1) {
1097 dprintk("%s: Invalid number of RPC auth flavours %d.\n",
1098 __FUNCTION__, data->auth_flavourlen);
1099 err = -EINVAL;
1100 goto out_fail;
1101 }
1102 if (copy_from_user(&authflavour, data->auth_flavours, sizeof(authflavour))) {
1103 err = -EFAULT;
1104 goto out_fail;
1105 }
1106 }
1107
1108 server->client = nfs4_create_client(server, data->timeo, data->retrans,
1109 data->proto, authflavour);
1110 if (IS_ERR(server->client)) {
1111 err = PTR_ERR(server->client);
1112 dprintk("%s: cannot create RPC client. Error = %d\n",
1113 __FUNCTION__, err);
1114 goto out_fail;
1115 }
1116
1117 sb->s_time_gran = 1; 758 sb->s_time_gran = 1;
1118 759 sb->s_op = old_sb->s_op;
1119 sb->s_op = &nfs4_sops; 760 nfs_initialise_sb(sb);
1120 err = nfs_sb_init(sb, authflavour);
1121
1122 out_fail:
1123 return err;
1124} 761}
1125 762
1126static int nfs4_compare_super(struct super_block *sb, void *data) 763/*
764 * Set up an NFS4 superblock
765 */
766static void nfs4_fill_super(struct super_block *sb)
1127{ 767{
1128 struct nfs_server *server = data; 768 sb->s_time_gran = 1;
1129 struct nfs_server *old = NFS_SB(sb); 769 sb->s_op = &nfs4_sops;
1130 770 nfs_initialise_sb(sb);
1131 if (strcmp(server->hostname, old->hostname) != 0)
1132 return 0;
1133 if (strcmp(server->mnt_path, old->mnt_path) != 0)
1134 return 0;
1135 return 1;
1136} 771}
1137 772
1138static void * 773static void *nfs_copy_user_string(char *dst, struct nfs_string *src, int maxlen)
1139nfs_copy_user_string(char *dst, struct nfs_string *src, int maxlen)
1140{ 774{
1141 void *p = NULL; 775 void *p = NULL;
1142 776
@@ -1157,14 +791,22 @@ nfs_copy_user_string(char *dst, struct nfs_string *src, int maxlen)
1157 return dst; 791 return dst;
1158} 792}
1159 793
794/*
795 * Get the superblock for an NFS4 mountpoint
796 */
1160static int nfs4_get_sb(struct file_system_type *fs_type, 797static int nfs4_get_sb(struct file_system_type *fs_type,
1161 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) 798 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
1162{ 799{
1163 int error;
1164 struct nfs_server *server;
1165 struct super_block *s;
1166 struct nfs4_mount_data *data = raw_data; 800 struct nfs4_mount_data *data = raw_data;
801 struct super_block *s;
802 struct nfs_server *server;
803 struct sockaddr_in addr;
804 rpc_authflavor_t authflavour;
805 struct nfs_fh mntfh;
806 struct dentry *mntroot;
807 char *mntpath = NULL, *hostname = NULL, ip_addr[16];
1167 void *p; 808 void *p;
809 int error;
1168 810
1169 if (data == NULL) { 811 if (data == NULL) {
1170 dprintk("%s: missing data argument\n", __FUNCTION__); 812 dprintk("%s: missing data argument\n", __FUNCTION__);
@@ -1175,75 +817,107 @@ static int nfs4_get_sb(struct file_system_type *fs_type,
1175 return -EINVAL; 817 return -EINVAL;
1176 } 818 }
1177 819
1178 server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL); 820 /* We now require that the mount process passes the remote address */
1179 if (!server) 821 if (data->host_addrlen != sizeof(addr))
1180 return -ENOMEM; 822 return -EINVAL;
1181 /* Zero out the NFS state stuff */ 823
1182 init_nfsv4_state(server); 824 if (copy_from_user(&addr, data->host_addr, sizeof(addr)))
1183 server->client = server->client_acl = ERR_PTR(-EINVAL); 825 return -EFAULT;
826
827 if (addr.sin_family != AF_INET ||
828 addr.sin_addr.s_addr == INADDR_ANY
829 ) {
830 dprintk("%s: mount program didn't pass remote IP address!\n",
831 __FUNCTION__);
832 return -EINVAL;
833 }
834
835 /* Grab the authentication type */
836 authflavour = RPC_AUTH_UNIX;
837 if (data->auth_flavourlen != 0) {
838 if (data->auth_flavourlen != 1) {
839 dprintk("%s: Invalid number of RPC auth flavours %d.\n",
840 __FUNCTION__, data->auth_flavourlen);
841 error = -EINVAL;
842 goto out_err_noserver;
843 }
844
845 if (copy_from_user(&authflavour, data->auth_flavours,
846 sizeof(authflavour))) {
847 error = -EFAULT;
848 goto out_err_noserver;
849 }
850 }
1184 851
1185 p = nfs_copy_user_string(NULL, &data->hostname, 256); 852 p = nfs_copy_user_string(NULL, &data->hostname, 256);
1186 if (IS_ERR(p)) 853 if (IS_ERR(p))
1187 goto out_err; 854 goto out_err;
1188 server->hostname = p; 855 hostname = p;
1189 856
1190 p = nfs_copy_user_string(NULL, &data->mnt_path, 1024); 857 p = nfs_copy_user_string(NULL, &data->mnt_path, 1024);
1191 if (IS_ERR(p)) 858 if (IS_ERR(p))
1192 goto out_err; 859 goto out_err;
1193 server->mnt_path = p; 860 mntpath = p;
1194 861
1195 p = nfs_copy_user_string(server->ip_addr, &data->client_addr, 862 dprintk("MNTPATH: %s\n", mntpath);
1196 sizeof(server->ip_addr) - 1); 863
864 p = nfs_copy_user_string(ip_addr, &data->client_addr,
865 sizeof(ip_addr) - 1);
1197 if (IS_ERR(p)) 866 if (IS_ERR(p))
1198 goto out_err; 867 goto out_err;
1199 868
1200 /* We now require that the mount process passes the remote address */ 869 /* Get a volume representation */
1201 if (data->host_addrlen != sizeof(server->addr)) { 870 server = nfs4_create_server(data, hostname, &addr, mntpath, ip_addr,
1202 error = -EINVAL; 871 authflavour, &mntfh);
1203 goto out_free; 872 if (IS_ERR(server)) {
1204 } 873 error = PTR_ERR(server);
1205 if (copy_from_user(&server->addr, data->host_addr, sizeof(server->addr))) { 874 goto out_err_noserver;
1206 error = -EFAULT;
1207 goto out_free;
1208 }
1209 if (server->addr.sin_family != AF_INET ||
1210 server->addr.sin_addr.s_addr == INADDR_ANY) {
1211 dprintk("%s: mount program didn't pass remote IP address!\n",
1212 __FUNCTION__);
1213 error = -EINVAL;
1214 goto out_free;
1215 } 875 }
1216 876
1217 s = sget(fs_type, nfs4_compare_super, nfs_set_super, server); 877 /* Get a superblock - note that we may end up sharing one that already exists */
878 s = sget(fs_type, nfs_compare_super, nfs_set_super, server);
1218 if (IS_ERR(s)) { 879 if (IS_ERR(s)) {
1219 error = PTR_ERR(s); 880 error = PTR_ERR(s);
1220 goto out_free; 881 goto out_free;
1221 } 882 }
1222 883
1223 if (s->s_root) { 884 if (!s->s_root) {
1224 kfree(server->mnt_path); 885 /* initial superblock/root creation */
1225 kfree(server->hostname); 886 s->s_flags = flags;
1226 kfree(server);
1227 return simple_set_mnt(mnt, s);
1228 }
1229 887
1230 s->s_flags = flags; 888 nfs4_fill_super(s);
889 } else {
890 nfs_free_server(server);
891 }
1231 892
1232 error = nfs4_fill_super(s, data, flags & MS_SILENT ? 1 : 0); 893 mntroot = nfs4_get_root(s, &mntfh);
1233 if (error) { 894 if (IS_ERR(mntroot)) {
1234 up_write(&s->s_umount); 895 error = PTR_ERR(mntroot);
1235 deactivate_super(s); 896 goto error_splat_super;
1236 return error;
1237 } 897 }
898
1238 s->s_flags |= MS_ACTIVE; 899 s->s_flags |= MS_ACTIVE;
1239 return simple_set_mnt(mnt, s); 900 mnt->mnt_sb = s;
901 mnt->mnt_root = mntroot;
902 kfree(mntpath);
903 kfree(hostname);
904 return 0;
905
1240out_err: 906out_err:
1241 error = PTR_ERR(p); 907 error = PTR_ERR(p);
908 goto out_err_noserver;
909
1242out_free: 910out_free:
1243 kfree(server->mnt_path); 911 nfs_free_server(server);
1244 kfree(server->hostname); 912out_err_noserver:
1245 kfree(server); 913 kfree(mntpath);
914 kfree(hostname);
1246 return error; 915 return error;
916
917error_splat_super:
918 up_write(&s->s_umount);
919 deactivate_super(s);
920 goto out_err_noserver;
1247} 921}
1248 922
1249static void nfs4_kill_super(struct super_block *sb) 923static void nfs4_kill_super(struct super_block *sb)
@@ -1254,133 +928,140 @@ static void nfs4_kill_super(struct super_block *sb)
1254 kill_anon_super(sb); 928 kill_anon_super(sb);
1255 929
1256 nfs4_renewd_prepare_shutdown(server); 930 nfs4_renewd_prepare_shutdown(server);
1257 931 nfs_free_server(server);
1258 if (server->client != NULL && !IS_ERR(server->client))
1259 rpc_shutdown_client(server->client);
1260
1261 destroy_nfsv4_state(server);
1262
1263 nfs_free_iostats(server->io_stats);
1264 kfree(server->hostname);
1265 kfree(server);
1266 nfs_release_automount_timer();
1267} 932}
1268 933
1269/* 934/*
1270 * Constructs the SERVER-side path 935 * Clone an NFS4 server record on xdev traversal (FSID-change)
1271 */ 936 */
1272static inline char *nfs4_dup_path(const struct dentry *dentry) 937static int nfs4_xdev_get_sb(struct file_system_type *fs_type, int flags,
938 const char *dev_name, void *raw_data,
939 struct vfsmount *mnt)
1273{ 940{
1274 char *page = (char *) __get_free_page(GFP_USER); 941 struct nfs_clone_mount *data = raw_data;
1275 char *path; 942 struct super_block *s;
943 struct nfs_server *server;
944 struct dentry *mntroot;
945 int error;
1276 946
1277 path = nfs4_path(dentry, page, PAGE_SIZE); 947 dprintk("--> nfs4_xdev_get_sb()\n");
1278 if (!IS_ERR(path)) {
1279 int len = PAGE_SIZE + page - path;
1280 char *tmp = path;
1281 948
1282 path = kmalloc(len, GFP_KERNEL); 949 /* create a new volume representation */
1283 if (path) 950 server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr);
1284 memcpy(path, tmp, len); 951 if (IS_ERR(server)) {
1285 else 952 error = PTR_ERR(server);
1286 path = ERR_PTR(-ENOMEM); 953 goto out_err_noserver;
1287 } 954 }
1288 free_page((unsigned long)page);
1289 return path;
1290}
1291 955
1292static struct super_block *nfs4_clone_sb(struct nfs_server *server, struct nfs_clone_mount *data) 956 /* Get a superblock - note that we may end up sharing one that already exists */
1293{ 957 s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server);
1294 const struct dentry *dentry = data->dentry; 958 if (IS_ERR(s)) {
1295 struct nfs_client *clp = server->nfs_client; 959 error = PTR_ERR(s);
1296 struct super_block *sb; 960 goto out_err_nosb;
1297
1298 server->fsid = data->fattr->fsid;
1299 nfs_copy_fh(&server->fh, data->fh);
1300 server->mnt_path = nfs4_dup_path(dentry);
1301 if (IS_ERR(server->mnt_path)) {
1302 sb = (struct super_block *)server->mnt_path;
1303 goto err;
1304 } 961 }
1305 sb = sget(&nfs4_fs_type, nfs4_compare_super, nfs_set_super, server);
1306 if (IS_ERR(sb) || sb->s_root)
1307 goto free_path;
1308 nfs4_server_capabilities(server, &server->fh);
1309
1310 down_write(&clp->cl_sem);
1311 list_add_tail(&server->nfs4_siblings, &clp->cl_superblocks);
1312 up_write(&clp->cl_sem);
1313 return sb;
1314free_path:
1315 kfree(server->mnt_path);
1316err:
1317 server->mnt_path = NULL;
1318 return sb;
1319}
1320 962
1321static int nfs_clone_nfs4_sb(struct file_system_type *fs_type, 963 if (s->s_fs_info != server) {
1322 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) 964 nfs_free_server(server);
1323{ 965 server = NULL;
1324 struct nfs_clone_mount *data = raw_data; 966 }
1325 return nfs_clone_generic_sb(data, nfs4_clone_sb, nfs_clone_server, mnt);
1326}
1327 967
1328static struct super_block *nfs4_referral_sb(struct nfs_server *server, struct nfs_clone_mount *data) 968 if (!s->s_root) {
1329{ 969 /* initial superblock/root creation */
1330 struct super_block *sb = ERR_PTR(-ENOMEM); 970 s->s_flags = flags;
1331 int len; 971 nfs4_clone_super(s, data->sb);
1332 972 }
1333 len = strlen(data->mnt_path) + 1;
1334 server->mnt_path = kmalloc(len, GFP_KERNEL);
1335 if (server->mnt_path == NULL)
1336 goto err;
1337 memcpy(server->mnt_path, data->mnt_path, len);
1338 memcpy(&server->addr, data->addr, sizeof(struct sockaddr_in));
1339
1340 sb = sget(&nfs4_fs_type, nfs4_compare_super, nfs_set_super, server);
1341 if (IS_ERR(sb) || sb->s_root)
1342 goto free_path;
1343 return sb;
1344free_path:
1345 kfree(server->mnt_path);
1346err:
1347 server->mnt_path = NULL;
1348 return sb;
1349}
1350 973
1351static struct nfs_server *nfs4_referral_server(struct super_block *sb, struct nfs_clone_mount *data) 974 mntroot = nfs4_get_root(s, data->fh);
1352{ 975 if (IS_ERR(mntroot)) {
1353 struct nfs_server *server = NFS_SB(sb); 976 error = PTR_ERR(mntroot);
1354 int proto, timeo, retrans; 977 goto error_splat_super;
1355 void *err; 978 }
1356
1357 proto = IPPROTO_TCP;
1358 /* Since we are following a referral and there may be alternatives,
1359 set the timeouts and retries to low values */
1360 timeo = 2;
1361 retrans = 1;
1362
1363 nfs_put_client(server->nfs_client);
1364 server->nfs_client = NULL;
1365 server->client = nfs4_create_client(server, timeo, retrans, proto,
1366 data->authflavor);
1367 if (IS_ERR((err = server->client)))
1368 goto out_err;
1369 979
1370 sb->s_time_gran = 1; 980 s->s_flags |= MS_ACTIVE;
1371 sb->s_op = &nfs4_sops; 981 mnt->mnt_sb = s;
1372 err = ERR_PTR(nfs_sb_init(sb, data->authflavor)); 982 mnt->mnt_root = mntroot;
1373 if (!IS_ERR(err)) 983
1374 return server; 984 dprintk("<-- nfs4_xdev_get_sb() = 0\n");
1375out_err: 985 return 0;
1376 return (struct nfs_server *)err; 986
987out_err_nosb:
988 nfs_free_server(server);
989out_err_noserver:
990 dprintk("<-- nfs4_xdev_get_sb() = %d [error]\n", error);
991 return error;
992
993error_splat_super:
994 up_write(&s->s_umount);
995 deactivate_super(s);
996 dprintk("<-- nfs4_xdev_get_sb() = %d [splat]\n", error);
997 return error;
1377} 998}
1378 999
1379static int nfs_referral_nfs4_sb(struct file_system_type *fs_type, 1000/*
1380 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) 1001 * Create an NFS4 server record on referral traversal
1002 */
1003static int nfs4_referral_get_sb(struct file_system_type *fs_type, int flags,
1004 const char *dev_name, void *raw_data,
1005 struct vfsmount *mnt)
1381{ 1006{
1382 struct nfs_clone_mount *data = raw_data; 1007 struct nfs_clone_mount *data = raw_data;
1383 return nfs_clone_generic_sb(data, nfs4_referral_sb, nfs4_referral_server, mnt); 1008 struct super_block *s;
1009 struct nfs_server *server;
1010 struct dentry *mntroot;
1011 struct nfs_fh mntfh;
1012 int error;
1013
1014 dprintk("--> nfs4_referral_get_sb()\n");
1015
1016 /* create a new volume representation */
1017 server = nfs4_create_referral_server(data, &mntfh);
1018 if (IS_ERR(server)) {
1019 error = PTR_ERR(server);
1020 goto out_err_noserver;
1021 }
1022
1023 /* Get a superblock - note that we may end up sharing one that already exists */
1024 s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server);
1025 if (IS_ERR(s)) {
1026 error = PTR_ERR(s);
1027 goto out_err_nosb;
1028 }
1029
1030 if (s->s_fs_info != server) {
1031 nfs_free_server(server);
1032 server = NULL;
1033 }
1034
1035 if (!s->s_root) {
1036 /* initial superblock/root creation */
1037 s->s_flags = flags;
1038 nfs4_fill_super(s);
1039 }
1040
1041 mntroot = nfs4_get_root(s, data->fh);
1042 if (IS_ERR(mntroot)) {
1043 error = PTR_ERR(mntroot);
1044 goto error_splat_super;
1045 }
1046
1047 s->s_flags |= MS_ACTIVE;
1048 mnt->mnt_sb = s;
1049 mnt->mnt_root = mntroot;
1050
1051 dprintk("<-- nfs4_referral_get_sb() = 0\n");
1052 return 0;
1053
1054out_err_nosb:
1055 nfs_free_server(server);
1056out_err_noserver:
1057 dprintk("<-- nfs4_referral_get_sb() = %d [error]\n", error);
1058 return error;
1059
1060error_splat_super:
1061 up_write(&s->s_umount);
1062 deactivate_super(s);
1063 dprintk("<-- nfs4_referral_get_sb() = %d [splat]\n", error);
1064 return error;
1384} 1065}
1385 1066
1386#endif 1067#endif /* CONFIG_NFS_V4 */