Commit f1ae820e authored by Mike Hibler's avatar Mike Hibler

Add sitevar to determine whether clients should use UDP or TCP for NFS.

Yes, out of the blue and off the wall. But I got tired of trying to
guess what we had Linux and FreeBSD use. I was surprised to discover
that we were using UDP on Linux (which caused Clemson CloudLab to fail
because they have jumbo frames enabled on their control net switches
but ops had the MTU set to 1500).

Anyway, here it is. The default setting is UDP for backward compat.
We should probably set it to TCP nowadays. There is also an 'osdefault'
setting which says use the default setting on the client OS.
parent 5018fb70
#!/usr/bin/perl -w
#
# Copyright (c) 2004-2013 University of Utah and the Flux Group.
# Copyright (c) 2004-2015 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
......@@ -144,6 +144,7 @@ sub doboot()
my @tmccresults;
my %curmounts;
my $dolocaldirs = 0;
my $transport;
print STDOUT "Mounting project and home directories ... \n";
......@@ -155,6 +156,10 @@ sub doboot()
if ($str =~ /^FSTYPE=([-\w]+)/) {
# XXX we have no business doing this here!
libsetup::setFSRVTYPE($1);
if ($str =~ /TRANSPORT=(TCP|UDP|osdefault)/) {
$transport = $1;
}
}
elsif ($str =~ /^REMOTE=([-:\@\w\.\/]+) LOCAL=([-\@\w\.\/]+)/) {
$mounts{$1} = $2;
......@@ -171,7 +176,11 @@ sub doboot()
}
}
print STDOUT " Mount type is ", FSRVTYPE(), "\n";
print STDOUT " Mount type is ", FSRVTYPE();
if ($transport) {
print STDOUT " (using $transport transport)";
}
print STDOUT "\n";
#
# The MFS version does not support (or need) this DB stuff. Just mount
......@@ -188,7 +197,7 @@ sub doboot()
if (!$dolocaldirs) {
print STDOUT " Mounting $remote on $local\n";
if (os_nfsmount($remote,$local)) {
if (os_nfsmount($remote,$local,$transport)) {
warning("Could not os_nfsmount $remote on $local: $!");
next;
}
......@@ -384,7 +393,7 @@ sub doboot()
}
print STDOUT " Mounting $remote on $local\n";
if (os_nfsmount($remote,$local)) {
if (os_nfsmount($remote,$local,$transport)) {
warning("Could not os_nfsmount $remote on $local: $!");
next;
}
......
......@@ -1133,11 +1133,26 @@ sub os_get_partition_info($$)
return -1;
}
sub os_nfsmount($$)
sub os_nfsmount($$$)
{
my ($remote,$local) = @_;
my ($remote,$local,$transport) = @_;
my $opts = "-b";
if (system("$NFSMOUNT $remote $local")) {
# XXX backward compat: use default
if (!defined($transport)) {
;
}
elsif ($transport eq "TCP") {
$opts .= ",tcp";
}
elsif ($transport eq "UDP") {
$opts .= ",udp";
}
elsif ($transport eq "osdefault") {
;
}
if (system("/sbin/mount -o $opts $remote $local")) {
return 1;
}
......
......@@ -2330,10 +2330,24 @@ sub os_get_partition_info($$)
return -1;
}
sub os_nfsmount($$)
sub os_nfsmount($$$)
{
my ($remote,$local) = @_;
my $opts = "nolock,udp";
my ($remote,$local,$transport) = @_;
my $opts = "nolock";
# XXX backward compat: force UDP
if (!defined($transport)) {
$opts .= ",udp";
}
elsif ($transport eq "TCP") {
$opts .= ",tcp";
}
elsif ($transport eq "UDP") {
$opts .= ",udp";
}
elsif ($transport eq "osdefault") {
;
}
# XXX doesn't work without this
if (INXENVM()) {
......@@ -2343,11 +2357,11 @@ sub os_nfsmount($$)
#
# XXX newer mount commands default to v4 and don't recognize "nolock".
# Since we are not setup for v4 now anyway, explicitly try vers=3 first
# and then fall back on vers=2 and then nothing.
# and then fall back on vers=2 and then the default.
#
if (system("/bin/mount -o vers=3,$opts $remote $local") &&
system("/bin/mount -o vers=2,$opts $remote $local") &&
system("/bin/mount -o udp $remote $local")) {
system("/bin/mount $remote $local")) {
return 1;
}
......
......@@ -155,6 +155,7 @@ INSERT INTO sitevariables VALUES ('aptlab/message',NULL,'','Message to display a
INSERT INTO sitevariables VALUES ('cloudlab/message',NULL,'','Message to display at the top of the CloudLab interface',0);
INSERT INTO sitevariables VALUES ('aptui/autoextend_maximum',NULL,'7','Maximum number of days requested that will automaticaly be granted; zero means only admins can extend an experiment.',0);
INSERT INTO sitevariables VALUES ('aptui/autoextend_maxage',NULL,'14','Maximum age (in days) of an experiment before all extension requests require admin approval.',0);
INSERT INTO sitevariables VALUES ('node/nfs_transport',NULL,'udp','Transport protocol to be used by NFS mounts on clients. One of: udp, tcp, or osdefault, where osdefault means use the client OS default setting.',0);
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
......
#
# Site variables.
#
use strict;
use libdb;
sub DoUpdate($$$)
{
my ($dbhandle, $dbname, $version) = @_;
my $var = "node/nfs_transport";
if (!TBSiteVarExists($var)) {
my $desc = "Transport protocol to be used by NFS mounts on clients.".
" One of: udp, tcp, or osdefault, where osdefault means use the".
" client OS default setting.";
my $defval = "udp";
DBQueryFatal("INSERT INTO sitevariables VALUES ".
"('$var',NULL,'$defval','$desc',0)");
}
return 0;
}
1;
# Local Variables:
# mode:perl
# End:
......@@ -4771,6 +4771,7 @@ COMMAND_PROTOTYPE(domounts)
*/
if (vers >= 32) {
char *fstype = "";
char *transport = NULL;
/* XXX sanity for code below */
if (reqp->sharing_mode[0] && !reqp->isvnode)
......@@ -4781,6 +4782,36 @@ COMMAND_PROTOTYPE(domounts)
} else if (usesfs) {
fstype = "SFS";
} else {
/*
* See what transport we should use.
*
* N.B. we did not need a version bump here because
* older clients only match on /^FSTYPE=/ and so are
* not affected by putting more stuff at the end of
* the line.
*/
res = mydb_query("select value,defaultvalue "
"from sitevariables "
"where name='node/nfs_transport'", 2);
if (res && (nrows = (int)mysql_num_rows(res)) > 0) {
char *value = NULL;
row = mysql_fetch_row(res);
if (row[0] && row[0][0])
value = row[0];
else if (row[1] && row[1][0])
value = row[1];
if (value) {
if (!strcasecmp(value, "tcp"))
transport = "TCP";
else if (!strcasecmp(value, "udp"))
transport = "UDP";
else if (!strcasecmp(value, "osdefault"))
transport = "osdefault";
}
}
if (res)
mysql_free_result(res);
#ifdef NFSRACY
fstype = "NFS-RACY";
#else
......@@ -4788,7 +4819,12 @@ COMMAND_PROTOTYPE(domounts)
#endif
}
OUTPUT(buf, sizeof(buf), "FSTYPE=%s\n", fstype);
if (transport) {
OUTPUT(buf, sizeof(buf), "FSTYPE=%s TRANSPORT=%s\n",
fstype, transport);
} else {
OUTPUT(buf, sizeof(buf), "FSTYPE=%s\n", fstype);
}
client_writeback(sock, buf, strlen(buf), tcp);
}
#ifdef NOVIRTNFSMOUNTS
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment