Blob Blame History Raw
diff --git a/.gitignore b/.gitignore
index df791a8..682153d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -86,3 +86,5 @@ systemd/rpc-gssd.service
 cscope.*
 # generic editor backup et al
 *~
+# file generated by ctags
+tags
diff --git a/NEWS b/NEWS
index e70ae8a..77872c5 100644
--- a/NEWS
+++ b/NEWS
@@ -1,32 +1,32 @@
 Significant changes for nfs-utils 1.1.0 - March/April 2007
 
- - rpc.lockd is gone.  One 3 old kernel releases need it.
- - rpc.rquotad is gone.  Use the one from the 'quota' package.
-   Everone else does.
+ - rpc.lockd is gone. One 3 old kernel releases need it.
+ - rpc.rquotad is gone. Use the one from the 'quota' package.
+   Everyone else does.
  - /sbin/{u,}mount.nfs{,4} are now installed so 'mount' will
    use these to mount nfs filesystems instead of internal code.
   + mount.nfs will check for 'statd' to be running when mounting
-    a filesystem which requires it.  If it is not running it will
+    a filesystem which requires it. If it is not running it will
     run "/usr/sbin/start-statd" to try to start it.
     If statd is not running and cannot be started, mount.nfs will
     refuse to mount the filesystem and will suggest the 'nolock'
     option.
  - Substantial changes to statd
   + The 'notify' process that must happen at boot has been split
-    into a separate program "sm-notify".  It ensures that it
-    only runs once even if you restart statd.  This is correct
+    into a separate program "sm-notify". It ensures that it
+    only runs once even if you restart statd. This is correct
     behaviour.
   + statd stores state in the files in /var/lib/nfs/sm/ so that
     if you kill and restart it, it will restore that state and
     continue working correctly.
   + statd makes more use of DNS lookup and should handle
-    multi-homed peers better.  In particular, files in
+    multi-homed peers better. In particular, files in
     /var/lib/nfs/sm/ are named with the Full Qualified Domain Name
     if available.
  - If you export a directory as 'crossmnt', all filesystems
    mounted beneath are automatically exported with the same
    options (unless explicitly exported with different options).
- - subtree_check is no-longer the default.  The default is now
+ - subtree_check is no-longer the default. The default is now
    no_subtree_check.
  - By default the system 'rpcgen' is used while building
    nfs-utils rather than the internal one.
@@ -43,14 +43,14 @@ Significant changes for nfs-utils 1.1.0 - March/April 2007
 
  - A new option, -n, was added to rpc.gssd which specifies that
    accesses by root should not use 'machine credentials' when
-   accessing NFS file systems mounted with Kerberos.  Using this
+   accessing NFS file systems mounted with Kerberos. Using this
    option allows the root user to access the NFS space using any
    Kerberos principal, rather than always using the machine
-   credentials.  However, its use also requires that root manually
+   credentials. However, its use also requires that root manually
    authenticate before attempting a mount with Kerberos.
 
    When rpc.gssd uses machine credentials, the selection algorithm has
-   been changed.  Instead of simply using the first "nfs/*" key in the
+   been changed. Instead of simply using the first "nfs/*" key in the
    keytab, the keytab is now searched for keys in the following
    defined order:
 
diff --git a/README b/README
index 5e98240..3b0e771 100644
--- a/README
+++ b/README
@@ -25,7 +25,7 @@ Unpack the sources and run these commands:
     # ./configure
     # make
 
-To install binaries and documenation, run this command:
+To install binaries and documentation, run this command:
 
     # make install
 
@@ -40,7 +40,7 @@ Updating to the latest head after you've already got it.
 
 	git pull
 
-Building requires that autotools be installed.  To invoke them
+Building requires that autotools be installed. To invoke them
 simply
 
 	sh autogen.sh
@@ -70,7 +70,7 @@ scripts can be written to work correctly.
 3.1.  SERVER STARTUP
 
 
-   A/  mount -t nfsd /proc/fs/nfsd
+   A/  mount -t nfsd nfsd /proc/fs/nfsd
       This filesystem needs to be mount before most daemons,
       particularly exportfs, mountd, svcgssd, idmapd.
       It could be mounted once, or the script that starts each daemon
@@ -95,27 +95,27 @@ scripts can be written to work correctly.
 
    D/ rpc.statd --no-notify
        It is best if statd is started before nfsd though this isn't
-       critical.  Certainly it should be at most a few seconds after
+       critical. Certainly, it should be at most a few seconds after
        nfsd.
        When nfsd starts it will start lockd. If lockd then receives a
-       lock request it will communicate with statd.  If statd is not
+       lock request, it will communicate with statd. If statd is not
        running lockd will retry, but it won't wait forever for a
        reply.
        Note that if statd is started before nfsd, the --no-notify
-       option must be used.  If notify requests are sent out before
+       option must be used. If notify requests are sent out before
        nfsd start, clients may try to reclaim locks and, on finding
        that lockd isn't running, they will give up and never reclaim
        the lock.
        rpc.statd is only needed for NFSv2 and NFSv3 support.
 
    E/ rpc.nfsd
-       Starting nfsd will automatically start lockd.  The nfs server
+       Starting nfsd will automatically start lockd. The nfs server
        will now be fully active and respond to any requests from
        clients.
        
    F/ sm-notify
        This will notify any client which might have locks from before
-       a reboot to try to reclaim their locks.  This should start
+       a reboot to try to reclaim their locks. This should start
        immediately after rpc.nfsd is started so that clients have a
        chance to reclaim locks within the 90 second grace period.
        sm-notify is only needed for NFSv2 and NFSv3 support.
