Blob Blame History Raw
diff --git a/aclocal/libtirpc.m4 b/aclocal/libtirpc.m4
index bddae02..ef48a2a 100644
--- a/aclocal/libtirpc.m4
+++ b/aclocal/libtirpc.m4
@@ -26,6 +26,11 @@ AC_DEFUN([AC_LIBTIRPC], [
                                     [Define to 1 if your tirpc library provides libtirpc_set_debug])],,
                          [${LIBS}])])
 
+     AS_IF([test -n "${LIBTIRPC}"],
+           [AC_CHECK_LIB([tirpc], [rpc_gss_seccreate],
+                         [AC_DEFINE([HAVE_TIRPC_GSS_SECCREATE], [1],
+                                    [Define to 1 if your tirpc library provides rpc_gss_seccreate])],,
+                         [${LIBS}])])
   AC_SUBST([AM_CPPFLAGS])
   AC_SUBST(LIBTIRPC)
 
diff --git a/configure.ac b/configure.ac
index 93a1202..58d1728 100644
--- a/configure.ac
+++ b/configure.ac
@@ -175,14 +175,14 @@ else
 fi
 
 AC_ARG_ENABLE(sbin-override,
-	[AS_HELP_STRING([--disable-sbin-override],[Don't force nfsdcltrack and mount helpers into /sbin: always honour --sbindir])],
+	[AS_HELP_STRING([--disable-sbin-override],[Do not force nfsdcltrack and mount helpers into /sbin: always honour --sbindir])],
 	enable_sbin_override=$enableval,
 	enable_sbin_override=yes)
 	AM_CONDITIONAL(CONFIG_SBIN_OVERRIDE, [test "$enable_sbin_override" = "yes"])
 AC_ARG_ENABLE(junction,
-	[AS_HELP_STRING([--enable-junction],[enable support for NFS junctions @<:@default=no@:>@])],
+	[AS_HELP_STRING([--enable-junction],[enable support for NFS junctions @<:@default=yes@:>@])],
 	enable_junction=$enableval,
-	enable_junction=no)
+	enable_junction=yes)
 	if test "$enable_junction" = yes; then
 		AC_DEFINE(HAVE_JUNCTION_SUPPORT, 1,
                           [Define this if you want junction support compiled in])
diff --git a/nfs.conf b/nfs.conf
index 323f072..23b5f7d 100644
--- a/nfs.conf
+++ b/nfs.conf
@@ -23,6 +23,7 @@
 # use-gss-proxy=0
 # avoid-dns=1
 # limit-to-legacy-enctypes=0
+# allowed-enctypes=aes256-cts-hmac-sha384-192,aes128-cts-hmac-sha256-128,camellia256-cts-cmac,camellia128-cts-cmac,aes256-cts-hmac-sha1-96,aes128-cts-hmac-sha1-96
 # context-timeout=0
 # rpc-timeout=5
 # keytab-file=/etc/krb5.keytab
diff --git a/support/export/export.c b/support/export/export.c
index 3e48c42..2c8c333 100644
--- a/support/export/export.c
+++ b/support/export/export.c
@@ -119,7 +119,7 @@ export_read(char *fname, int ignore_hosts)
 	int reexport_found = 0;
 
 	setexportent(fname, "r");
-	while ((eep = getexportent(0,1)) != NULL) {
+	while ((eep = getexportent(0)) != NULL) {
 		exp = export_lookup(eep->e_hostname, eep->e_path, ignore_hosts);
 		if (!exp) {
 			if (export_create(eep, 0))
@@ -140,7 +140,7 @@ export_read(char *fname, int ignore_hosts)
 					continue;
 
 				if (exp->m_export.e_flags & NFSEXP_FSID) {
-					xlog(L_ERROR, "When a reexport= option is present no manully assigned numerical fsid= options are allowed");
+					xlog(L_ERROR, "When a reexport= option is present no manually assigned numerical fsid= options are allowed");
 					return -1;
 				}
 			}
diff --git a/support/export/v4root.c b/support/export/v4root.c
index 03805dc..c3b17a5 100644
--- a/support/export/v4root.c
+++ b/support/export/v4root.c
@@ -137,7 +137,7 @@ v4root_support(void)
 	if (!warned) {
 		xlog(L_WARNING, "Kernel does not have pseudo root support.");
 		xlog(L_WARNING, "NFS v4 mounts will be disabled unless fsid=0");
-		xlog(L_WARNING, "is specfied in /etc/exports file.");
+		xlog(L_WARNING, "is specified in /etc/exports file.");
 		warned++;
 	}
 	return 0;
diff --git a/support/export/xtab.c b/support/export/xtab.c
index e210ca9..282f15b 100644
--- a/support/export/xtab.c
+++ b/support/export/xtab.c
@@ -47,7 +47,7 @@ xtab_read(char *xtab, char *lockfn, int is_export)
 	setexportent(xtab, "r");
 	if (is_export == 1)
 		v4root_needed = 1;
-	while ((xp = getexportent(is_export==0, 0)) != NULL) {
+	while ((xp = getexportent(is_export==0)) != NULL) {
 		if (!(exp = export_lookup(xp->e_hostname, xp->e_path, is_export != 1)) &&
 		    !(exp = export_create(xp, is_export!=1))) {
                         if(xp->e_hostname) {
diff --git a/support/include/conffile.h b/support/include/conffile.h
index c4a3ca6..c04cd1e 100644
--- a/support/include/conffile.h
+++ b/support/include/conffile.h
@@ -62,7 +62,7 @@ extern char    *conf_get_str(const char *, const char *);
 extern char    *conf_get_str_with_def(const char *, const char *, char *);
 extern char    *conf_get_section(const char *, const char *, const char *);
 extern char    *conf_get_entry(const char *, const char *, const char *);
-extern int      conf_init_file(const char *);
+extern void     conf_init_file(const char *);
 extern void     conf_cleanup(void);
 extern int      conf_match_num(const char *, const char *, int);
 extern int      conf_remove(int, const char *, const char *);
diff --git a/support/include/nfslib.h b/support/include/nfslib.h
index bdbde78..eff2a48 100644
--- a/support/include/nfslib.h
+++ b/support/include/nfslib.h
@@ -111,7 +111,7 @@ struct rmtabent {
  * configuration file parsing
  */
 void			setexportent(char *fname, char *type);
-struct exportent *	getexportent(int,int);
+struct exportent *	getexportent(int);
 void 			secinfo_show(FILE *fp, struct exportent *ep);
 void			xprtsecinfo_show(FILE *fp, struct exportent *ep);
 void			putexportent(struct exportent *xep);
diff --git a/support/junction/junction-internal.h b/support/junction/junction-internal.h
index 3dff4cc..7abd45c 100644
--- a/support/junction/junction-internal.h
+++ b/support/junction/junction-internal.h
@@ -28,6 +28,7 @@
 
 #include <libxml/tree.h>
 #include <libxml/xpath.h>
+#include <libxml/parser.h>
 
 /**
  ** Names of extended attributes that store junction data
diff --git a/support/junction/xml.c b/support/junction/xml.c
index 813110b..aef1cbb 100644
--- a/support/junction/xml.c
+++ b/support/junction/xml.c
@@ -290,7 +290,7 @@ junction_parse_xml_buf(const char *pathname, const char *name,
 {
 	xmlDocPtr tmp;
 
-	tmp = xmlParseMemory(buf, (int)len);
+	tmp = xmlReadMemory(buf, (int)len, NULL, NULL, 0);
 	if (tmp == NULL) {
 		xlog(D_GENERAL, "Failed to parse XML in %s(%s)\n",
 			pathname, name);
@@ -387,7 +387,6 @@ junction_xml_write(const char *pathname, const char *name, xmlDocPtr doc)
 		return retval;
 
 	retval = FEDFS_ERR_SVRFAULT;
-	xmlIndentTreeOutput = 1;
 	xmlDocDumpFormatMemoryEnc(doc, &buf, &len, "UTF-8", 1);
 	if (len < 0)
 		goto out;
diff --git a/support/nfs/conffile.c b/support/nfs/conffile.c
index fd4a17a..1e9c22b 100644
--- a/support/nfs/conffile.c
+++ b/support/nfs/conffile.c
@@ -658,7 +658,7 @@ conf_load_file(const char *conf_file)
 	return 0;
 }
 
-static void 
+static void
 conf_init_dir(const char *conf_file)
 {
 	struct dirent **namelist = NULL;
@@ -669,14 +669,14 @@ conf_init_dir(const char *conf_file)
 	dname = malloc(strlen(conf_file) + 3);
 	if (dname == NULL) {
 		xlog(L_WARNING, "conf_init_dir: malloc: %s", strerror(errno));
-		return;	
+		return;
 	}
 	sprintf(dname, "%s.d", conf_file);
 
 	n = scandir(dname, &namelist, NULL, versionsort);
 	if (n < 0) {
 		if (errno != ENOENT) {
-			xlog(L_WARNING, "conf_init_dir: scandir %s: %s", 
+			xlog(L_WARNING, "conf_init_dir: scandir %s: %s",
 				dname, strerror(errno));
 		}
 		free(dname);
@@ -691,7 +691,7 @@ conf_init_dir(const char *conf_file)
 	for (i = 0; i < n; i++ ) {
 		struct dirent *d = namelist[i];
 
-	 	switch (d->d_type) {
+		switch (d->d_type) {
 			case DT_UNKNOWN:
 			case DT_REG:
 			case DT_LNK:
@@ -701,13 +701,13 @@ conf_init_dir(const char *conf_file)
 		}
 		if (*d->d_name == '.')
 			continue;
-		
+
 		fname_len = strlen(d->d_name);
 		path_len = (fname_len + dname_len);
 		if (!fname_len || path_len > PATH_MAX) {
 			xlog(L_WARNING, "conf_init_dir: Too long file name: %s in %s", 
 				d->d_name, dname);
-			continue; 
+			continue;
 		}
 
 		/*
@@ -715,7 +715,7 @@ conf_init_dir(const char *conf_file)
 		 * that end with CONF_FILE_EXT
 		 */
 		if (fname_len <= CONF_FILE_EXT_LEN) {
-			xlog(D_GENERAL, "conf_init_dir: %s: name too short", 
+			xlog(D_GENERAL, "conf_init_dir: %s: name too short",
 				d->d_name);
 			continue;
 		}
@@ -746,41 +746,43 @@ conf_init_dir(const char *conf_file)
 		free(namelist[i]);
 	free(namelist);
 	free(dname);
-	
+
 	return;
 }
 
-int
+void
 conf_init_file(const char *conf_file)
 {
 	unsigned int i;
-	int ret;
+	int j;
 
 	for (i = 0; i < sizeof conf_bindings / sizeof conf_bindings[0]; i++)
 		LIST_INIT (&conf_bindings[i]);
 
 	TAILQ_INIT (&conf_trans_queue);
 
-	if (conf_file == NULL) 
-		conf_file=NFS_CONFFILE;
+	if (conf_file == NULL)
+		conf_file = NFS_CONFFILE;
 
-	/*
-	 * First parse the give config file 
-	 * then parse the config.conf.d directory 
-	 * (if it exists)
+	/* If the config file is in /etc (normal) then check
+	 * /usr/etc first.  Also check config.conf.d for files
+	 * names *.conf.
 	 *
+	 * Content or later files always over-rides earlier
+	 * files.
 	 */
-	ret = conf_load_file(conf_file);
-
-	/*
-	 * When the same variable is set in both files
-	 * the conf.d file will override the config file.
-	 * This allows automated admin systems to
-	 * have the final say.
-	 */
+	if (strncmp(conf_file, "/etc/", 5) == 0) {
+		char *usrconf = NULL;
+
+		j = asprintf(&usrconf, "/usr%s", conf_file);
+		if (usrconf && j > 0) {
+			conf_load_file(usrconf);
+			conf_init_dir(usrconf);
+			free(usrconf);
+		}
+	}
+	conf_load_file(conf_file);
 	conf_init_dir(conf_file);
-
-	return ret;
 }
 
 /*
diff --git a/support/nfs/exports.c b/support/nfs/exports.c
index 15dc574..a6816e6 100644
--- a/support/nfs/exports.c
+++ b/support/nfs/exports.c
@@ -59,7 +59,7 @@ static int	*squids = NULL, nsquids = 0,
 
 static int	getexport(char *exp, int len);
 static int	getpath(char *path, int len);
-static int	parseopts(char *cp, struct exportent *ep, int warn, int *had_subtree_opt_ptr);
+static int	parseopts(char *cp, struct exportent *ep, int *had_subtree_opt_ptr);
 static int	parsesquash(char *list, int **idp, int *lenp, char **ep);
 static int	parsenum(char **cpp);
 static void	freesquash(void);
@@ -109,7 +109,7 @@ static void init_exportent (struct exportent *ee, int fromkernel)
 }
 
 struct exportent *
-getexportent(int fromkernel, int fromexports)
+getexportent(int fromkernel)
 {
 	static struct exportent	ee, def_ee;
 	char		exp[512], *hostname;
@@ -147,7 +147,7 @@ getexportent(int fromkernel, int fromexports)
 	 * we're not reading from the kernel.
 	 */
 	if (exp[0] == '-' && !fromkernel) {
-		if (parseopts(exp + 1, &def_ee, 0, &has_default_subtree_opts) < 0)
+		if (parseopts(exp + 1, &def_ee, &has_default_subtree_opts) < 0)
 			return NULL;
 
 		has_default_opts = 1;
@@ -185,20 +185,20 @@ getexportent(int fromkernel, int fromexports)
 	}
 	ee.e_hostname = xstrdup(hostname);
 
-	if (parseopts(opt, &ee, fromexports && !has_default_subtree_opts, NULL) < 0) {
-                if(ee.e_hostname)
-                {
-                    xfree(ee.e_hostname);
-                    ee.e_hostname=NULL;
-                }
-                if(ee.e_uuid)
-                {
-                    xfree(ee.e_uuid);
-                    ee.e_uuid=NULL;
-                }
+	if (parseopts(opt, &ee, NULL) < 0) {
+		if(ee.e_hostname)
+		{
+			xfree(ee.e_hostname);
+			ee.e_hostname=NULL;
+		}
+		if(ee.e_uuid)
+		{
+			xfree(ee.e_uuid);
+			ee.e_uuid=NULL;
+		}
 
 		return NULL;
-        }
+	}
 	/* resolve symlinks */
 	if (realpath(ee.e_path, rpath) != NULL) {
 		rpath[sizeof (rpath) - 1] = '\0';
@@ -433,7 +433,7 @@ mkexportent(char *hname, char *path, char *options)
 	}
 	strncpy(ee.e_path, path, sizeof (ee.e_path));
 	ee.e_path[sizeof (ee.e_path) - 1] = '\0';
-	if (parseopts(options, &ee, 0, NULL) < 0)
+	if (parseopts(options, &ee, NULL) < 0)
 		return NULL;
 	return &ee;
 }
@@ -441,7 +441,7 @@ mkexportent(char *hname, char *path, char *options)
 int
 updateexportent(struct exportent *eep, char *options)
 {
-	if (parseopts(options, eep, 0, NULL) < 0)
+	if (parseopts(options, eep, NULL) < 0)
 		return 0;
 	return 1;
 }
@@ -632,7 +632,7 @@ void fix_pseudoflavor_flags(struct exportent *ep)
  * Parse option string pointed to by cp and set mount options accordingly.
  */
 static int
-parseopts(char *cp, struct exportent *ep, int warn, int *had_subtree_opt_ptr)
+parseopts(char *cp, struct exportent *ep, int *had_subtree_opt_ptr)
 {
 	int	had_subtree_opt = 0;
 	char 	*flname = efname?efname:"command line";
@@ -852,13 +852,6 @@ bad_option:
 	ep->e_nsqgids = nsqgids;
 
 out:
-	if (warn && !had_subtree_opt)
-		xlog(L_WARNING, "%s [%d]: Neither 'subtree_check' or 'no_subtree_check' specified for export \"%s:%s\".\n"
-				"  Assuming default behaviour ('no_subtree_check').\n"
-				"  NOTE: this default has changed since nfs-utils version 1.0.x\n",
-
-				flname, flline,
-				ep->e_hostname, ep->e_path);
 	if (had_subtree_opt_ptr)
 		*had_subtree_opt_ptr = had_subtree_opt;
 
diff --git a/support/nfsidmap/idmapd.conf.5 b/support/nfsidmap/idmapd.conf.5
index 87e39bb..58c2d97 100644
--- a/support/nfsidmap/idmapd.conf.5
+++ b/support/nfsidmap/idmapd.conf.5
@@ -37,7 +37,7 @@ Configuration file for libnfsidmap.  Used by idmapd and svcgssd to map NFSv4 nam
 .SH DESCRIPTION
 The
 .B idmapd.conf
-configuration file consists of several sections, initiated by strings of the
+configuration files consists of several sections, initiated by strings of the
 form [General] and [Mapping].  Each section may contain lines of the form
 .nf
   variable = value
@@ -398,6 +398,19 @@ LDAP_base = dc=org,dc=domain
 .\" Additional sections
 .\" -------------------------------------------------------------------
 .\"
+.SH FILES
+.I /usr/etc/idmapd.conf
+.br
+.I /usr/etc/idmapd.conf.d/*.conf
+.br
+.I /etc/idmapd.conf
+.br
+.I /etc/idmapd.conf.d/*.conf
+.br
+.IP
+Files are read in the order listed.  Later settings override earlier
+settings.
+
 .SH SEE ALSO
 .BR idmapd (8)
 .BR svcgssd (8)
diff --git a/support/reexport/fsidd.c b/support/reexport/fsidd.c
index 3e62b3f..51750ea 100644
--- a/support/reexport/fsidd.c
+++ b/support/reexport/fsidd.c
@@ -7,6 +7,8 @@
 #include <dlfcn.h>
 #endif
 #include <event2/event.h>
+#include <sys/un.h>
+#include <unistd.h>
 
 #include "conffile.h"
 #include "reexport_backend.h"
@@ -147,6 +149,7 @@ int main(void)
 {
 	struct event *srv_ev;
 	struct sockaddr_un addr;
+	socklen_t addr_len;
 	char *sock_file;
 	int srv;
 
@@ -161,10 +164,12 @@ int main(void)
 	memset(&addr, 0, sizeof(struct sockaddr_un));
 	addr.sun_family = AF_UNIX;
 	strncpy(addr.sun_path, sock_file, sizeof(addr.sun_path) - 1);
-	if (addr.sun_path[0] == '@')
+	addr_len = sizeof(struct sockaddr_un);
+	if (addr.sun_path[0] == '@') {
 		/* "abstract" socket namespace */
+		addr_len = offsetof(struct sockaddr_un, sun_path) + strlen(addr.sun_path);
 		addr.sun_path[0] = 0;
-	else
+	} else
 		unlink(sock_file);
 
 	srv = socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK, 0);
@@ -173,7 +178,7 @@ int main(void)
 		return 1;
 	}
 
-	if (bind(srv, (const struct sockaddr *)&addr, sizeof(struct sockaddr_un)) == -1) {
+	if (bind(srv, (const struct sockaddr *)&addr, addr_len) == -1) {
 		xlog(L_WARNING, "Unable to bind %s: %m\n", sock_file);
 		return 1;
 	}
diff --git a/support/reexport/reexport.c b/support/reexport/reexport.c
index 7851658..1febf59 100644
--- a/support/reexport/reexport.c
+++ b/support/reexport/reexport.c
@@ -7,7 +7,9 @@
 #endif
 #include <sys/types.h>
 #include <sys/vfs.h>
+#include <unistd.h>
 #include <errno.h>
+#include <stddef.h>
 
 #include "nfsd_path.h"
 #include "conffile.h"
@@ -21,6 +23,7 @@ static int fsidd_srv = -1;
 static bool connect_fsid_service(void)
 {
 	struct sockaddr_un addr;
+	socklen_t addr_len;
 	char *sock_file;
 	int ret;
 	int s;
@@ -33,9 +36,12 @@ static bool connect_fsid_service(void)
 	memset(&addr, 0, sizeof(struct sockaddr_un));
 	addr.sun_family = AF_UNIX;
 	strncpy(addr.sun_path, sock_file, sizeof(addr.sun_path) - 1);
-	if (addr.sun_path[0] == '@')
+	addr_len = sizeof(struct sockaddr_un);
+	if (addr.sun_path[0] == '@') {
 		/* "abstract" socket namespace */
+		addr_len = offsetof(struct sockaddr_un, sun_path) + strlen(addr.sun_path);
 		addr.sun_path[0] = 0;
+	}
 
 	s = socket(AF_UNIX, SOCK_SEQPACKET, 0);
 	if (s == -1) {
@@ -43,7 +49,7 @@ static bool connect_fsid_service(void)
 		return false;
 	}
 
-	ret = connect(s, (const struct sockaddr *)&addr, sizeof(struct sockaddr_un));
+	ret = connect(s, (const struct sockaddr *)&addr, addr_len);
 	if (ret == -1) {
 		xlog(L_WARNING, "Unable to connect %s: %m, is fsidd running?\n", sock_file);
 		return false;
diff --git a/systemd/nfs-blkmap.service b/systemd/nfs-blkmap.service
index 6aa45ba..5718163 100644
--- a/systemd/nfs-blkmap.service
+++ b/systemd/nfs-blkmap.service
@@ -1,5 +1,6 @@
 [Unit]
 Description=pNFS block layout mapping daemon
+Documentation=man:blkmapd(8)
 DefaultDependencies=no
 Conflicts=umount.target
 After=rpc_pipefs.target
diff --git a/systemd/nfs-idmapd.service b/systemd/nfs-idmapd.service
index 198ca87..d820f10 100644
--- a/systemd/nfs-idmapd.service
+++ b/systemd/nfs-idmapd.service
@@ -1,5 +1,6 @@
 [Unit]
 Description=NFSv4 ID-name mapping service
+Documentation=man:idmapd(8)
 DefaultDependencies=no
 Requires=rpc_pipefs.target
 After=rpc_pipefs.target local-fs.target network-online.target
diff --git a/systemd/nfs-mountd.service b/systemd/nfs-mountd.service
index e8ece53..4618fab 100644
--- a/systemd/nfs-mountd.service
+++ b/systemd/nfs-mountd.service
@@ -1,5 +1,6 @@
 [Unit]
 Description=NFS Mount Daemon
+Documentation=man:rpc.mountd(8)
 DefaultDependencies=no
 Requires=proc-fs-nfsd.mount
 Wants=network-online.target
diff --git a/systemd/nfs-server.service b/systemd/nfs-server.service
index 2cdd786..ac17d52 100644
--- a/systemd/nfs-server.service
+++ b/systemd/nfs-server.service
@@ -1,5 +1,6 @@
 [Unit]
 Description=NFS server and services
+Documentation=man:rpc.nfsd(8) man:exportfs(8)
 DefaultDependencies=no
 Requires=network.target proc-fs-nfsd.mount
 Requires=nfs-mountd.service
diff --git a/systemd/nfs.conf.man b/systemd/nfs.conf.man
index 866939a..d03fc88 100644
--- a/systemd/nfs.conf.man
+++ b/systemd/nfs.conf.man
@@ -2,10 +2,13 @@
 .SH NAME
 nfs.conf \- general configuration for NFS daemons and tools
 .SH SYNOPSIS
+.I /usr/etc/nfs.conf
+.I /usr/etc/nfs.conf.d/
 .I /etc/nfs.conf
+.I /etc/nfs.conf.d/
 .SH DESCRIPTION
 .PP
-This file contains site-specific configuration for various NFS daemons
+These files contain site-specific configuration for various NFS daemons
 and other processes.  Most configuration can also be passed to
 processes via command line arguments, but it can be more convenient to
 have a central file.  In particular, this encourages consistent
@@ -314,15 +317,17 @@ See
 for deatils.
 
 .SH FILES
-.TP 10n
+.I /usr/etc/nfs.conf
+.br
+.I /usr/etc/nfs.conf.d/*.conf
+.br
 .I /etc/nfs.conf
-Default NFS client configuration file
-.TP 10n
-.I /etc/nfs.conf.d
-When this directory exists and files ending 
-with ".conf" exist, those files will be
-used to set configuration variables. These
-files will override variables set in /etc/nfs.conf
+.br
+.I /etc/nfs.conf.d/*.conf
+.br
+.IP
+Various configuration files read in order.  Later settings override
+earlier settings.
 .SH SEE ALSO
 .BR nfsdcltrack (8),
 .BR rpc.nfsd (8),
diff --git a/systemd/nfs.systemd.man b/systemd/nfs.systemd.man
index 46b476a..df89ddd 100644
--- a/systemd/nfs.systemd.man
+++ b/systemd/nfs.systemd.man
@@ -27,7 +27,9 @@ any command line arguments to daemons so as to configure their
 behavior.  In many case such configuration can be performed by making
 changes to
 .I /etc/nfs.conf
-or other configuration files.  When that is not convenient, a
+or other configuration files (see
+.BR nfs.conf (5)).
+When that is not convenient, a
 distribution might provide systemd "drop-in" files which replace the
 .B ExecStart=
 setting to start the program with different arguments.  For example a
@@ -171,6 +173,12 @@ running, it can be masked with
 /etc/nfsmount.conf
 .br
 /etc/idmapd.conf
+.P
+Also similar files in 
+.B /usr/etc
+and in related
+.I conf.d
+drop-in directories.
 .SH SEE ALSO
 .BR systemd.unit (5),
 .BR nfs.conf (5),
diff --git a/systemd/nfsdcld.service b/systemd/nfsdcld.service
index a32d243..3ced565 100644
--- a/systemd/nfsdcld.service
+++ b/systemd/nfsdcld.service
@@ -1,5 +1,6 @@
 [Unit]
 Description=NFSv4 Client Tracking Daemon
+Documentation=man:nfsdcld(8)
 DefaultDependencies=no
 Conflicts=umount.target
 Requires=rpc_pipefs.target proc-fs-nfsd.mount
diff --git a/systemd/rpc-gssd.service.in b/systemd/rpc-gssd.service.in
index 6807db3..38382ed 100644
--- a/systemd/rpc-gssd.service.in
+++ b/systemd/rpc-gssd.service.in
@@ -1,5 +1,6 @@
 [Unit]
 Description=RPC security service for NFS client and server
+Documentation=man:rpc.gssd(8)
 DefaultDependencies=no
 Conflicts=umount.target
 Requires=rpc_pipefs.target
diff --git a/systemd/rpc-statd-notify.service b/systemd/rpc-statd-notify.service
index aad4c0d..962f18b 100644
--- a/systemd/rpc-statd-notify.service
+++ b/systemd/rpc-statd-notify.service
@@ -1,5 +1,6 @@
 [Unit]
 Description=Notify NFS peers of a restart
+Documentation=man:sm-notify(8) man:rpc.statd(8)
 DefaultDependencies=no
 Wants=network-online.target
 After=local-fs.target network-online.target nss-lookup.target
diff --git a/systemd/rpc-statd.service b/systemd/rpc-statd.service
index 392750d..660ed86 100644
--- a/systemd/rpc-statd.service
+++ b/systemd/rpc-statd.service
@@ -1,5 +1,6 @@
 [Unit]
 Description=NFS status monitor for NFSv2/3 locking.
+Documentation=man:rpc.statd(8)
 DefaultDependencies=no
 Conflicts=umount.target
 Requires=nss-lookup.target rpcbind.socket
diff --git a/systemd/rpc-svcgssd.service b/systemd/rpc-svcgssd.service
index cb2bcd4..401fba1 100644
--- a/systemd/rpc-svcgssd.service
+++ b/systemd/rpc-svcgssd.service
@@ -1,5 +1,6 @@
 [Unit]
 Description=RPC security service for NFS server
+Documentation=man:rpc.svcgssd(8)
 DefaultDependencies=no
 After=local-fs.target
 PartOf=nfs-server.service
diff --git a/tools/locktest/testlk.c b/tools/locktest/testlk.c
index ea51f78..c9bd6ba 100644
--- a/tools/locktest/testlk.c
+++ b/tools/locktest/testlk.c
@@ -81,8 +81,8 @@ main(int argc, char **argv)
 		if (fl.l_type == F_UNLCK) {
 			printf("%s: no conflicting lock\n", fname);
 		} else {
-			printf("%s: conflicting lock by %d on (%zd;%zd)\n",
-				fname, fl.l_pid, fl.l_start, fl.l_len);
+			printf("%s: conflicting lock by %d on (%lld;%lld)\n",
+				fname, fl.l_pid, (long long)fl.l_start, (long long)fl.l_len);
 		}
 		return 0;
 	}
diff --git a/tools/nfsconf/nfsconfcli.c b/tools/nfsconf/nfsconfcli.c
index b2ef96d..bd9d527 100644
--- a/tools/nfsconf/nfsconfcli.c
+++ b/tools/nfsconf/nfsconfcli.c
@@ -135,19 +135,8 @@ int main(int argc, char **argv)
 		return 1;
 	}
 
-	if (mode != MODE_SET && mode != MODE_UNSET) {
-		if (conf_init_file(confpath)) {
-			/* config file was missing or had an error, warn about it */
-			if (verbose || mode != MODE_ISSET) {
-				fprintf(stderr, "Error loading config file %s\n",
-					confpath);
-			}
-
-			/* this isnt fatal for --isset */
-			if (mode != MODE_ISSET)
-				return 1;
-		}
-	}
+	if (mode != MODE_SET && mode != MODE_UNSET)
+		conf_init_file(confpath);
 
 	/* --dump mode, output the current configuration */
 	if (mode == MODE_DUMP) {
diff --git a/utils/exportfs/exports.man b/utils/exportfs/exports.man
index b758277..c14769e 100644
--- a/utils/exportfs/exports.man
+++ b/utils/exportfs/exports.man
@@ -298,7 +298,7 @@ set.
 
 The
 .I nocrossmnt
-option can explictly disable
+option can explicitly disable
 .I crossmnt
 if it was previously set.  This is rarely useful.
 .TP
@@ -445,6 +445,9 @@ the given list an alternative location for the filesystem.
 filesystem is not required; so, for example,
 .IR "mount --bind" " /path /path"
 is sufficient.)
+
+This option affects only NFSv4 clients. Other clients will ignore
+all "refer=" parts.
 .TP
 .IR replicas= path@host[+host][:path@host[+host]]
 If the client asks for alternative locations for the export point, it
diff --git a/utils/gssd/err_util.h b/utils/gssd/err_util.h
index 6fa9d3d..61f5a31 100644
--- a/utils/gssd/err_util.h
+++ b/utils/gssd/err_util.h
@@ -32,7 +32,7 @@
 #define _ERR_UTIL_H_
 
 void initerr(char *progname, int verbosity, int fg);
-void printerr(int priority, char *format, ...);
+void printerr(int priority, char *format, ...) __attribute__ ((format (printf, 2, 3)));
 int get_verbosity(void);
 char * sec2time(int);
 
diff --git a/utils/gssd/gss_names.c b/utils/gssd/gss_names.c
index 982b96f..0548c33 100644
--- a/utils/gssd/gss_names.c
+++ b/utils/gssd/gss_names.c
@@ -65,7 +65,7 @@ get_krb5_hostbased_name(gss_buffer_desc *name, char **hostbased_name)
 	if (strchr(name->value, '@') && strchr(name->value, '/')) {
 		if ((sname = calloc(name->length, 1)) == NULL) {
 			printerr(0, "ERROR: get_krb5_hostbased_name failed "
-				 "to allocate %d bytes\n", name->length);
+				 "to allocate %zd bytes\n", name->length);
 			return -1;
 		}
 		/* read in name and instance and replace '/' with '@' */
@@ -102,7 +102,7 @@ get_hostbased_client_name(gss_name_t client_name, gss_OID mech,
 	}
 	if (name.length >= 0xffff) {	    /* don't overflow */
 		printerr(0, "ERROR: get_hostbased_client_name: "
-			 "received gss_name is too long (%d bytes)\n",
+			 "received gss_name is too long (%zd bytes)\n",
 			 name.length);
 		goto out_rel_buf;
 	}
diff --git a/utils/gssd/gss_util.c b/utils/gssd/gss_util.c
index a4b2777..7d41a94 100644
--- a/utils/gssd/gss_util.c
+++ b/utils/gssd/gss_util.c
@@ -304,7 +304,7 @@ gssd_acquire_cred(char *server_name, const gss_OID oid)
 				target_name, &pbuf, NULL);
 		if (ignore_maj_stat == GSS_S_COMPLETE) {
 			printerr(1, "Unable to obtain credentials for '%.*s'\n",
-				 pbuf.length, pbuf.value);
+				 (int)pbuf.length, (char *)pbuf.value);
 			ignore_maj_stat = gss_release_buffer(&ignore_min_stat,
 							     &pbuf);
 		}
diff --git a/utils/gssd/gssd.c b/utils/gssd/gssd.c
index ca9b326..d7a2822 100644
--- a/utils/gssd/gssd.c
+++ b/utils/gssd/gssd.c
@@ -559,9 +559,9 @@ scan_active_thread_list(void)
 					do_error_downcall(info->fd, info->uid, -ETIMEDOUT);
 				} else {
 					if (!(info->flags & UPCALL_THREAD_WARNED)) {
-						printerr(0, "watchdog: thread id 0x%lx running for %ld seconds\n",
+						printerr(0, "watchdog: thread id 0x%lx running for %lld seconds\n",
 								info->tid,
-								now.tv_sec - info->timeout.tv_sec + upcall_timeout);
+								(long long int)(now.tv_sec - info->timeout.tv_sec + upcall_timeout));
 						info->flags |= UPCALL_THREAD_WARNED;
 					}
 				}
@@ -1232,6 +1232,12 @@ main(int argc, char *argv[])
 
 	daemon_init(fg);
 
+#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
+	rc = get_allowed_enctypes();
+	if (rc)
+		exit(EXIT_FAILURE);
+#endif
+
 	if (gssd_check_mechs() != 0)
 		errx(1, "Problem with gssapi library");
 
diff --git a/utils/gssd/gssd.man b/utils/gssd/gssd.man
index 2a5384d..c735eff 100644
--- a/utils/gssd/gssd.man
+++ b/utils/gssd/gssd.man
@@ -346,6 +346,15 @@ flag.
 Equivalent to
 .BR -l .
 .TP
+.B allowed-enctypes
+Allows you to restrict
+.B rpc.gssd
+to using a subset of the encryption types permitted by the kernel and the krb5
+libraries.  This is useful if you need to interoperate with an NFS server that
+does not have support for the newer SHA2 and Camellia encryption types, for
+example.  This configuration file option does not have an equivalent
+command-line option.
+.TP
 .B context-timeout
 Equivalent to
 .BR -t .
diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c
index a96647d..2ad84c5 100644
--- a/utils/gssd/gssd_proc.c
+++ b/utils/gssd/gssd_proc.c
@@ -70,6 +70,9 @@
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <syscall.h>
+#ifdef HAVE_TIRPC_GSS_SECCREATE
+#include <rpc/rpcsec_gss.h>
+#endif
 
 #include "gssd.h"
 #include "err_util.h"
@@ -168,7 +171,7 @@ do_downcall(int k5_fd, uid_t uid, struct authgss_private_data *pd,
 
 	if (get_verbosity() > 1)
 		printerr(2, "do_downcall(0x%lx): lifetime_rec=%s acceptor=%.*s\n",
-			tid, sec2time(lifetime_rec), acceptor->length, acceptor->value);
+			tid, sec2time(lifetime_rec), (int)acceptor->length, (char *)acceptor->value);
 	buf_size = sizeof(uid) + sizeof(timeout) + sizeof(pd->pd_seq_win) +
 		sizeof(pd->pd_ctx_hndl.length) + pd->pd_ctx_hndl.length +
 		sizeof(context_token->length) + context_token->length +
@@ -284,14 +287,14 @@ populate_port(struct sockaddr *sa, const socklen_t salen,
 
 	port = nfs_getport(sa, salen, program, version, protocol);
 	if (!port) {
-		printerr(0, "ERROR: unable to obtain port for prog %ld "
-			    "vers %ld\n", program, version);
+		printerr(0, "ERROR: unable to obtain port for prog %lu "
+			    "vers %lu\n", (long unsigned int)program, (long unsigned int)version);
 		return 0;
 	}
 
 set_port:
 	printerr(2, "DEBUG: setting port to %hu for prog %lu vers %lu\n", port,
-		 program, version);
+		 (long unsigned int)program, (long unsigned int)version);
 
 	switch (sa->sa_family) {
 	case AF_INET:
@@ -330,6 +333,11 @@ create_auth_rpc_client(struct clnt_info *clp,
 	struct timeval	timeout;
 	struct sockaddr		*addr = (struct sockaddr *) &clp->addr;
 	socklen_t		salen;
+#ifdef HAVE_TIRPC_GSS_SECCREATE
+	rpc_gss_options_req_t	req;
+	rpc_gss_options_ret_t	ret;
+	char			mechanism[] = "kerberos_v5";
+#endif
 	pthread_t tid = pthread_self();
 
 	sec.qop = GSS_C_QOP_DEFAULT;
@@ -410,9 +418,17 @@ create_auth_rpc_client(struct clnt_info *clp,
 
 	printerr(3, "create_auth_rpc_client(0x%lx): creating context with server %s\n", 
 		tid, tgtname);
+#ifdef HAVE_TIRPC_GSS_SECCREATE
+	memset(&req, 0, sizeof(req));
+	req.my_cred = sec.cred;
+	auth = rpc_gss_seccreate(rpc_clnt, tgtname, mechanism,
+			rpcsec_gss_svc_none, NULL, &req, &ret);
+#else
 	auth = authgss_create_default(rpc_clnt, tgtname, &sec);
+#endif
 	if (!auth) {
-		if (sec.minor_status == KRB5KRB_AP_ERR_BAD_INTEGRITY) {
+#ifdef HAVE_TIRPC_GSS_SECCREATE
+		if (ret.minor_status == KRB5KRB_AP_ERR_BAD_INTEGRITY) {
 			printerr(2, "WARNING: server=%s failed context "
 				 "creation with KRB5_AP_ERR_BAD_INTEGRITY\n",
 				 clp->servername);
@@ -422,19 +438,23 @@ create_auth_rpc_client(struct clnt_info *clp,
 			else
 				retval = gssd_k5_remove_bad_service_cred(clp->servername);
 			if (!retval) {
-				auth = authgss_create_default(rpc_clnt, tgtname,
-						&sec);
+				auth = rpc_gss_seccreate(rpc_clnt, tgtname,
+						mechanism, rpcsec_gss_svc_none,
+						NULL, &req, &ret);
 				if (auth)
 					goto success;
 			}
 		}
+#endif
 		/* Our caller should print appropriate message */
 		printerr(2, "WARNING: Failed to create krb5 context for "
 			    "user with uid %d for server %s\n",
 			 uid, tgtname);
 		goto out_fail;
 	}
+#ifdef HAVE_TIRPC_GSS_SECCREATE
 success:
+#endif
 	/* Success !!! */
 	rpc_clnt->cl_auth = auth;
 	*clnt_return = rpc_clnt;
diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c
index 6f66ef4..d7116d9 100644
--- a/utils/gssd/krb5_util.c
+++ b/utils/gssd/krb5_util.c
@@ -129,6 +129,7 @@
 #include "err_util.h"
 #include "gss_util.h"
 #include "krb5_util.h"
+#include "conffile.h"
 
 /*
  * List of principals from our keytab that we
@@ -155,6 +156,8 @@ static pthread_mutex_t ple_lock = PTHREAD_MUTEX_INITIALIZER;
 
 #ifdef HAVE_SET_ALLOWABLE_ENCTYPES
 int limit_to_legacy_enctypes = 0;
+krb5_enctype *allowed_enctypes = NULL;
+int num_allowed_enctypes = 0;
 #endif
 
 /*==========================*/
@@ -304,9 +307,9 @@ gssd_find_existing_krb5_ccache(uid_t uid, char *dirname,
 				score++;
 
 			printerr(3, "CC '%s'(%s@%s) passed all checks and"
-				    " has mtime of %u\n",
+				    " has mtime of %llu\n",
 				 buf, princname, realm, 
-				 tmp_stat.st_mtime);
+				 (long long unsigned)tmp_stat.st_mtime);
 			/*
 			 * if more than one match is found, return the most
 			 * recent (the one with the latest mtime), and
@@ -341,10 +344,10 @@ gssd_find_existing_krb5_ccache(uid_t uid, char *dirname,
 				}
 				printerr(3, "CC '%s:%s/%s' is our "
 					    "current best match "
-					    "with mtime of %u\n",
-					 cctype, dirname,
+					    "with mtime of %llu\n",
+					 *cctype, dirname,
 					 best_match_dir->d_name,
-					 best_match_stat.st_mtime);
+					 (long long unsigned)best_match_stat.st_mtime);
 			}
 			free(princname);
 			free(realm);
@@ -1596,6 +1599,68 @@ out_cred:
 }
 
 #ifdef HAVE_SET_ALLOWABLE_ENCTYPES
+int
+get_allowed_enctypes(void)
+{
+	struct conf_list *allowed_etypes = NULL;
+	struct conf_list_node *node;
+	char *buf = NULL, *old = NULL;
+	int len, ret = 0;
+
+	allowed_etypes = conf_get_list("gssd", "allowed-enctypes");
+	if (allowed_etypes) {
+		TAILQ_FOREACH(node, &(allowed_etypes->fields), link) {
+			allowed_enctypes = realloc(allowed_enctypes,
+						   (num_allowed_enctypes + 1) *
+						   sizeof(*allowed_enctypes));
+			if (allowed_enctypes == NULL) {
+				ret = ENOMEM;
+				goto out_err;
+			}
+			ret = krb5_string_to_enctype(node->field,
+						     &allowed_enctypes[num_allowed_enctypes]);
+			if (ret) {
+				printerr(0, "%s: invalid enctype %s",
+					 __func__, node->field);
+				goto out_err;
+			}
+			if (get_verbosity() > 1) {
+				if (buf == NULL) {
+					len = asprintf(&buf, "%s(%d)", node->field,
+						       allowed_enctypes[num_allowed_enctypes]);
+					if (len < 0) {
+						ret = ENOMEM;
+						goto out_err;
+					}
+				} else {
+					old = buf;
+					len = asprintf(&buf, "%s,%s(%d)", old, node->field,
+						       allowed_enctypes[num_allowed_enctypes]);
+					if (len < 0) {
+						ret = ENOMEM;
+						goto out_err;
+					}
+					free(old);
+					old = NULL;
+				}
+			}
+			num_allowed_enctypes++;
+		}
+		printerr(2, "%s: allowed_enctypes = %s", __func__, buf);
+	}
+	goto out;
+out_err:
+	num_allowed_enctypes = 0;
+	free(allowed_enctypes);
+out:
+	free(buf);
+	if (old != buf)
+		free(old);
+	if (allowed_etypes)
+		conf_free_list(allowed_etypes);
+	return ret;
+}
+
 /*
  * this routine obtains a credentials handle via gss_acquire_cred()
  * then calls gss_krb5_set_allowable_enctypes() to limit the encryption
@@ -1619,6 +1684,10 @@ limit_krb5_enctypes(struct rpc_gss_sec *sec)
 	int num_enctypes = sizeof(enctypes) / sizeof(enctypes[0]);
 	extern int num_krb5_enctypes;
 	extern krb5_enctype *krb5_enctypes;
+	extern int num_allowed_enctypes;
+	extern krb5_enctype *allowed_enctypes;
+	int num_set_enctypes;
+	krb5_enctype *set_enctypes;
 	int err = -1;
 
 	if (sec->cred == GSS_C_NO_CREDENTIAL) {
@@ -1631,12 +1700,26 @@ limit_krb5_enctypes(struct rpc_gss_sec *sec)
 	 * If we failed for any reason to produce global
 	 * list of supported enctypes, use local default here.
 	 */
-	if (krb5_enctypes == NULL || limit_to_legacy_enctypes)
-		maj_stat = gss_set_allowable_enctypes(&min_stat, sec->cred,
-					&krb5oid, num_enctypes, enctypes);
-	else
-		maj_stat = gss_set_allowable_enctypes(&min_stat, sec->cred,
-					&krb5oid, num_krb5_enctypes, krb5_enctypes);
+	if (krb5_enctypes == NULL || limit_to_legacy_enctypes ||
+			allowed_enctypes) {
+		if (allowed_enctypes) {
+			printerr(2, "%s: using allowed enctypes from config\n",
+				 __func__);
+			num_set_enctypes = num_allowed_enctypes;
+			set_enctypes = allowed_enctypes;
+		} else {
+			printerr(2, "%s: using legacy enctypes\n", __func__);
+			num_set_enctypes = num_enctypes;
+			set_enctypes = enctypes;
+		}
+	} else {
+		printerr(2, "%s: using enctypes from the kernel\n", __func__);
+		num_set_enctypes = num_krb5_enctypes;
+		set_enctypes = krb5_enctypes;
+	}
+
+	maj_stat = gss_set_allowable_enctypes(&min_stat, sec->cred,
+				&krb5oid, num_set_enctypes, set_enctypes);
 
 	if (maj_stat != GSS_S_COMPLETE) {
 		pgsserr("gss_set_allowable_enctypes",
diff --git a/utils/gssd/krb5_util.h b/utils/gssd/krb5_util.h
index 7ef8701..40ad323 100644
--- a/utils/gssd/krb5_util.h
+++ b/utils/gssd/krb5_util.h
@@ -27,6 +27,7 @@ int gssd_k5_remove_bad_service_cred(char *srvname);
 #ifdef HAVE_SET_ALLOWABLE_ENCTYPES
 extern int limit_to_legacy_enctypes;
 int limit_krb5_enctypes(struct rpc_gss_sec *sec);
+int get_allowed_enctypes(void);
 #endif
 
 /*
diff --git a/utils/gssd/svcgssd_proc.c b/utils/gssd/svcgssd_proc.c
index b403143..7fecd1a 100644
--- a/utils/gssd/svcgssd_proc.c
+++ b/utils/gssd/svcgssd_proc.c
@@ -102,10 +102,10 @@ do_svc_downcall(gss_buffer_desc *out_handle, struct svc_cred *cred,
 	qword_addint(&bp, &blen, cred->cr_uid);
 	qword_addint(&bp, &blen, cred->cr_gid);
 	qword_addint(&bp, &blen, cred->cr_ngroups);
-	printerr(2, "mech: %s, hndl len: %d, ctx len %d, timeout: %d (%d from now), "
+	printerr(2, "mech: %s, hndl len: %zd, ctx len %zd, timeout: %lld (%lld from now), "
 		 "clnt: %s, uid: %d, gid: %d, num aux grps: %d:\n",
 		 fname, out_handle->length, context_token->length,
-		 endtime, endtime - time(0),
+		 (long long int)endtime, (long long int)(endtime - time(0)),
 		 client_name ? client_name : "<null>",
 		 cred->cr_uid, cred->cr_gid, cred->cr_ngroups);
 	for (i=0; i < cred->cr_ngroups; i++) {
@@ -232,7 +232,7 @@ get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred)
 	}
 	if (name.length >= 0xffff || /* be certain name.length+1 doesn't overflow */
 	    !(sname = calloc(name.length + 1, 1))) {
-		printerr(0, "WARNING: get_ids: error allocating %d bytes "
+		printerr(0, "WARNING: get_ids: error allocating %zd bytes "
 			"for sname\n", name.length + 1);
 		gss_release_buffer(&min_stat, &name);
 		goto out;
@@ -360,7 +360,7 @@ handle_nullreq(char *cp) {
 	if (in_handle.length != 0) { /* CONTINUE_INIT case */
 		if (in_handle.length != sizeof(ctx)) {
 			printerr(0, "WARNING: handle_nullreq: "
-				    "input handle has unexpected length %d\n",
+				    "input handle has unexpected length %zd\n",
 				    in_handle.length);
 			goto out_err;
 		}
diff --git a/utils/mount/mount_libmount.c b/utils/mount/mount_libmount.c
index aa4ac5c..fd6cb2c 100644
--- a/utils/mount/mount_libmount.c
+++ b/utils/mount/mount_libmount.c
@@ -442,7 +442,7 @@ int main(int argc, char *argv[])
 	mnt_init_debug(0);
 	cxt = mnt_new_context();
 	if (!cxt) {
-		nfs_error(_("Can't initilize libmount: %s"),
+		nfs_error(_("Can't initialize libmount: %s"),
 					strerror(errno));
 		rc = EX_FAIL;
 		goto done;
diff --git a/utils/mount/nfs.man b/utils/mount/nfs.man
index c0ba4d0..233a717 100644
--- a/utils/mount/nfs.man
+++ b/utils/mount/nfs.man
@@ -186,6 +186,10 @@ infrequently used request types are retried after 1.1 seconds.
 After each retransmission, the NFS client doubles the timeout for
 that request,
 up to a maximum timeout length of 60 seconds.
+.IP
+Any timeo value greater than default value will be set to the default value.
+For TCP and RDMA, default value is 600 (60 seconds).
+For UDP, default value is 60 (6 seconds).
 .TP 1.5i
 .BI retrans= n
 The number of times the NFS client retries a request before
@@ -964,7 +968,7 @@ Some server features misbehave in the face of a migration-compatible
 identification string.
 The
 .B nomigration
-option retains the use of a traditional client indentification string
+option retains the use of a traditional client identification string
 which is compatible with legacy NFS servers.
 This is also the behavior if neither option is specified.
 A client's open and lock state cannot be migrated transparently
@@ -1832,7 +1836,7 @@ auxiliary services such as the NLM service can choose
 any unused port number at random.
 .P
 Common firewall configurations block the well-known rpcbind port.
-In the absense of an rpcbind service,
+In the absence of an rpcbind service,
 the server administrator fixes the port number
 of NFS-related services so that the firewall
 can allow access to specific NFS service ports.
diff --git a/utils/mount/nfsmount.conf.man b/utils/mount/nfsmount.conf.man
index 34879c8..6419190 100644
--- a/utils/mount/nfsmount.conf.man
+++ b/utils/mount/nfsmount.conf.man
@@ -43,7 +43,7 @@ and will be shifted to lower case before being passed to the filesystem.
 .PP
 Boolean mount options which do not need an equals sign must be given as
 .RI \[dq] option =True".
-Instead of preceeding such an option with
+Instead of preceding such an option with
 .RB \[dq] no \[dq]
 its negation must be given as
 .RI \[dq] option =False".
@@ -115,16 +115,17 @@ All mounts to the '/export/home' export will be performed in
 the background (i.e. done asynchronously).
 .RE
 .SH FILES
-.TP 10n
+.I /usr/etc/nfsmount.conf
+.br
+.I /usr/etc/nfsmount.conf.d/*.conf
+.br
 .I /etc/nfsmount.conf
-Default NFS mount configuration file
-.TP 10n
-.I /etc/nfsmount.conf.d
-When this directory exists and files ending
-with ".conf" exist, those files will be
-used to set configuration variables. These
-files will override variables set
-in /etc/nfsmount.conf
+.br
+.I /etc/nfsmount.conf.d/*.conf
+.br
+.IP
+Default NFS mount configuration files, variables set in the later file
+over-ride those in the earlier file.
 .PD
 .SH SEE ALSO
 .BR nfs (5),
diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
index dbdd11e..a92c420 100644
--- a/utils/mount/stropts.c
+++ b/utils/mount/stropts.c
@@ -780,6 +780,14 @@ static int nfs_do_mount_v4(struct nfsmount_info *mi,
 		goto out_fail;
 	}
 
+	if (po_contains(options, "namlen")) {
+		po_remove_all(options, "namlen");
+		if (verbose) {
+			printf(_("%s: Ignore unsupported nfs4 mount option 'namlen' in '%s'\n"),
+				progname, *mi->extra_opts);
+		}
+	}
+
 	if (mi->version.v_mode != V_SPECIFIC) {
 		char *fmt;
 		switch (mi->version.minor) {
diff --git a/utils/nfsdcld/nfsdcld.man b/utils/nfsdcld/nfsdcld.man
index 861f1c4..ee6e9dc 100644
--- a/utils/nfsdcld/nfsdcld.man
+++ b/utils/nfsdcld/nfsdcld.man
@@ -198,7 +198,7 @@ initialize client tracking in the following order:  First, the \fBnfsdcld\fR upc
 the \fBnfsdcltrack\fR usermodehelper upcall.  Finally, the legacy client tracking.
 .PP
 This daemon should be run as root, as the pipe that it uses to communicate
-with the kernel is only accessable by root. The daemon however does drop all
+with the kernel is only accessible by root. The daemon however does drop all
 superuser capabilities after starting. Because of this, the \fIstoragedir\fR
 should be owned by root, and be readable and writable by owner.
 .PP
diff --git a/utils/nfsdcltrack/nfsdcltrack.man b/utils/nfsdcltrack/nfsdcltrack.man
index cc24b7a..3905ba4 100644
--- a/utils/nfsdcltrack/nfsdcltrack.man
+++ b/utils/nfsdcltrack/nfsdcltrack.man
@@ -80,7 +80,7 @@ section.  For example:
 .br
   storagedir = /shared/nfs/nfsdcltrack
 .in -5
-Debuging to syslog can also be enabled by setting "debug = 1" in this file.
+Debugging to syslog can also be enabled by setting "debug = 1" in this file.
 .SH "LEGACY TRANSITION MECHANISM"
 .IX Header "LEGACY TRANSITION MECHANISM"
 The Linux kernel NFSv4 server has historically tracked this information
diff --git a/utils/nfsref/nfsref.c b/utils/nfsref/nfsref.c
index 7f97d01..aa8414b 100644
--- a/utils/nfsref/nfsref.c
+++ b/utils/nfsref/nfsref.c
@@ -24,8 +24,6 @@
  */
 
 #include <sys/types.h>
-#include <sys/capability.h>
-#include <sys/prctl.h>
 #include <sys/stat.h>
 
 #include <stdbool.h>
diff --git a/utils/nfsref/nfsref.man b/utils/nfsref/nfsref.man
index 1261549..1970f9d 100644
--- a/utils/nfsref/nfsref.man
+++ b/utils/nfsref/nfsref.man
@@ -53,33 +53,37 @@ nfsref \- manage NFS referrals
 NFS version 4 introduces the concept of
 .I file system referrals
 to NFS.
-A file system referral is like a symbolic link on a file server
-to another file system share, possibly on another file server.
-On an NFS client, a referral behaves like an automounted directory.
-The client, under the server's direction, mounts a new NFS export
-automatically when an application first accesses that directory.
 .P
-Referrals are typically used to construct a single file name space
-across multiple file servers.
-Because file servers control the shape of the name space,
-no client configuration is required,
-and all clients see the same referral information.
+A file system referral is like a symbolic link
+(or,
+.IR symlink )
+to another file system share, typically on another file server.
+An NFS client, under the server's direction,
+mounts the referred-to NFS export
+automatically when an application first accesses it.
 .P
-The Linux NFS server supports NFS version 4 referrals.
-Administrators can specify the
-.B refer=
-export option in
-.I /etc/exports
-to configure a list of exports from which the client can choose.
-See
-.BR exports (5)
-for details.
+NFSv4 referrals can be used to transparently redirect clients
+to file systems that have been moved elsewhere, or
+to construct a single file name space across multiple file servers.
+Because file servers control the shape of the whole file name space,
+no client configuration is required.
 .P
 .SH DESCRIPTION
+A
+.I junction
+is a file system object on an NFS server that,
+when an NFS client encounters it, triggers a referral.
+Similar to a symlink, a junction contains one or more target locations
+that the server sends to clients in the form of an NFSv4 referral.
+.P
+On Linux, an existing directory can be converted to a junction
+and back atomically and without the loss of the directory contents.
+When a directory acts as a junction, it's local content is hidden
+from NFSv4 clients.
+.P
 The
 .BR nfsref (8)
-command is a simple way to get started managing junction metadata.
-Other administrative commands provide richer access to junction information.
+command is a simple way to get started managing junctions and their content.
 .SS Subcommands
 Valid
 .BR nfsref (8)
@@ -135,6 +139,10 @@ For the
 .B add
 subcommand, the default value if this option is not specified is
 .BR nfs-basic .
+The
+.B nfs-fedfs
+type is not used in this implementation.
+.IP
 For the
 .B remove
 and
@@ -163,18 +171,12 @@ you might issue this command as root:
 .sp
 # mkdir /home
 .br
-# nfsref --type=nfs-basic add /home home.example.net /
+# nfsref add /home home.example.net /
 .br
 Created junction /home.
 .sp
 .RE
-.SH FILES
-.TP
-.I /etc/exports
-NFS server export table
 .SH "SEE ALSO"
-.BR exports (5)
-.sp
-RFC 5661 for a description of NFS version 4 referrals
+RFC 8881 for a description of the NFS version 4 referral mechanism
 .SH "AUTHOR"
 Chuck Lever <chuck.lever@oracle.com>
diff --git a/utils/statd/start-statd b/utils/statd/start-statd
index b11a7d9..67a2f4a 100755
--- a/utils/statd/start-statd
+++ b/utils/statd/start-statd
@@ -8,7 +8,7 @@ PATH="/sbin:/usr/sbin:/bin:/usr/bin"
 
 # Use flock to serialize the running of this script
 exec 9> /run/rpc.statd.lock
-flock -e 9
+flock -x 9
 
 if [ -s /run/rpc.statd.pid ] &&
        [ "1$(cat /run/rpc.statd.pid)" -gt 1 ] &&