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.c167
1 files changed, 114 insertions, 53 deletions
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 3dfa4f112c0..ccc4cdb1efe 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -52,6 +52,8 @@
52#include <linux/nfs_xdr.h> 52#include <linux/nfs_xdr.h>
53#include <linux/magic.h> 53#include <linux/magic.h>
54#include <linux/parser.h> 54#include <linux/parser.h>
55#include <linux/nsproxy.h>
56#include <linux/rcupdate.h>
55 57
56#include <asm/system.h> 58#include <asm/system.h>
57#include <asm/uaccess.h> 59#include <asm/uaccess.h>
@@ -79,7 +81,6 @@ enum {
79 Opt_cto, Opt_nocto, 81 Opt_cto, Opt_nocto,
80 Opt_ac, Opt_noac, 82 Opt_ac, Opt_noac,
81 Opt_lock, Opt_nolock, 83 Opt_lock, Opt_nolock,
82 Opt_v2, Opt_v3, Opt_v4,
83 Opt_udp, Opt_tcp, Opt_rdma, 84 Opt_udp, Opt_tcp, Opt_rdma,
84 Opt_acl, Opt_noacl, 85 Opt_acl, Opt_noacl,
85 Opt_rdirplus, Opt_nordirplus, 86 Opt_rdirplus, Opt_nordirplus,
@@ -97,10 +98,10 @@ enum {
97 Opt_namelen, 98 Opt_namelen,
98 Opt_mountport, 99 Opt_mountport,
99 Opt_mountvers, 100 Opt_mountvers,
100 Opt_nfsvers,
101 Opt_minorversion, 101 Opt_minorversion,
102 102
103 /* Mount options that take string arguments */ 103 /* Mount options that take string arguments */
104 Opt_nfsvers,
104 Opt_sec, Opt_proto, Opt_mountproto, Opt_mounthost, 105 Opt_sec, Opt_proto, Opt_mountproto, Opt_mounthost,
105 Opt_addr, Opt_mountaddr, Opt_clientaddr, 106 Opt_addr, Opt_mountaddr, Opt_clientaddr,
106 Opt_lookupcache, 107 Opt_lookupcache,
@@ -132,9 +133,6 @@ static const match_table_t nfs_mount_option_tokens = {
132 { Opt_noac, "noac" }, 133 { Opt_noac, "noac" },
133 { Opt_lock, "lock" }, 134 { Opt_lock, "lock" },
134 { Opt_nolock, "nolock" }, 135 { Opt_nolock, "nolock" },
135 { Opt_v2, "v2" },
136 { Opt_v3, "v3" },
137 { Opt_v4, "v4" },
138 { Opt_udp, "udp" }, 136 { Opt_udp, "udp" },
139 { Opt_tcp, "tcp" }, 137 { Opt_tcp, "tcp" },
140 { Opt_rdma, "rdma" }, 138 { Opt_rdma, "rdma" },
@@ -163,9 +161,10 @@ static const match_table_t nfs_mount_option_tokens = {
163 { Opt_namelen, "namlen=%s" }, 161 { Opt_namelen, "namlen=%s" },
164 { Opt_mountport, "mountport=%s" }, 162 { Opt_mountport, "mountport=%s" },
165 { Opt_mountvers, "mountvers=%s" }, 163 { Opt_mountvers, "mountvers=%s" },
164 { Opt_minorversion, "minorversion=%s" },
165
166 { Opt_nfsvers, "nfsvers=%s" }, 166 { Opt_nfsvers, "nfsvers=%s" },
167 { Opt_nfsvers, "vers=%s" }, 167 { Opt_nfsvers, "vers=%s" },
168 { Opt_minorversion, "minorversion=%s" },
169 168
170 { Opt_sec, "sec=%s" }, 169 { Opt_sec, "sec=%s" },
171 { Opt_proto, "proto=%s" }, 170 { Opt_proto, "proto=%s" },
@@ -179,6 +178,9 @@ static const match_table_t nfs_mount_option_tokens = {
179 { Opt_fscache_uniq, "fsc=%s" }, 178 { Opt_fscache_uniq, "fsc=%s" },
180 { Opt_local_lock, "local_lock=%s" }, 179 { Opt_local_lock, "local_lock=%s" },
181 180
181 /* The following needs to be listed after all other options */
182 { Opt_nfsvers, "v%s" },
183
182 { Opt_err, NULL } 184 { Opt_err, NULL }
183}; 185};
184 186
@@ -259,6 +261,22 @@ static match_table_t nfs_local_lock_tokens = {
259 { Opt_local_lock_err, NULL } 261 { Opt_local_lock_err, NULL }
260}; 262};
261 263
264enum {
265 Opt_vers_2, Opt_vers_3, Opt_vers_4, Opt_vers_4_0,
266 Opt_vers_4_1,
267
268 Opt_vers_err
269};
270
271static match_table_t nfs_vers_tokens = {
272 { Opt_vers_2, "2" },
273 { Opt_vers_3, "3" },
274 { Opt_vers_4, "4" },
275 { Opt_vers_4_0, "4.0" },
276 { Opt_vers_4_1, "4.1" },
277
278 { Opt_vers_err, NULL }
279};
262 280
263static void nfs_umount_begin(struct super_block *); 281static void nfs_umount_begin(struct super_block *);
264static int nfs_statfs(struct dentry *, struct kstatfs *); 282static int nfs_statfs(struct dentry *, struct kstatfs *);
@@ -620,7 +638,6 @@ static void nfs_show_nfsv4_options(struct seq_file *m, struct nfs_server *nfss,
620 struct nfs_client *clp = nfss->nfs_client; 638 struct nfs_client *clp = nfss->nfs_client;
621 639
622 seq_printf(m, ",clientaddr=%s", clp->cl_ipaddr); 640 seq_printf(m, ",clientaddr=%s", clp->cl_ipaddr);
623 seq_printf(m, ",minorversion=%u", clp->cl_minorversion);
624} 641}
625#else 642#else
626static void nfs_show_nfsv4_options(struct seq_file *m, struct nfs_server *nfss, 643static void nfs_show_nfsv4_options(struct seq_file *m, struct nfs_server *nfss,
@@ -629,6 +646,15 @@ static void nfs_show_nfsv4_options(struct seq_file *m, struct nfs_server *nfss,
629} 646}
630#endif 647#endif
631 648
649static void nfs_show_nfs_version(struct seq_file *m,
650 unsigned int version,
651 unsigned int minorversion)
652{
653 seq_printf(m, ",vers=%u", version);
654 if (version == 4)
655 seq_printf(m, ".%u", minorversion);
656}
657
632/* 658/*
633 * Describe the mount options in force on this server representation 659 * Describe the mount options in force on this server representation
634 */ 660 */
@@ -656,7 +682,7 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
656 u32 version = clp->rpc_ops->version; 682 u32 version = clp->rpc_ops->version;
657 int local_flock, local_fcntl; 683 int local_flock, local_fcntl;
658 684
659 seq_printf(m, ",vers=%u", version); 685 nfs_show_nfs_version(m, version, clp->cl_minorversion);
660 seq_printf(m, ",rsize=%u", nfss->rsize); 686 seq_printf(m, ",rsize=%u", nfss->rsize);
661 seq_printf(m, ",wsize=%u", nfss->wsize); 687 seq_printf(m, ",wsize=%u", nfss->wsize);
662 if (nfss->bsize != 0) 688 if (nfss->bsize != 0)
@@ -676,8 +702,10 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
676 else 702 else
677 seq_puts(m, nfs_infop->nostr); 703 seq_puts(m, nfs_infop->nostr);
678 } 704 }
705 rcu_read_lock();
679 seq_printf(m, ",proto=%s", 706 seq_printf(m, ",proto=%s",
680 rpc_peeraddr2str(nfss->client, RPC_DISPLAY_NETID)); 707 rpc_peeraddr2str(nfss->client, RPC_DISPLAY_NETID));
708 rcu_read_unlock();
681 if (version == 4) { 709 if (version == 4) {
682 if (nfss->port != NFS_PORT) 710 if (nfss->port != NFS_PORT)
683 seq_printf(m, ",port=%u", nfss->port); 711 seq_printf(m, ",port=%u", nfss->port);
@@ -726,9 +754,11 @@ static int nfs_show_options(struct seq_file *m, struct dentry *root)
726 754
727 nfs_show_mount_options(m, nfss, 0); 755 nfs_show_mount_options(m, nfss, 0);
728 756
757 rcu_read_lock();
729 seq_printf(m, ",addr=%s", 758 seq_printf(m, ",addr=%s",
730 rpc_peeraddr2str(nfss->nfs_client->cl_rpcclient, 759 rpc_peeraddr2str(nfss->nfs_client->cl_rpcclient,
731 RPC_DISPLAY_ADDR)); 760 RPC_DISPLAY_ADDR));
761 rcu_read_unlock();
732 762
733 return 0; 763 return 0;
734} 764}
@@ -745,7 +775,6 @@ static void show_sessions(struct seq_file *m, struct nfs_server *server) {}
745#endif 775#endif
746#endif 776#endif
747 777
748#ifdef CONFIG_NFS_V4
749#ifdef CONFIG_NFS_V4_1 778#ifdef CONFIG_NFS_V4_1
750static void show_pnfs(struct seq_file *m, struct nfs_server *server) 779static void show_pnfs(struct seq_file *m, struct nfs_server *server)
751{ 780{
@@ -755,9 +784,26 @@ static void show_pnfs(struct seq_file *m, struct nfs_server *server)
755 else 784 else
756 seq_printf(m, "not configured"); 785 seq_printf(m, "not configured");
757} 786}
787
788static void show_implementation_id(struct seq_file *m, struct nfs_server *nfss)
789{
790 if (nfss->nfs_client && nfss->nfs_client->impl_id) {
791 struct nfs41_impl_id *impl_id = nfss->nfs_client->impl_id;
792 seq_printf(m, "\n\timpl_id:\tname='%s',domain='%s',"
793 "date='%llu,%u'",
794 impl_id->name, impl_id->domain,
795 impl_id->date.seconds, impl_id->date.nseconds);
796 }
797}
758#else 798#else
759static void show_pnfs(struct seq_file *m, struct nfs_server *server) {} 799#ifdef CONFIG_NFS_V4
800static void show_pnfs(struct seq_file *m, struct nfs_server *server)
801{
802}
760#endif 803#endif
804static void show_implementation_id(struct seq_file *m, struct nfs_server *nfss)
805{
806}
761#endif 807#endif
762 808
763static int nfs_show_devname(struct seq_file *m, struct dentry *root) 809static int nfs_show_devname(struct seq_file *m, struct dentry *root)
@@ -806,6 +852,8 @@ static int nfs_show_stats(struct seq_file *m, struct dentry *root)
806 852
807 seq_printf(m, "\n\tage:\t%lu", (jiffies - nfss->mount_time) / HZ); 853 seq_printf(m, "\n\tage:\t%lu", (jiffies - nfss->mount_time) / HZ);
808 854
855 show_implementation_id(m, nfss);
856
809 seq_printf(m, "\n\tcaps:\t"); 857 seq_printf(m, "\n\tcaps:\t");
810 seq_printf(m, "caps=0x%x", nfss->caps); 858 seq_printf(m, "caps=0x%x", nfss->caps);
811 seq_printf(m, ",wtmult=%u", nfss->wtmult); 859 seq_printf(m, ",wtmult=%u", nfss->wtmult);
@@ -908,6 +956,7 @@ static struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(unsigned int ve
908 data->auth_flavor_len = 1; 956 data->auth_flavor_len = 1;
909 data->version = version; 957 data->version = version;
910 data->minorversion = 0; 958 data->minorversion = 0;
959 data->net = current->nsproxy->net_ns;
911 security_init_mnt_opts(&data->lsm_opts); 960 security_init_mnt_opts(&data->lsm_opts);
912 } 961 }
913 return data; 962 return data;
@@ -1052,6 +1101,40 @@ static int nfs_parse_security_flavors(char *value,
1052 return 1; 1101 return 1;
1053} 1102}
1054 1103
1104static int nfs_parse_version_string(char *string,
1105 struct nfs_parsed_mount_data *mnt,
1106 substring_t *args)
1107{
1108 mnt->flags &= ~NFS_MOUNT_VER3;
1109 switch (match_token(string, nfs_vers_tokens, args)) {
1110 case Opt_vers_2:
1111 mnt->version = 2;
1112 break;
1113 case Opt_vers_3:
1114 mnt->flags |= NFS_MOUNT_VER3;
1115 mnt->version = 3;
1116 break;
1117 case Opt_vers_4:
1118 /* Backward compatibility option. In future,
1119 * the mount program should always supply
1120 * a NFSv4 minor version number.
1121 */
1122 mnt->version = 4;
1123 break;
1124 case Opt_vers_4_0:
1125 mnt->version = 4;
1126 mnt->minorversion = 0;
1127 break;
1128 case Opt_vers_4_1:
1129 mnt->version = 4;
1130 mnt->minorversion = 1;
1131 break;
1132 default:
1133 return 0;
1134 }
1135 return 1;
1136}
1137
1055static int nfs_get_option_str(substring_t args[], char **option) 1138static int nfs_get_option_str(substring_t args[], char **option)
1056{ 1139{
1057 kfree(*option); 1140 kfree(*option);
@@ -1157,18 +1240,6 @@ static int nfs_parse_mount_options(char *raw,
1157 mnt->flags |= (NFS_MOUNT_LOCAL_FLOCK | 1240 mnt->flags |= (NFS_MOUNT_LOCAL_FLOCK |
1158 NFS_MOUNT_LOCAL_FCNTL); 1241 NFS_MOUNT_LOCAL_FCNTL);
1159 break; 1242 break;
1160 case Opt_v2:
1161 mnt->flags &= ~NFS_MOUNT_VER3;
1162 mnt->version = 2;
1163 break;
1164 case Opt_v3:
1165 mnt->flags |= NFS_MOUNT_VER3;
1166 mnt->version = 3;
1167 break;
1168 case Opt_v4:
1169 mnt->flags &= ~NFS_MOUNT_VER3;
1170 mnt->version = 4;
1171 break;
1172 case Opt_udp: 1243 case Opt_udp:
1173 mnt->flags &= ~NFS_MOUNT_TCP; 1244 mnt->flags &= ~NFS_MOUNT_TCP;
1174 mnt->nfs_server.protocol = XPRT_TRANSPORT_UDP; 1245 mnt->nfs_server.protocol = XPRT_TRANSPORT_UDP;
@@ -1295,26 +1366,6 @@ static int nfs_parse_mount_options(char *raw,
1295 goto out_invalid_value; 1366 goto out_invalid_value;
1296 mnt->mount_server.version = option; 1367 mnt->mount_server.version = option;
1297 break; 1368 break;
1298 case Opt_nfsvers:
1299 if (nfs_get_option_ul(args, &option))
1300 goto out_invalid_value;
1301 switch (option) {
1302 case NFS2_VERSION:
1303 mnt->flags &= ~NFS_MOUNT_VER3;
1304 mnt->version = 2;
1305 break;
1306 case NFS3_VERSION:
1307 mnt->flags |= NFS_MOUNT_VER3;
1308 mnt->version = 3;
1309 break;
1310 case NFS4_VERSION:
1311 mnt->flags &= ~NFS_MOUNT_VER3;
1312 mnt->version = 4;
1313 break;
1314 default:
1315 goto out_invalid_value;
1316 }
1317 break;
1318 case Opt_minorversion: 1369 case Opt_minorversion:
1319 if (nfs_get_option_ul(args, &option)) 1370 if (nfs_get_option_ul(args, &option))
1320 goto out_invalid_value; 1371 goto out_invalid_value;
@@ -1326,6 +1377,15 @@ static int nfs_parse_mount_options(char *raw,
1326 /* 1377 /*
1327 * options that take text values 1378 * options that take text values
1328 */ 1379 */
1380 case Opt_nfsvers:
1381 string = match_strdup(args);
1382 if (string == NULL)
1383 goto out_nomem;
1384 rc = nfs_parse_version_string(string, mnt, args);
1385 kfree(string);
1386 if (!rc)
1387 goto out_invalid_value;
1388 break;
1329 case Opt_sec: 1389 case Opt_sec:
1330 string = match_strdup(args); 1390 string = match_strdup(args);
1331 if (string == NULL) 1391 if (string == NULL)
@@ -1405,7 +1465,7 @@ static int nfs_parse_mount_options(char *raw,
1405 if (string == NULL) 1465 if (string == NULL)
1406 goto out_nomem; 1466 goto out_nomem;
1407 mnt->nfs_server.addrlen = 1467 mnt->nfs_server.addrlen =
1408 rpc_pton(string, strlen(string), 1468 rpc_pton(mnt->net, string, strlen(string),
1409 (struct sockaddr *) 1469 (struct sockaddr *)
1410 &mnt->nfs_server.address, 1470 &mnt->nfs_server.address,
1411 sizeof(mnt->nfs_server.address)); 1471 sizeof(mnt->nfs_server.address));
@@ -1427,7 +1487,7 @@ static int nfs_parse_mount_options(char *raw,
1427 if (string == NULL) 1487 if (string == NULL)
1428 goto out_nomem; 1488 goto out_nomem;
1429 mnt->mount_server.addrlen = 1489 mnt->mount_server.addrlen =
1430 rpc_pton(string, strlen(string), 1490 rpc_pton(mnt->net, string, strlen(string),
1431 (struct sockaddr *) 1491 (struct sockaddr *)
1432 &mnt->mount_server.address, 1492 &mnt->mount_server.address,
1433 sizeof(mnt->mount_server.address)); 1493 sizeof(mnt->mount_server.address));
@@ -1516,6 +1576,9 @@ static int nfs_parse_mount_options(char *raw,
1516 if (!sloppy && invalid_option) 1576 if (!sloppy && invalid_option)
1517 return 0; 1577 return 0;
1518 1578
1579 if (mnt->minorversion && mnt->version != 4)
1580 goto out_minorversion_mismatch;
1581
1519 /* 1582 /*
1520 * verify that any proto=/mountproto= options match the address 1583 * verify that any proto=/mountproto= options match the address
1521 * familiies in the addr=/mountaddr= options. 1584 * familiies in the addr=/mountaddr= options.
@@ -1549,6 +1612,10 @@ out_invalid_address:
1549out_invalid_value: 1612out_invalid_value:
1550 printk(KERN_INFO "NFS: bad mount option value specified: %s\n", p); 1613 printk(KERN_INFO "NFS: bad mount option value specified: %s\n", p);
1551 return 0; 1614 return 0;
1615out_minorversion_mismatch:
1616 printk(KERN_INFO "NFS: mount option vers=%u does not support "
1617 "minorversion=%u\n", mnt->version, mnt->minorversion);
1618 return 0;
1552out_nomem: 1619out_nomem:
1553 printk(KERN_INFO "NFS: not enough memory to parse option\n"); 1620 printk(KERN_INFO "NFS: not enough memory to parse option\n");
1554 return 0; 1621 return 0;
@@ -1622,6 +1689,7 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args,
1622 .noresvport = args->flags & NFS_MOUNT_NORESVPORT, 1689 .noresvport = args->flags & NFS_MOUNT_NORESVPORT,
1623 .auth_flav_len = &server_authlist_len, 1690 .auth_flav_len = &server_authlist_len,
1624 .auth_flavs = server_authlist, 1691 .auth_flavs = server_authlist,
1692 .net = args->net,
1625 }; 1693 };
1626 int status; 1694 int status;
1627 1695
@@ -2047,7 +2115,7 @@ static inline void nfs_initialise_sb(struct super_block *sb)
2047 2115
2048 /* We probably want something more informative here */ 2116 /* We probably want something more informative here */
2049 snprintf(sb->s_id, sizeof(sb->s_id), 2117 snprintf(sb->s_id, sizeof(sb->s_id),
2050 "%x:%x", MAJOR(sb->s_dev), MINOR(sb->s_dev)); 2118 "%u:%u", MAJOR(sb->s_dev), MINOR(sb->s_dev));
2051 2119
2052 if (sb->s_blocksize == 0) 2120 if (sb->s_blocksize == 0)
2053 sb->s_blocksize = nfs_block_bits(server->wsize, 2121 sb->s_blocksize = nfs_block_bits(server->wsize,
@@ -2499,12 +2567,6 @@ static int nfs4_validate_text_mount_data(void *options,
2499 return -EINVAL; 2567 return -EINVAL;
2500 } 2568 }
2501 2569
2502 if (args->client_address == NULL) {
2503 dfprintk(MOUNT,
2504 "NFS4: mount program didn't pass callback address\n");
2505 return -EINVAL;
2506 }
2507
2508 return nfs_parse_devname(dev_name, 2570 return nfs_parse_devname(dev_name,
2509 &args->nfs_server.hostname, 2571 &args->nfs_server.hostname,
2510 NFS4_MAXNAMLEN, 2572 NFS4_MAXNAMLEN,
@@ -2663,8 +2725,7 @@ nfs4_remote_mount(struct file_system_type *fs_type, int flags,
2663 if (!s->s_root) { 2725 if (!s->s_root) {
2664 /* initial superblock/root creation */ 2726 /* initial superblock/root creation */
2665 nfs4_fill_super(s); 2727 nfs4_fill_super(s);
2666 nfs_fscache_get_super_cookie( 2728 nfs_fscache_get_super_cookie(s, data->fscache_uniq, NULL);
2667 s, data ? data->fscache_uniq : NULL, NULL);
2668 } 2729 }
2669 2730
2670 mntroot = nfs4_get_root(s, mntfh, dev_name); 2731 mntroot = nfs4_get_root(s, mntfh, dev_name);