aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2009-12-03 15:58:56 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2009-12-03 15:58:56 -0500
commitee671b016fbfc26d69c3fe02e28706222beb1149 (patch)
tree1e3b2d050fd301b24f8aca01e58f76d68ca42a68 /fs
parentd4e935bd67ca05db4119b67801d9ece6ae139f05 (diff)
NFS: convert proto= option to use netids rather than a protoname
Solaris uses netids as values for the proto= option, so that when someone specifies "tcp6" they get traffic over TCP + IPv6. Until recently, this has never really been an issue for Linux since it didn't support NFS over IPv6. The netid and the protocol name were generally always the same (modulo any strange configuration in /etc/netconfig). The solaris manpage documents their proto= option as: proto= _netid_ | rdma This patch is intended to bring Linux closer to how the Solaris proto= option works, by declaring a static netid mapping in the kernel and converting the proto= and mountproto= options to follow it and display the proper values in /proc/mounts. Much of this functionality will need to be provided by a userspace mount.nfs patch. Chuck Lever has a patch to change mount.nfs in the same way. In principle, we could do *all* of this in userspace but that would mean that the options in /proc/mounts may not match the options used by userspace. The alternative to the static mapping here is to add a mechanism to upcall to userspace for netid's. I'm not opposed to that option, but it'll probably mean more overhead (and quite a bit more code). Rather than shoot for that at first, I figured it was probably better to start simply. Comments welcome. Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/super.c94
1 files changed, 81 insertions, 13 deletions
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index f0188eaf3726..bfad74648754 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -175,14 +175,16 @@ static const match_table_t nfs_mount_option_tokens = {
175}; 175};
176 176
177enum { 177enum {
178 Opt_xprt_udp, Opt_xprt_tcp, Opt_xprt_rdma, 178 Opt_xprt_udp, Opt_xprt_udp6, Opt_xprt_tcp, Opt_xprt_tcp6, Opt_xprt_rdma,
179 179
180 Opt_xprt_err 180 Opt_xprt_err
181}; 181};
182 182
183static const match_table_t nfs_xprt_protocol_tokens = { 183static const match_table_t nfs_xprt_protocol_tokens = {
184 { Opt_xprt_udp, "udp" }, 184 { Opt_xprt_udp, "udp" },
185 { Opt_xprt_udp6, "udp6" },
185 { Opt_xprt_tcp, "tcp" }, 186 { Opt_xprt_tcp, "tcp" },
187 { Opt_xprt_tcp6, "tcp6" },
186 { Opt_xprt_rdma, "rdma" }, 188 { Opt_xprt_rdma, "rdma" },
187 189
188 { Opt_xprt_err, NULL } 190 { Opt_xprt_err, NULL }
@@ -492,6 +494,45 @@ static const char *nfs_pseudoflavour_to_name(rpc_authflavor_t flavour)
492 return sec_flavours[i].str; 494 return sec_flavours[i].str;
493} 495}
494 496
497static void nfs_show_mountd_netid(struct seq_file *m, struct nfs_server *nfss,
498 int showdefaults)
499{
500 struct sockaddr *sap = (struct sockaddr *) &nfss->mountd_address;
501
502 seq_printf(m, ",mountproto=");
503 switch (sap->sa_family) {
504 case AF_INET:
505 switch (nfss->mountd_protocol) {
506 case IPPROTO_UDP:
507 seq_printf(m, RPCBIND_NETID_UDP);
508 break;
509 case IPPROTO_TCP:
510 seq_printf(m, RPCBIND_NETID_TCP);
511 break;
512 default:
513 if (showdefaults)
514 seq_printf(m, "auto");
515 }
516 break;
517 case AF_INET6:
518 switch (nfss->mountd_protocol) {
519 case IPPROTO_UDP:
520 seq_printf(m, RPCBIND_NETID_UDP6);
521 break;
522 case IPPROTO_TCP:
523 seq_printf(m, RPCBIND_NETID_TCP6);
524 break;
525 default:
526 if (showdefaults)
527 seq_printf(m, "auto");
528 }
529 break;
530 default:
531 if (showdefaults)
532 seq_printf(m, "auto");
533 }
534}
535
495static void nfs_show_mountd_options(struct seq_file *m, struct nfs_server *nfss, 536static void nfs_show_mountd_options(struct seq_file *m, struct nfs_server *nfss,
496 int showdefaults) 537 int showdefaults)
497{ 538{
@@ -518,17 +559,7 @@ static void nfs_show_mountd_options(struct seq_file *m, struct nfs_server *nfss,
518 if (nfss->mountd_port || showdefaults) 559 if (nfss->mountd_port || showdefaults)
519 seq_printf(m, ",mountport=%u", nfss->mountd_port); 560 seq_printf(m, ",mountport=%u", nfss->mountd_port);
520 561
521 switch (nfss->mountd_protocol) { 562 nfs_show_mountd_netid(m, nfss, showdefaults);
522 case IPPROTO_UDP:
523 seq_printf(m, ",mountproto=udp");
524 break;
525 case IPPROTO_TCP:
526 seq_printf(m, ",mountproto=tcp");
527 break;
528 default:
529 if (showdefaults)
530 seq_printf(m, ",mountproto=auto");
531 }
532} 563}
533 564
534/* 565/*
@@ -578,7 +609,7 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
578 seq_puts(m, nfs_infop->nostr); 609 seq_puts(m, nfs_infop->nostr);
579 } 610 }
580 seq_printf(m, ",proto=%s", 611 seq_printf(m, ",proto=%s",
581 rpc_peeraddr2str(nfss->client, RPC_DISPLAY_PROTO)); 612 rpc_peeraddr2str(nfss->client, RPC_DISPLAY_NETID));
582 if (version == 4) { 613 if (version == 4) {
583 if (nfss->port != NFS_PORT) 614 if (nfss->port != NFS_PORT)
584 seq_printf(m, ",port=%u", nfss->port); 615 seq_printf(m, ",port=%u", nfss->port);
@@ -883,6 +914,8 @@ static int nfs_parse_mount_options(char *raw,
883{ 914{
884 char *p, *string, *secdata; 915 char *p, *string, *secdata;
885 int rc, sloppy = 0, invalid_option = 0; 916 int rc, sloppy = 0, invalid_option = 0;
917 unsigned short protofamily = AF_UNSPEC;
918 unsigned short mountfamily = AF_UNSPEC;
886 919
887 if (!raw) { 920 if (!raw) {
888 dfprintk(MOUNT, "NFS: mount options string was NULL.\n"); 921 dfprintk(MOUNT, "NFS: mount options string was NULL.\n");
@@ -1228,12 +1261,17 @@ static int nfs_parse_mount_options(char *raw,
1228 token = match_token(string, 1261 token = match_token(string,
1229 nfs_xprt_protocol_tokens, args); 1262 nfs_xprt_protocol_tokens, args);
1230 1263
1264 protofamily = AF_INET;
1231 switch (token) { 1265 switch (token) {
1266 case Opt_xprt_udp6:
1267 protofamily = AF_INET6;
1232 case Opt_xprt_udp: 1268 case Opt_xprt_udp:
1233 mnt->flags &= ~NFS_MOUNT_TCP; 1269 mnt->flags &= ~NFS_MOUNT_TCP;
1234 mnt->nfs_server.protocol = XPRT_TRANSPORT_UDP; 1270 mnt->nfs_server.protocol = XPRT_TRANSPORT_UDP;
1235 kfree(string); 1271 kfree(string);
1236 break; 1272 break;
1273 case Opt_xprt_tcp6:
1274 protofamily = AF_INET6;
1237 case Opt_xprt_tcp: 1275 case Opt_xprt_tcp:
1238 mnt->flags |= NFS_MOUNT_TCP; 1276 mnt->flags |= NFS_MOUNT_TCP;
1239 mnt->nfs_server.protocol = XPRT_TRANSPORT_TCP; 1277 mnt->nfs_server.protocol = XPRT_TRANSPORT_TCP;
@@ -1261,10 +1299,15 @@ static int nfs_parse_mount_options(char *raw,
1261 nfs_xprt_protocol_tokens, args); 1299 nfs_xprt_protocol_tokens, args);
1262 kfree(string); 1300 kfree(string);
1263 1301
1302 mountfamily = AF_INET;
1264 switch (token) { 1303 switch (token) {
1304 case Opt_xprt_udp6:
1305 mountfamily = AF_INET6;
1265 case Opt_xprt_udp: 1306 case Opt_xprt_udp:
1266 mnt->mount_server.protocol = XPRT_TRANSPORT_UDP; 1307 mnt->mount_server.protocol = XPRT_TRANSPORT_UDP;
1267 break; 1308 break;
1309 case Opt_xprt_tcp6:
1310 mountfamily = AF_INET6;
1268 case Opt_xprt_tcp: 1311 case Opt_xprt_tcp:
1269 mnt->mount_server.protocol = XPRT_TRANSPORT_TCP; 1312 mnt->mount_server.protocol = XPRT_TRANSPORT_TCP;
1270 break; 1313 break;
@@ -1363,8 +1406,33 @@ static int nfs_parse_mount_options(char *raw,
1363 if (!sloppy && invalid_option) 1406 if (!sloppy && invalid_option)
1364 return 0; 1407 return 0;
1365 1408
1409 /*
1410 * verify that any proto=/mountproto= options match the address
1411 * familiies in the addr=/mountaddr= options.
1412 */
1413 if (protofamily != AF_UNSPEC &&
1414 protofamily != mnt->nfs_server.address.ss_family)
1415 goto out_proto_mismatch;
1416
1417 if (mountfamily != AF_UNSPEC) {
1418 if (mnt->mount_server.addrlen) {
1419 if (mountfamily != mnt->mount_server.address.ss_family)
1420 goto out_mountproto_mismatch;
1421 } else {
1422 if (mountfamily != mnt->nfs_server.address.ss_family)
1423 goto out_mountproto_mismatch;
1424 }
1425 }
1426
1366 return 1; 1427 return 1;
1367 1428
1429out_mountproto_mismatch:
1430 printk(KERN_INFO "NFS: mount server address does not match mountproto= "
1431 "option\n");
1432 return 0;
1433out_proto_mismatch:
1434 printk(KERN_INFO "NFS: server address does not match proto= option\n");
1435 return 0;
1368out_invalid_address: 1436out_invalid_address:
1369 printk(KERN_INFO "NFS: bad IP address specified: %s\n", p); 1437 printk(KERN_INFO "NFS: bad IP address specified: %s\n", p);
1370 return 0; 1438 return 0;