diff --git a/configure.ac b/configure.ac
index f1c46c5..7672a76 100644
--- a/configure.ac
+++ b/configure.ac
@@ -71,18 +71,6 @@ AC_ARG_WITH(systemd,
 	AM_CONDITIONAL(INSTALL_SYSTEMD, [test "$use_systemd" = 1])
 	AC_SUBST(unitdir)
 
-modprobedir=/usr/lib/modprobe.d
-AC_ARG_WITH(modprobedir,
-	[AS_HELP_STRING([--with-modprobedir@<:@=modprobe-dir-path@:>@],[install modprobe config files @<:@Default: /usr/lib/modprobe.d@:>@])],
-	if test "$withval" != "no" ; then
-		modprobedir=$withval
-	else
-		modprobedir=
-	fi
-	)
-	AM_CONDITIONAL(INSTALL_MODPROBEDIR, [test -n "$modprobedir"])
-	AC_SUBST(modprobedir)
-
 AC_ARG_ENABLE(nfsv4,
 	[AS_HELP_STRING([--disable-nfsv4],[disable support for NFSv4 @<:@default=no@:>@])],
 	enable_nfsv4=$enableval,
@@ -249,6 +237,16 @@ AC_ARG_ENABLE(nfsdcld,
 	enable_nfsdcld=$enableval,
 	enable_nfsdcld="yes")
 
+AC_ARG_ENABLE(nfsrahead,
+	[AS_HELP_STRING([--disable-nfsrahead],[disable nfsrahead command @<:@default=no@:>@])],
+	enable_nfsrahead=$enableval,
+	enable_nfsrahead="yes")
+	AM_CONDITIONAL(CONFIG_NFSRAHEAD, [test "$enable_nfsrahead" = "yes" ])
+	if test "$enable_nfsrahead" = yes; then
+		dnl Check for -lmount
+		PKG_CHECK_MODULES([LIBMOUNT], [mount])
+	fi
+
 AC_ARG_ENABLE(nfsdcltrack,
 	[AS_HELP_STRING([--disable-nfsdcltrack],[disable NFSv4 clientid tracking programs @<:@default=no@:>@])],
 	enable_nfsdcltrack=$enableval,
@@ -678,12 +676,12 @@ AC_SUBST([AM_CFLAGS], ["$my_am_cflags $flg1 $flg2 $flg3 $flg4 $flg5"])
 # Make sure that $ACLOCAL_FLAGS are used during a rebuild
 AC_SUBST([ACLOCAL_AMFLAGS], ["-I $ac_macro_dir \$(ACLOCAL_FLAGS)"])
 
-# make _sysconfdir available for substituion in config files
+# make _sysconfdir available for substitution in config files
 # 2 "evals" needed late to expand variable names.
 AC_SUBST([_sysconfdir])
 AC_CONFIG_COMMANDS_PRE([eval eval _sysconfdir=$sysconfdir])
 
-# make _statedir available for substituion in config files
+# make _statedir available for substitution in config files
 # 2 "evals" needed late to expand variable names.
 AC_SUBST([_statedir])
 AC_CONFIG_COMMANDS_PRE([eval eval _statedir=$statedir])
@@ -695,7 +693,7 @@ else
 fi
 AC_SUBST(rpc_pipefsmount)
 
-# make _rpc_pipefsmount available for substituion in config files
+# make _rpc_pipefsmount available for substitution in config files
 # 2 "evals" needed late to expand variable names.
 AC_SUBST([_rpc_pipefsmount])
 AC_CONFIG_COMMANDS_PRE([eval eval _rpc_pipefsmount=$rpc_pipefsmount])
diff --git a/support/export/auth.c b/support/export/auth.c
index 03ce4b8..2d7960f 100644
--- a/support/export/auth.c
+++ b/support/export/auth.c
@@ -82,7 +82,7 @@ check_useipaddr(void)
 }
 
 unsigned int
-auth_reload()
+auth_reload(void)
 {
 	struct stat		stb;
 	static ino_t		last_inode;
diff --git a/support/export/cache.c b/support/export/cache.c
index a5823e9..2497d4f 100644
--- a/support/export/cache.c
+++ b/support/export/cache.c
@@ -346,27 +346,27 @@ static int uuid_by_path(char *path, int type, size_t uuidlen, char *uuid)
 
 	/* Possible sources of uuid are
 	 * - blkid uuid
-	 * - statfs64 uuid
+	 * - statfs uuid
 	 *
-	 * On some filesystems (e.g. vfat) the statfs64 uuid is simply an
+	 * On some filesystems (e.g. vfat) the statfs uuid is simply an
 	 * encoding of the device that the filesystem is mounted from, so
 	 * it we be very bad to use that (as device numbers change).  blkid
 	 * must be preferred.
-	 * On other filesystems (e.g. btrfs) the statfs64 uuid contains
+	 * On other filesystems (e.g. btrfs) the statfs uuid contains
 	 * important info that the blkid uuid cannot contain:  This happens
 	 * when multiple subvolumes are exported (they have the same
-	 * blkid uuid but different statfs64 uuids).
+	 * blkid uuid but different statfs uuids).
 	 * We rely on get_uuid_blkdev *knowing* which is which and not returning
-	 * a uuid for filesystems where the statfs64 uuid is better.
+	 * a uuid for filesystems where the statfs uuid is better.
 	 *
 	 */
-	struct statfs64 st;
+	struct statfs st;
 	char fsid_val[17];
 	const char *blkid_val = NULL;
 	const char *val;
 	int rc;
 
-	rc = nfsd_path_statfs64(path, &st);
+	rc = nfsd_path_statfs(path, &st);
 
 	if (type == 0 && rc == 0) {
 		const unsigned long *bad;
diff --git a/support/export/client.c b/support/export/client.c
index ea4f89d..79164fe 100644
--- a/support/export/client.c
+++ b/support/export/client.c
@@ -699,6 +699,9 @@ check_netgroup(const nfs_client *clp, const struct addrinfo *ai)
 
 	/* check whether the IP itself is in the netgroup */
 	ip = calloc(INET6_ADDRSTRLEN, 1);
+	if (ip == NULL)
+		goto out;
+
 	if (inet_ntop(ai->ai_family, &(((struct sockaddr_in *)ai->ai_addr)->sin_addr), ip, INET6_ADDRSTRLEN) == ip) {
 		if (innetgr(netgroup, ip, NULL, NULL)) {
 			free(hname);
diff --git a/support/export/v4clients.c b/support/export/v4clients.c
index 5f15b61..3230251 100644
--- a/support/export/v4clients.c
+++ b/support/export/v4clients.c
@@ -26,7 +26,7 @@ void v4clients_init(void)
 {
 	struct stat sb;
 
-	if (!stat("/proc/fs/nfsd/clients", &sb) == 0 ||
+	if (stat("/proc/fs/nfsd/clients", &sb) != 0 ||
 	    !S_ISDIR(sb.st_mode))
 		return;
 	if (clients_fd >= 0)
diff --git a/support/export/v4root.c b/support/export/v4root.c
index c12a7d8..fbb0ad5 100644
--- a/support/export/v4root.c
+++ b/support/export/v4root.c
@@ -198,7 +198,7 @@ static int v4root_add_parents(nfs_export *exp)
  * looking for components of the v4 mount.
  */
 void
-v4root_set()
+v4root_set(void)
 {
 	nfs_export	*exp;
 	int	i;
diff --git a/support/export/xtab.c b/support/export/xtab.c
index c888a80..e210ca9 100644
--- a/support/export/xtab.c
+++ b/support/export/xtab.c
@@ -135,7 +135,7 @@ xtab_write(char *xtab, char *xtabtmp, char *lockfn, int is_export)
 }
 
 int
-xtab_export_write()
+xtab_export_write(void)
 {
 	return xtab_write(etab.statefn, etab.tmpfn, etab.lockfn, 1);
 }
diff --git a/support/include/nfsd_path.h b/support/include/nfsd_path.h
index 3b73aad..aa1e1dd 100644
--- a/support/include/nfsd_path.h
+++ b/support/include/nfsd_path.h
@@ -7,7 +7,7 @@
 #include <sys/stat.h>
 
 struct file_handle;
-struct statfs64;
+struct statfs;
 
 void 		nfsd_path_init(void);
 
@@ -18,8 +18,8 @@ char *		nfsd_path_prepend_dir(const char *dir, const char *pathname);
 int 		nfsd_path_stat(const char *pathname, struct stat *statbuf);
 int 		nfsd_path_lstat(const char *pathname, struct stat *statbuf);
 
-int		nfsd_path_statfs64(const char *pathname,
-				   struct statfs64 *statbuf);
+int		nfsd_path_statfs(const char *pathname,
+				   struct statfs *statbuf);
 
 char *		nfsd_realpath(const char *path, char *resolved_path);
 
diff --git a/support/junction/junction.c b/support/junction/junction.c
index 41cce26..0628bb0 100644
--- a/support/junction/junction.c
+++ b/support/junction/junction.c
@@ -63,7 +63,7 @@ junction_open_path(const char *pathname, int *fd)
 	if (pathname == NULL || fd == NULL)
 		return FEDFS_ERR_INVAL;
 
-	tmp = open(pathname, O_DIRECTORY);
+	tmp = open(pathname, O_PATH|O_DIRECTORY);
 	if (tmp == -1) {
 		switch (errno) {
 		case EPERM:
@@ -93,7 +93,7 @@ junction_is_directory(int fd, const char *path)
 {
 	struct stat stb;
 
-	if (fstat(fd, &stb) == -1) {
+	if (fstatat(fd, "", &stb, AT_NO_AUTOMOUNT|AT_EMPTY_PATH) == -1) {
 		xlog(D_GENERAL, "%s: failed to stat %s: %m",
 				__func__, path);
 		return FEDFS_ERR_ACCESS;
@@ -121,7 +121,7 @@ junction_is_sticky_bit_set(int fd, const char *path)
 {
 	struct stat stb;
 
-	if (fstat(fd, &stb) == -1) {
+	if (fstatat(fd, "", &stb, AT_NO_AUTOMOUNT|AT_EMPTY_PATH) == -1) {
 		xlog(D_GENERAL, "%s: failed to stat %s: %m",
 				__func__, path);
 		return FEDFS_ERR_ACCESS;
@@ -155,7 +155,7 @@ junction_set_sticky_bit(int fd, const char *path)
 {
 	struct stat stb;
 
-	if (fstat(fd, &stb) == -1) {
+	if (fstatat(fd, "", &stb, AT_NO_AUTOMOUNT|AT_EMPTY_PATH) == -1) {
 		xlog(D_GENERAL, "%s: failed to stat %s: %m",
 			__func__, path);
 		return FEDFS_ERR_ACCESS;
@@ -393,7 +393,7 @@ junction_get_mode(const char *pathname, mode_t *mode)
 	if (retval != FEDFS_OK)
 		return retval;
 
-	if (fstat(fd, &stb) == -1) {
+	if (fstatat(fd, "", &stb, AT_NO_AUTOMOUNT|AT_EMPTY_PATH) == -1) {
 		xlog(D_GENERAL, "%s: failed to stat %s: %m",
 			__func__, pathname);
 		(void)close(fd);
diff --git a/support/misc/nfsd_path.c b/support/misc/nfsd_path.c
index 65e53c1..c3dea4f 100644
--- a/support/misc/nfsd_path.c
+++ b/support/misc/nfsd_path.c
@@ -184,46 +184,46 @@ nfsd_path_lstat(const char *pathname, struct stat *statbuf)
 	return nfsd_run_stat(nfsd_wq, nfsd_lstatfunc, pathname, statbuf);
 }
 
-struct nfsd_statfs64_data {
+struct nfsd_statfs_data {
 	const char *pathname;
-	struct statfs64 *statbuf;
+	struct statfs *statbuf;
 	int ret;
 	int err;
 };
 
 static void
-nfsd_statfs64func(void *data)
+nfsd_statfsfunc(void *data)
 {
-	struct nfsd_statfs64_data *d = data;
+	struct nfsd_statfs_data *d = data;
 
-	d->ret = statfs64(d->pathname, d->statbuf);
+	d->ret = statfs(d->pathname, d->statbuf);
 	if (d->ret < 0)
 		d->err = errno;
 }
 
 static int
-nfsd_run_statfs64(struct xthread_workqueue *wq,
+nfsd_run_statfs(struct xthread_workqueue *wq,
 		  const char *pathname,
-		  struct statfs64 *statbuf)
+		  struct statfs *statbuf)
 {
-	struct nfsd_statfs64_data data = {
+	struct nfsd_statfs_data data = {
 		pathname,
 		statbuf,
 		0,
 		0
 	};
-	xthread_work_run_sync(wq, nfsd_statfs64func, &data);
+	xthread_work_run_sync(wq, nfsd_statfsfunc, &data);
 	if (data.ret < 0)
 		errno = data.err;
 	return data.ret;
 }
 
 int
-nfsd_path_statfs64(const char *pathname, struct statfs64 *statbuf)
+nfsd_path_statfs(const char *pathname, struct statfs *statbuf)
 {
 	if (!nfsd_wq)
-		return statfs64(pathname, statbuf);
-	return nfsd_run_statfs64(nfsd_wq, pathname, statbuf);
+		return statfs(pathname, statbuf);
+	return nfsd_run_statfs(nfsd_wq, pathname, statbuf);
 }
 
 struct nfsd_realpath_data {
diff --git a/support/nfs/xlog.c b/support/nfs/xlog.c
index e5861b9..fa125ce 100644
--- a/support/nfs/xlog.c
+++ b/support/nfs/xlog.c
@@ -46,11 +46,13 @@ int export_errno = 0;
 
 static void	xlog_toggle(int sig);
 static struct xlog_debugfac	debugnames[] = {
+	{ "0",		0, },
 	{ "general",	D_GENERAL, },
 	{ "call",	D_CALL, },
 	{ "auth",	D_AUTH, },
 	{ "parse",	D_PARSE, },
 	{ "all",	D_ALL, },
+	{ "1",		D_ALL, },
 	{ NULL,		0, },
 };
 
@@ -119,13 +121,14 @@ xlog_sconfig(char *kind, int on)
 {
 	struct xlog_debugfac	*tbl = debugnames;
 
-	while (tbl->df_name != NULL && strcasecmp(tbl->df_name, kind)) 
+	while (tbl->df_name != NULL && strcasecmp(tbl->df_name, kind))
 		tbl++;
 	if (!tbl->df_name) {
 		xlog (L_WARNING, "Invalid debug facility: %s\n", kind);
 		return;
 	}
-	xlog_config(tbl->df_fac, on);
+	if (tbl->df_fac)
+		xlog_config(tbl->df_fac, on);
 }
 
 void
diff --git a/support/nfsidmap/regex.c b/support/nfsidmap/regex.c
index 958b4ac..8424179 100644
--- a/support/nfsidmap/regex.c
+++ b/support/nfsidmap/regex.c
@@ -542,7 +542,7 @@ struct trans_func regex_trans = {
 	.gss_princ_to_grouplist	= regex_gss_princ_to_grouplist,
 };
 
-struct trans_func *libnfsidmap_plugin_init()
+struct trans_func *libnfsidmap_plugin_init(void)
 {
 	return (&regex_trans);
 }
diff --git a/systemd/50-nfs.conf b/systemd/50-nfs.conf
deleted file mode 100644
index 19e8ee7..0000000
--- a/systemd/50-nfs.conf
+++ /dev/null
@@ -1,16 +0,0 @@
-# Ensure all NFS systctl settings get applied when modules load
-
-# sunrpc module supports "sunrpc.*" sysctls
-install sunrpc /sbin/modprobe --ignore-install sunrpc $CMDLINE_OPTS && { /sbin/sysctl -q --pattern sunrpc --system; exit 0; }
-
-# rpcrdma module supports sunrpc.svc_rdma.*
-install rpcrdma /sbin/modprobe --ignore-install rpcrdma $CMDLINE_OPTS && { /sbin/sysctl -q --pattern sunrpc.svc_rdma --system; exit 0; }
-
-# lockd module supports "fs.nfs.nlm*" and "fs.nfs.nsm*" sysctls
-install lockd /sbin/modprobe --ignore-install lockd $CMDLINE_OPTS && { /sbin/sysctl -q --pattern fs.nfs.n[sl]m --system; exit 0; }
-
-# nfsv4 module supports "fs.nfs.*" sysctls (nfs_callback_tcpport and idmap_cache_timeout)
-install nfsv4 /sbin/modprobe --ignore-install nfsv4 $CMDLINE_OPTS && { /sbin/sysctl -q --pattern 'fs.nfs.(nfs_callback_tcpport|idmap_cache_timeout)' --system; exit 0; }
-
-# nfs module supports "fs.nfs.*" sysctls
-install nfs /sbin/modprobe --ignore-install nfs $CMDLINE_OPTS && { /sbin/sysctl -q --pattern fs.nfs --system; exit 0; }
diff --git a/systemd/60-nfs.rules b/systemd/60-nfs.rules
new file mode 100644
index 0000000..188423c
--- /dev/null
+++ b/systemd/60-nfs.rules
@@ -0,0 +1,21 @@
+# Ensure all NFS systctl settings get applied when modules load
+
+# sunrpc module supports "sunrpc.*" sysctls
+ACTION=="add", SUBSYSTEM=="module", KERNEL=="sunrpc", \
+  RUN+="/sbin/sysctl -q --pattern ^sunrpc --system"
+
+# rpcrdma module supports sunrpc.svc_rdma.*
+ACTION=="add", SUBSYSTEM=="module", KERNEL=="rpcrdma", \
+  RUN+="/sbin/sysctl -q --pattern ^sunrpc.svc_rdma --system"
+
+# lockd module supports "fs.nfs.nlm*" and "fs.nfs.nsm*" sysctls
+ACTION=="add", SUBSYSTEM=="module", KERNEL=="lockd", \
+  RUN+="/sbin/sysctl -q --pattern ^fs.nfs.n[sl]m --system"
+
+# nfsv4 module supports "fs.nfs.*" sysctls (nfs_callback_tcpport and idmap_cache_timeout)
+ACTION=="add", SUBSYSTEM=="module", KERNEL=="nfsv4", \
+  RUN+="/sbin/sysctl -q --pattern ^fs.nfs.(nfs_callback_tcpport|idmap_cache_timeout) --system"
+
+# nfs module supports "fs.nfs.*" sysctls
+ACTION=="add", SUBSYSTEM=="module", KERNEL=="nfs", \
+  RUN+="/sbin/sysctl -q --pattern ^fs.nfs --system"
diff --git a/systemd/Makefile.am b/systemd/Makefile.am
index 7b5ab84..577c6a2 100644
--- a/systemd/Makefile.am
+++ b/systemd/Makefile.am
@@ -2,7 +2,8 @@
 
 MAINTAINERCLEANFILES = Makefile.in
 
-modprobe_files = 50-nfs.conf
+udev_rulesdir = /usr/lib/udev/rules.d/
+udev_files = 60-nfs.rules
 
 unit_files =  \
     nfs-client.target \
@@ -53,7 +54,7 @@ endif
 
 man5_MANS	= nfs.conf.man
 man7_MANS	= nfs.systemd.man
-EXTRA_DIST = $(unit_files) $(modprobe_files) $(man5_MANS) $(man7_MANS)
+EXTRA_DIST = $(unit_files) $(udev_files) $(man5_MANS) $(man7_MANS)
 
 generator_dir = $(unitdir)/../system-generators
 
@@ -75,14 +76,10 @@ rpc_pipefs_generator_LDADD = ../support/nfs/libnfs.la
 
 if INSTALL_SYSTEMD
 genexec_PROGRAMS = nfs-server-generator rpc-pipefs-generator
-install-data-hook: $(unit_files) $(modprobe_files)
+install-data-hook: $(unit_files) $(udev_files)
 	mkdir -p $(DESTDIR)/$(unitdir)
 	cp $(unit_files) $(DESTDIR)/$(unitdir)
 	cp $(rpc_pipefs_mount_file) $(DESTDIR)/$(unitdir)/$(rpc_pipefsmount)
-else
-install-data-hook: $(modprobe_files)
-endif
-if INSTALL_MODPROBEDIR
-	mkdir -p $(DESTDIR)$(modprobedir)
-	cp $(modprobe_files) $(DESTDIR)$(modprobedir)
+	mkdir -p $(DESTDIR)/$(udev_rulesdir)
+	cp $(udev_files) $(DESTDIR)/$(udev_rulesdir)
 endif
diff --git a/systemd/auth-rpcgss-module.service b/systemd/auth-rpcgss-module.service
index 4548283..4a69a7b 100644
--- a/systemd/auth-rpcgss-module.service
+++ b/systemd/auth-rpcgss-module.service
@@ -8,8 +8,9 @@
 Description=Kernel Module supporting RPCSEC_GSS
 DefaultDependencies=no
 Before=gssproxy.service rpc-svcgssd.service rpc-gssd.service
-Wants=gssproxy.service rpc-svcgssd.service rpc-gssd.service
+Wants=gssproxy.service rpc-gssd.service
 ConditionPathExists=/etc/krb5.keytab
+ConditionVirtualization=!container
 
 [Service]
 Type=oneshot
diff --git a/systemd/nfs-server.service b/systemd/nfs-server.service
index b432f91..2cdd786 100644
--- a/systemd/nfs-server.service
+++ b/systemd/nfs-server.service
@@ -15,7 +15,7 @@ After=nfsdcld.service
 Before=rpc-statd-notify.service
 
 # GSS services dependencies and ordering
-Wants=auth-rpcgss-module.service
+Wants=auth-rpcgss-module.service rpc-svcgssd.service
 After=rpc-gssd.service gssproxy.service rpc-svcgssd.service
 
 [Service]
diff --git a/systemd/nfs.conf.man b/systemd/nfs.conf.man
index e74083e..bfd3380 100644
--- a/systemd/nfs.conf.man
+++ b/systemd/nfs.conf.man
@@ -98,6 +98,12 @@ value, which can be one or more from the list
 .BR parse ,
 .BR all .
 When a list is given, the members should be comma-separated.
+The values
+.BR 0
+and
+.BR 1
+are also accepted, with '0' making no changes to the debug level, and '1' equivalent to specifying 'all'.
+
 .TP
 .B general
 Recognized values:
@@ -166,6 +172,7 @@ for details.
 Recognized values:
 .BR threads ,
 .BR host ,
+.BR scope ,
 .BR port ,
 .BR grace-time ,
 .BR lease-time ,
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 40c17c3..48fd0cd 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -12,6 +12,10 @@ if CONFIG_NFSDCLD
 OPTDIRS += nfsdclddb
 endif
 
-SUBDIRS = locktest rpcdebug nlmtest mountstats nfs-iostat rpcctl nfsdclnts nfsrahead $(OPTDIRS)
+if CONFIG_NFSRAHEAD
+OPTDIRS += nfsrahead
+endif
+
+SUBDIRS = locktest rpcdebug nlmtest mountstats nfs-iostat rpcctl nfsdclnts $(OPTDIRS)
 
 MAINTAINERCLEANFILES = Makefile.in
diff --git a/tools/nfs-iostat/nfs-iostat.py b/tools/nfs-iostat/nfs-iostat.py
index 1df74ba..85294fb 100755
--- a/tools/nfs-iostat/nfs-iostat.py
+++ b/tools/nfs-iostat/nfs-iostat.py
@@ -43,7 +43,7 @@ NfsEventCounters = [
     'vfspermission',
     'vfsupdatepage',
     'vfsreadpage',
-    'vfsreadpages',
+    'vfsreadpages', # or vfsreadahead in statvers=1.2 or above
     'vfswritepage',
     'vfswritepages',
     'vfsreaddir',
@@ -86,14 +86,14 @@ class DeviceData:
             self.__nfs_data['export'] = words[1]
             self.__nfs_data['mountpoint'] = words[4]
             self.__nfs_data['fstype'] = words[7]
-            if words[7] == 'nfs':
-                self.__nfs_data['statvers'] = words[8]
+            if words[7] == 'nfs' or words[7] == 'nfs4':
+                self.__nfs_data['statvers'] = float(words[8].split('=',1)[1])
         elif 'nfs' in words or 'nfs4' in words:
             self.__nfs_data['export'] = words[0]
             self.__nfs_data['mountpoint'] = words[3]
             self.__nfs_data['fstype'] = words[6]
             if words[6] == 'nfs':
-                self.__nfs_data['statvers'] = words[7]
+                self.__nfs_data['statvers'] = float(words[7].split('=',1)[1])
         elif words[0] == 'age:':
             self.__nfs_data['age'] = int(words[1])
         elif words[0] == 'opts:':
@@ -294,8 +294,11 @@ class DeviceData:
         print()
         print('%d nfs_readpage() calls read %d pages' % \
             (vfsreadpage, vfsreadpage))
-        print('%d nfs_readpages() calls read %d pages' % \
-            (vfsreadpages, pages_read - vfsreadpage))
+        multipageread = "readpages"
+        if self.__nfs_data['statvers'] >= 1.2:
+            multipageread = "readahead"
+        print('%d nfs_%s() calls read %d pages' % \
+            (vfsreadpages, multipageread, pages_read - vfsreadpage))
         if vfsreadpages != 0:
             print('(%.1f pages per call)' % \
                 (float(pages_read - vfsreadpage) / vfsreadpages))
diff --git a/tools/nfsrahead/Makefile.am b/tools/nfsrahead/Makefile.am
index 845ea0d..7e08233 100644
--- a/tools/nfsrahead/Makefile.am
+++ b/tools/nfsrahead/Makefile.am
@@ -1,6 +1,6 @@
 libexec_PROGRAMS = nfsrahead
 nfsrahead_SOURCES = main.c
-nfsrahead_LDFLAGS= -lmount
+nfsrahead_LDFLAGS= $(LIBMOUNT_LIBS)
 nfsrahead_LDADD = ../../support/nfs/libnfsconf.la
 
 man5_MANS = nfsrahead.man
diff --git a/tools/nfsrahead/main.c b/tools/nfsrahead/main.c
index c83c6f7..8a11cf1 100644
--- a/tools/nfsrahead/main.c
+++ b/tools/nfsrahead/main.c
@@ -167,7 +167,7 @@ int main(int argc, char **argv)
 		if ((ret = get_device_info(argv[optind], &device)) == 0)
 			break;
 
-	if (ret != 0) {
+	if (ret != 0 || device.fstype == NULL) {
 		xlog(D_GENERAL, "unable to find device %s\n", argv[optind]);
 		goto out;
 	}
diff --git a/utils/blkmapd/device-discovery.c b/utils/blkmapd/device-discovery.c
index 2736ac8..a565fdb 100644
--- a/utils/blkmapd/device-discovery.c
+++ b/utils/blkmapd/device-discovery.c
@@ -187,10 +187,7 @@ static void bl_add_disk(char *filepath)
 	}
 
 	if (disk && diskpath) {
-		if (serial) {
-			free(serial->data);
-			free(serial);
-		}
+		bl_free_scsi_string(serial);
 		return;
 	}
 
@@ -228,10 +225,7 @@ static void bl_add_disk(char *filepath)
 			disk->size = size;
 			disk->valid_path = path;
 		}
-		if (serial) {
-			free(serial->data);
-			free(serial);
-		}
+		bl_free_scsi_string(serial);
 	}
 	return;
 
@@ -241,10 +235,7 @@ static void bl_add_disk(char *filepath)
 			free(path->full_path);
 		free(path);
 	}
-	if (serial) {
-		free(serial->data);
-		free(serial);
-	}
+	bl_free_scsi_string(serial);
 	return;
 }
 
@@ -462,7 +453,7 @@ static void sig_die(int signal)
 		unlink(PID_FILE);
 	}
 	BL_LOG_ERR("exit on signal(%d)\n", signal);
-	exit(1);
+	exit(0);
 }
 static void usage(void)
 {
@@ -507,28 +498,44 @@ int main(int argc, char **argv)
 	if (fg) {
 		openlog("blkmapd", LOG_PERROR, 0);
 	} else {
-		if (daemon(0, 0) != 0) {
-			fprintf(stderr, "Daemonize failed\n");
+		pid_t pid = fork();
+		if (pid < 0) {
+			BL_LOG_ERR("fork error\n");
 			exit(1);
+		} else if (pid != 0) {
+			pidfd = open(PID_FILE, O_WRONLY | O_CREAT, 0644);
+			if (pidfd < 0) {
+				BL_LOG_ERR("Create pid file %s failed\n", PID_FILE);
+				exit(1);
+			}
+
+			if (lockf(pidfd, F_TLOCK, 0) < 0) {
+				BL_LOG_ERR("Already running; Exiting!");
+				close(pidfd);
+				exit(1);
+			}
+			if (ftruncate(pidfd, 0) < 0)
+				BL_LOG_ERR("ftruncate on %s failed: m\n", PID_FILE);
+			sprintf(pidbuf, "%d\n", pid);
+			if (write(pidfd, pidbuf, strlen(pidbuf)) != (ssize_t)strlen(pidbuf))
+				BL_LOG_ERR("write on %s failed: m\n", PID_FILE);
+			exit(0);
 		}
 
-		openlog("blkmapd", LOG_PID, 0);
-		pidfd = open(PID_FILE, O_WRONLY | O_CREAT, 0644);
-		if (pidfd < 0) {
-			BL_LOG_ERR("Create pid file %s failed\n", PID_FILE);
-			exit(1);
+		(void)setsid();
+		if (chdir("/")) {
+			BL_LOG_ERR("chdir error\n");
 		}
+		int fd = open("/dev/null", O_RDWR, 0);
+		if (fd >= 0) {
+		    (void)dup2(fd, STDIN_FILENO);
+		    (void)dup2(fd, STDOUT_FILENO);
+		    (void)dup2(fd, STDERR_FILENO);
 
-		if (lockf(pidfd, F_TLOCK, 0) < 0) {
-			BL_LOG_ERR("Already running; Exiting!");
-			close(pidfd);
-			exit(1);
+		    (void)close(fd);
 		}
-		if (ftruncate(pidfd, 0) < 0)
-			BL_LOG_WARNING("ftruncate on %s failed: m\n", PID_FILE);
-		sprintf(pidbuf, "%d\n", getpid());
-		if (write(pidfd, pidbuf, strlen(pidbuf)) != (ssize_t)strlen(pidbuf))
-			BL_LOG_WARNING("write on %s failed: m\n", PID_FILE);
+
+		openlog("blkmapd", LOG_PID, 0);
 	}
 
 	signal(SIGINT, sig_die);
diff --git a/utils/blkmapd/device-discovery.h b/utils/blkmapd/device-discovery.h
index a86eed9..462aa94 100644
--- a/utils/blkmapd/device-discovery.h
+++ b/utils/blkmapd/device-discovery.h
@@ -151,6 +151,8 @@ uint64_t process_deviceinfo(const char *dev_addr_buf,
 
 extern ssize_t atomicio(ssize_t(*f) (int, void *, size_t),
 			int fd, void *_s, size_t n);
+extern struct bl_serial *bl_create_scsi_string(int len, const char *bytes);
+extern void bl_free_scsi_string(struct bl_serial *str);
 extern struct bl_serial *bldev_read_serial(int fd, const char *filename);
 extern enum bl_path_state_e bldev_read_ap_state(int fd);
 extern int bl_discover_devices(void);
diff --git a/utils/blkmapd/device-inq.c b/utils/blkmapd/device-inq.c
index c7952c3..9e5749e 100644
--- a/utils/blkmapd/device-inq.c
+++ b/utils/blkmapd/device-inq.c
@@ -53,7 +53,7 @@
 #define DEF_ALLOC_LEN	255
 #define MX_ALLOC_LEN	(0xc000 + 0x80)
 
-static struct bl_serial *bl_create_scsi_string(int len, const char *bytes)
+struct bl_serial *bl_create_scsi_string(int len, const char *bytes)
 {
 	struct bl_serial *s;
 
@@ -66,7 +66,7 @@ static struct bl_serial *bl_create_scsi_string(int len, const char *bytes)
 	return s;
 }
 
-static void bl_free_scsi_string(struct bl_serial *str)
+void bl_free_scsi_string(struct bl_serial *str)
 {
 	if (str)
 		free(str);
diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c
index 6ba615d..6d79a5b 100644
--- a/utils/exportfs/exportfs.c
+++ b/utils/exportfs/exportfs.c
@@ -69,14 +69,14 @@ static int _lockfd = -1;
  * need these additional lockfile() routines.
  */
 static void
-grab_lockfile()
+grab_lockfile(void)
 {
 	_lockfd = open(lockfile, O_CREAT|O_RDWR, 0666);
 	if (_lockfd != -1)
 		lockf(_lockfd, F_LOCK, 0);
 }
 static void
-release_lockfile()
+release_lockfile(void)
 {
 	if (_lockfd != -1) {
 		lockf(_lockfd, F_ULOCK, 0);
@@ -513,7 +513,7 @@ validate_export(nfs_export *exp)
 	 */
 	struct stat stb;
 	char *path = exportent_realpath(&exp->m_export);
-	struct statfs64 stf;
+	struct statfs stf;
 	int fs_has_fsid = 0;
 
 	if (stat(path, &stb) < 0) {
@@ -528,7 +528,7 @@ validate_export(nfs_export *exp)
 	if (!can_test())
 		return;
 
-	if (!statfs64(path, &stf) &&
+	if (!statfs(path, &stf) &&
 	    (stf.f_fsid.__val[0] || stf.f_fsid.__val[1]))
 		fs_has_fsid = 1;
 
diff --git a/utils/idmapd/idmapd.c b/utils/idmapd/idmapd.c
index e79c124..cd9a965 100644
--- a/utils/idmapd/idmapd.c
+++ b/utils/idmapd/idmapd.c
@@ -867,7 +867,7 @@ nfsdreopen_one(struct idmap_client *ic)
 }
 
 static void
-nfsdreopen()
+nfsdreopen(void)
 {
 	nfsdreopen_one(&nfsd_ic[IC_NAMEID]);
 	nfsdreopen_one(&nfsd_ic[IC_IDNAME]);
diff --git a/utils/mount/network.c b/utils/mount/network.c
index ed2f825..01ead49 100644
--- a/utils/mount/network.c
+++ b/utils/mount/network.c
@@ -179,7 +179,7 @@ static const unsigned long probe_mnt3_only[] = {
 
 static const unsigned int *nfs_default_proto(void);
 #ifdef MOUNT_CONFIG
-static const unsigned int *nfs_default_proto()
+static const unsigned int *nfs_default_proto(void)
 {
 	extern unsigned long config_default_proto;
 	/*
diff --git a/utils/mount/parse_dev.c b/utils/mount/parse_dev.c
index 0d3bcb9..2ade5d5 100644
--- a/utils/mount/parse_dev.c
+++ b/utils/mount/parse_dev.c
@@ -170,7 +170,8 @@ static int nfs_parse_square_bracket(const char *dev,
 	if (pathname) {
 		*pathname = strndup(cbrace, path_len);
 		if (*pathname == NULL) {
-			free(*hostname);
+			if (hostname)
+				free(*hostname);
 			return nfs_pdn_nomem_err();
 		}
 	}
diff --git a/utils/nfsd/nfsd.c b/utils/nfsd/nfsd.c
index 4016a76..249df00 100644
--- a/utils/nfsd/nfsd.c
+++ b/utils/nfsd/nfsd.c
@@ -23,6 +23,7 @@
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
+#include <sched.h>
 
 #include "conffile.h"
 #include "nfslib.h"
@@ -39,6 +40,7 @@ static void	usage(const char *);
 static struct option longopts[] =
 {
 	{ "host", 1, 0, 'H' },
+	{ "scope", 1, 0, 'S'},
 	{ "help", 0, 0, 'h' },
 	{ "no-nfs-version", 1, 0, 'N' },
 	{ "nfs-version", 1, 0, 'V' },
@@ -69,6 +71,7 @@ main(int argc, char **argv)
 	int	count = NFSD_NPROC, c, i, error = 0, portnum, fd, found_one;
 	char *p, *progname, *port, *rdma_port = NULL;
 	char **haddr = NULL;
+	char *scope = NULL;
 	int hcounter = 0;
 	struct conf_list *hosts;
 	int	socket_up = 0;
@@ -168,8 +171,9 @@ main(int argc, char **argv)
 			hcounter++;
 		}
 	}
+	scope = conf_get_str("nfsd", "scope");
 
-	while ((c = getopt_long(argc, argv, "dH:hN:V:p:P:stTuUrG:L:", longopts, NULL)) != EOF) {
+	while ((c = getopt_long(argc, argv, "dH:S:hN:V:p:P:stTuUrG:L:", longopts, NULL)) != EOF) {
 		switch(c) {
 		case 'd':
 			xlog_config(D_ALL, 1);
@@ -190,6 +194,9 @@ main(int argc, char **argv)
 			haddr[hcounter] = optarg;
 			hcounter++;
 			break;
+		case 'S':
+			scope = optarg;
+			break;
 		case 'P':	/* XXX for nfs-server compatibility */
 		case 'p':
 			/* only the last -p option has any effect */
@@ -367,6 +374,14 @@ main(int argc, char **argv)
 	if (lease  > 0)
 		nfssvc_set_time("lease", lease);
 
+	if (scope) {
+		if (unshare(CLONE_NEWUTS) < 0 ||
+		    sethostname(scope, strlen(scope)) < 0) {
+			xlog(L_ERROR, "Unable to set server scope: %m");
+			error = -1;
+			goto out;
+		}
+	}
 	i = 0;
 	do {
 		error = nfssvc_set_sockets(protobits, haddr[i], port);
diff --git a/utils/nfsd/nfsd.man b/utils/nfsd/nfsd.man
index 634b8a6..dc05f36 100644
--- a/utils/nfsd/nfsd.man
+++ b/utils/nfsd/nfsd.man
@@ -35,9 +35,17 @@ Note that
 .B lockd
 (which performs file locking services for NFS) may still accept
 request on all known network addresses.  This may change in future
-releases of the Linux Kernel. This option can be used multiple time 
+releases of the Linux Kernel. This option can be used multiple times
 to listen to more than one interface.
 .TP
+.B \S " or " \-\-scope scope
+NFSv4.1 and later require the server to report a "scope" which is used
+by the clients to detect if two connections are to the same server.
+By default Linux NFSD uses the host name as the scope.
+.sp
+It is particularly important for high-availablity configurations to ensure
+that all potential server nodes report the same server scope.
+.TP
 .B \-p " or " \-\-port  port
 specify a different port to listen on for NFS requests. By default,
 .B rpc.nfsd
@@ -134,6 +142,9 @@ will listen on.  Use of the
 .B --host
 option replaces all host names listed here.
 .TP
+.B scope
+Set the server scope.
+.TP
 .B grace-time
 The grace time, for both NFSv4 and NLM, in seconds.
 .TP
@@ -159,7 +170,9 @@ Enable or disable TCP support.
 .B vers3
 .TP
 .B vers4
-Enable or disable a major NFS version.  3 and 4 are normally enabled
+Enable or disable 
+.B all 
+NFSv4 versions.  All versions are normally enabled
 by default.
 .TP
 .B vers4.1