diff --git a/SOURCES/24-nfs-server.conf b/SOURCES/24-nfs-server.conf
new file mode 100644
index 0000000..5011e92
--- /dev/null
+++ b/SOURCES/24-nfs-server.conf
@@ -0,0 +1,7 @@
+[service/nfs-server]
+  mechs = krb5
+  socket = /run/gssproxy.sock
+  cred_store = keytab:/etc/krb5.keytab
+  trusted = yes
+  kernel_nfsd = yes
+  euid = 0
diff --git a/SOURCES/nfs-utils-1.2.1-exp-subtree-warn-off.patch b/SOURCES/nfs-utils-1.2.1-exp-subtree-warn-off.patch
index 14e376c..0ee49bd 100644
--- a/SOURCES/nfs-utils-1.2.1-exp-subtree-warn-off.patch
+++ b/SOURCES/nfs-utils-1.2.1-exp-subtree-warn-off.patch
@@ -1,7 +1,7 @@
-diff -up nfs-utils-1.2.1/support/nfs/exports.c.orig nfs-utils-1.2.1/support/nfs/exports.c
---- nfs-utils-1.2.1/support/nfs/exports.c.orig	2010-01-15 10:48:49.631894982 -0500
-+++ nfs-utils-1.2.1/support/nfs/exports.c	2010-01-15 11:05:02.009874055 -0500
-@@ -483,7 +483,7 @@ static void fix_pseudoflavor_flags(struc
+diff -up nfs-utils-1.3.0/support/nfs/exports.c.orig nfs-utils-1.3.0/support/nfs/exports.c
+--- nfs-utils-1.3.0/support/nfs/exports.c.orig	2017-04-27 14:09:49.090353525 -0400
++++ nfs-utils-1.3.0/support/nfs/exports.c	2017-04-27 14:10:09.083034672 -0400
+@@ -507,7 +507,7 @@ void fix_pseudoflavor_flags(struct expor
  static int
  parseopts(char *cp, struct exportent *ep, int warn, int *had_subtree_opt_ptr)
  {
diff --git a/SOURCES/nfs-utils-1.2.1-statdpath-man.patch b/SOURCES/nfs-utils-1.2.1-statdpath-man.patch
index 8c2e0e2..53e2f34 100644
--- a/SOURCES/nfs-utils-1.2.1-statdpath-man.patch
+++ b/SOURCES/nfs-utils-1.2.1-statdpath-man.patch
@@ -1,7 +1,7 @@
-diff -up nfs-utils-1.2.1/utils/statd/sm-notify.man.save nfs-utils-1.2.1/utils/statd/sm-notify.man
---- nfs-utils-1.2.1/utils/statd/sm-notify.man.save	2010-01-15 11:10:25.096874609 -0500
-+++ nfs-utils-1.2.1/utils/statd/sm-notify.man	2010-01-15 11:14:12.636873981 -0500
-@@ -186,7 +186,7 @@ where NSM state information resides.
+diff -up nfs-utils-1.3.0/utils/statd/sm-notify.man.orig nfs-utils-1.3.0/utils/statd/sm-notify.man
+--- nfs-utils-1.3.0/utils/statd/sm-notify.man.orig	2017-04-27 14:08:24.681720773 -0400
++++ nfs-utils-1.3.0/utils/statd/sm-notify.man	2017-04-27 14:09:05.347042274 -0400
+@@ -184,7 +184,7 @@ where NSM state information resides.
  If this option is not specified,
  .B sm-notify
  uses
@@ -10,7 +10,7 @@ diff -up nfs-utils-1.2.1/utils/statd/sm-notify.man.save nfs-utils-1.2.1/utils/st
  by default.
  .IP
  After starting,
-@@ -287,13 +287,13 @@ Currently, the
+@@ -330,13 +330,13 @@ Currently, the
  command supports sending notification only via datagram transport protocols.
  .SH FILES
  .TP 2.5i
@@ -27,10 +27,10 @@ diff -up nfs-utils-1.2.1/utils/statd/sm-notify.man.save nfs-utils-1.2.1/utils/st
  NSM state number for this host
  .TP 2.5i
  .I /proc/sys/fs/nfs/nsm_local_state
-diff -up nfs-utils-1.2.1/utils/statd/statd.man.save nfs-utils-1.2.1/utils/statd/statd.man
---- nfs-utils-1.2.1/utils/statd/statd.man.save	2010-01-15 11:10:25.098906325 -0500
-+++ nfs-utils-1.2.1/utils/statd/statd.man	2010-01-15 11:11:03.874769717 -0500
-@@ -232,7 +232,7 @@ where NSM state information resides.
+diff -up nfs-utils-1.3.0/utils/statd/statd.man.orig nfs-utils-1.3.0/utils/statd/statd.man
+--- nfs-utils-1.3.0/utils/statd/statd.man.orig	2017-04-27 14:08:24.662721095 -0400
++++ nfs-utils-1.3.0/utils/statd/statd.man	2017-04-27 14:09:05.347042274 -0400
+@@ -253,7 +253,7 @@ where NSM state information resides.
  If this option is not specified,
  .B rpc.statd
  uses
@@ -39,8 +39,8 @@ diff -up nfs-utils-1.2.1/utils/statd/statd.man.save nfs-utils-1.2.1/utils/statd/
  by default.
  .IP
  After starting,
-@@ -368,13 +368,13 @@ As long as at least one network transpor
- will operate.
+@@ -425,13 +425,13 @@ If set to a positive integer, has the sa
+ .IR \-\-no\-notify .
  .SH FILES
  .TP 2.5i
 -.I /var/lib/nfs/sm
diff --git a/SOURCES/nfs-utils-1.2.3-sm-notify-res_init.patch b/SOURCES/nfs-utils-1.2.3-sm-notify-res_init.patch
index 3ce55eb..7b1ea1d 100644
--- a/SOURCES/nfs-utils-1.2.3-sm-notify-res_init.patch
+++ b/SOURCES/nfs-utils-1.2.3-sm-notify-res_init.patch
@@ -1,6 +1,6 @@
-diff -up nfs-utils-1.2.3/utils/statd/sm-notify.c.orig nfs-utils-1.2.3/utils/statd/sm-notify.c
---- nfs-utils-1.2.3/utils/statd/sm-notify.c.orig	2010-09-28 08:24:16.000000000 -0400
-+++ nfs-utils-1.2.3/utils/statd/sm-notify.c	2010-10-15 16:44:43.487119601 -0400
+diff -up nfs-utils-1.3.0/utils/statd/sm-notify.c.orig nfs-utils-1.3.0/utils/statd/sm-notify.c
+--- nfs-utils-1.3.0/utils/statd/sm-notify.c.orig	2017-04-27 14:10:28.866713955 -0400
++++ nfs-utils-1.3.0/utils/statd/sm-notify.c	2017-04-27 14:10:50.454363993 -0400
 @@ -28,6 +28,9 @@
  #include <netdb.h>
  #include <errno.h>
@@ -9,9 +9,9 @@ diff -up nfs-utils-1.2.3/utils/statd/sm-notify.c.orig nfs-utils-1.2.3/utils/stat
 +#include <arpa/nameser.h>
 +#include <resolv.h>
  
+ #include "conffile.h"
  #include "sockaddr.h"
- #include "xlog.h"
-@@ -84,6 +87,7 @@ smn_lookup(const char *name)
+@@ -91,6 +94,7 @@ smn_lookup(const char *name)
  	};
  	int error;
  
diff --git a/SOURCES/nfs-utils-1.2.5-idmap-errmsg.patch b/SOURCES/nfs-utils-1.2.5-idmap-errmsg.patch
index f4657e3..99e16b1 100644
--- a/SOURCES/nfs-utils-1.2.5-idmap-errmsg.patch
+++ b/SOURCES/nfs-utils-1.2.5-idmap-errmsg.patch
@@ -1,7 +1,7 @@
 diff -up nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.c.orig nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.c
---- nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.c.orig	2016-04-28 14:17:28.704643000 -0400
-+++ nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.c	2016-04-28 14:19:20.004449000 -0400
-@@ -416,7 +416,7 @@ int main(int argc, char **argv)
+--- nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.c.orig	2017-04-27 14:11:05.788115492 -0400
++++ nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.c	2017-04-27 14:11:26.291788824 -0400
+@@ -417,7 +417,7 @@ int main(int argc, char **argv)
  
  	xlog_stderr(verbose);
  	if ((argc - optind) != 2) {
diff --git a/SOURCES/nfs-utils-1.3.0-daemon_init-warning.patch b/SOURCES/nfs-utils-1.3.0-daemon_init-warning.patch
new file mode 100644
index 0000000..ad10dbf
--- /dev/null
+++ b/SOURCES/nfs-utils-1.3.0-daemon_init-warning.patch
@@ -0,0 +1,24 @@
+commit 19e6ba690c7e9674dae006cfce89f638c8d8edab
+Author: Steve Dickson <steved@redhat.com>
+Date:   Wed Nov 4 16:25:28 2015 -0500
+
+    mydaemon.c: Removed a warning
+    
+    Commit 273b4647 introduced the following warning:
+        mydaemon.c:125:2: warning: implicit declaration of function 'closelog'
+        [-Wimplicit-function-declaration]
+    
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+
+diff --git a/support/nfs/mydaemon.c b/support/nfs/mydaemon.c
+index 701cfd9..343e80b 100644
+--- a/support/nfs/mydaemon.c
++++ b/support/nfs/mydaemon.c
+@@ -49,6 +49,7 @@
+ #include <stdbool.h>
+ #include <stdlib.h>
+ #include <string.h>
++#include <syslog.h>
+ #include <xlog.h>
+ 
+ #include "nfslib.h"
diff --git a/SOURCES/nfs-utils-1.3.0-exportfs-path-comp.patch b/SOURCES/nfs-utils-1.3.0-exportfs-path-comp.patch
new file mode 100644
index 0000000..9216eb4
--- /dev/null
+++ b/SOURCES/nfs-utils-1.3.0-exportfs-path-comp.patch
@@ -0,0 +1,12 @@
+diff -up nfs-utils-1.3.0/utils/exportfs/exportfs.c.orig nfs-utils-1.3.0/utils/exportfs/exportfs.c
+--- nfs-utils-1.3.0/utils/exportfs/exportfs.c.orig	2017-06-15 11:28:59.541764508 -0400
++++ nfs-utils-1.3.0/utils/exportfs/exportfs.c	2017-06-15 11:30:04.699701243 -0400
+@@ -421,6 +421,8 @@ unexportfs_parsed(char *hname, char *pat
+ 		nlen--;
+ 
+ 	for (exp = exportlist[htype].p_head; exp; exp = exp->m_next) {
++		if (strlen(exp->m_export.e_path) != nlen)
++			continue;
+ 		if (path && strncmp(path, exp->m_export.e_path, nlen))
+ 			continue;
+ 		if (htype != exp->m_client->m_type)
diff --git a/SOURCES/nfs-utils-1.3.0-exportfs-redundant.patch b/SOURCES/nfs-utils-1.3.0-exportfs-redundant.patch
new file mode 100644
index 0000000..78ef5c3
--- /dev/null
+++ b/SOURCES/nfs-utils-1.3.0-exportfs-redundant.patch
@@ -0,0 +1,41 @@
+diff -up nfs-utils-1.3.0/support/nfs/exports.c.orig nfs-utils-1.3.0/support/nfs/exports.c
+--- nfs-utils-1.3.0/support/nfs/exports.c.orig	2017-02-27 18:24:26.485237519 -0500
++++ nfs-utils-1.3.0/support/nfs/exports.c	2017-02-27 18:25:49.296652027 -0500
+@@ -197,7 +197,6 @@ static const struct secinfo_flag_display
+ 	const char *set;
+ 	const char *unset;
+ } secinfo_flag_displaymap[] = {
+-	{ NFSEXP_READONLY, "ro", "rw" },
+ 	{ NFSEXP_INSECURE_PORT, "insecure", "secure" },
+ 	{ NFSEXP_ROOTSQUASH, "root_squash", "no_root_squash" },
+ 	{ NFSEXP_ALLSQUASH, "all_squash", "no_all_squash" },
+diff -up nfs-utils-1.3.0/utils/exportfs/exportfs.c.orig nfs-utils-1.3.0/utils/exportfs/exportfs.c
+--- nfs-utils-1.3.0/utils/exportfs/exportfs.c.orig	2017-02-27 18:24:26.429237915 -0500
++++ nfs-utils-1.3.0/utils/exportfs/exportfs.c	2017-02-27 18:25:49.297652020 -0500
+@@ -814,20 +814,18 @@ dump(int verbose, int export_format)
+ 				c = dumpopt(c, "rw");
+ 			if (ep->e_flags & NFSEXP_ASYNC)
+ 				c = dumpopt(c, "async");
++			else
++				c = dumpopt(c, "sync");
+ 			if (ep->e_flags & NFSEXP_GATHERED_WRITES)
+ 				c = dumpopt(c, "wdelay");
++			else
++				c = dumpopt(c, "no_wdelay");
+ 			if (ep->e_flags & NFSEXP_NOHIDE)
+ 				c = dumpopt(c, "nohide");
++			else
++				c = dumpopt(c, "hide");
+ 			if (ep->e_flags & NFSEXP_CROSSMOUNT)
+ 				c = dumpopt(c, "crossmnt");
+-			if (ep->e_flags & NFSEXP_INSECURE_PORT)
+-				c = dumpopt(c, "insecure");
+-			if (ep->e_flags & NFSEXP_ROOTSQUASH)
+-				c = dumpopt(c, "root_squash");
+-			else
+-				c = dumpopt(c, "no_root_squash");
+-			if (ep->e_flags & NFSEXP_ALLSQUASH)
+-				c = dumpopt(c, "all_squash");
+ 			if (ep->e_flags & NFSEXP_NOSUBTREECHECK)
+ 				c = dumpopt(c, "no_subtree_check");
+ 			if (ep->e_flags & NFSEXP_NOAUTHNLM)
diff --git a/SOURCES/nfs-utils-1.3.0-exportfs-securitylabel.patch b/SOURCES/nfs-utils-1.3.0-exportfs-securitylabel.patch
new file mode 100644
index 0000000..33a5ef7
--- /dev/null
+++ b/SOURCES/nfs-utils-1.3.0-exportfs-securitylabel.patch
@@ -0,0 +1,64 @@
+diff -up nfs-utils-1.3.0/support/include/nfs/export.h.orig nfs-utils-1.3.0/support/include/nfs/export.h
+--- nfs-utils-1.3.0/support/include/nfs/export.h.orig	2017-03-27 10:07:41.440397336 -0400
++++ nfs-utils-1.3.0/support/include/nfs/export.h	2017-03-27 10:08:57.195772235 -0400
+@@ -18,7 +18,8 @@
+ #define NFSEXP_ASYNC		0x0010
+ #define NFSEXP_GATHERED_WRITES	0x0020
+ #define NFSEXP_NOREADDIRPLUS	0x0040
+-/* 80, 100 unused */
++#define NFSEXP_SECURITY_LABEL	0x0080
++/* 0x100 unused */
+ #define NFSEXP_NOHIDE		0x0200
+ #define NFSEXP_NOSUBTREECHECK	0x0400
+ #define NFSEXP_NOAUTHNLM	0x0800
+diff -up nfs-utils-1.3.0/support/nfs/exports.c.orig nfs-utils-1.3.0/support/nfs/exports.c
+--- nfs-utils-1.3.0/support/nfs/exports.c.orig	2017-03-27 10:07:41.549399315 -0400
++++ nfs-utils-1.3.0/support/nfs/exports.c	2017-03-27 10:08:58.441794848 -0400
+@@ -274,6 +274,8 @@ putexportent(struct exportent *ep)
+ 		"no_" : "");
+ 	if (ep->e_flags & NFSEXP_NOREADDIRPLUS)
+ 		fprintf(fp, "nordirplus,");
++	if (ep->e_flags & NFSEXP_SECURITY_LABEL)
++		fprintf(fp, "security_label,");
+ 	fprintf(fp, "%spnfs,", (ep->e_flags & NFSEXP_PNFS)? "" : "no_");
+ 	if (ep->e_flags & NFSEXP_FSID) {
+ 		fprintf(fp, "fsid=%d,", ep->e_fsid);
+@@ -543,6 +545,8 @@ parseopts(char *cp, struct exportent *ep
+ 			setflags(NFSEXP_ASYNC, active, ep);
+ 		else if (!strcmp(opt, "nordirplus"))
+ 			setflags(NFSEXP_NOREADDIRPLUS, active, ep);
++		else if (!strcmp(opt, "security_label"))
++			setflags(NFSEXP_SECURITY_LABEL, active, ep);
+ 		else if (!strcmp(opt, "nohide"))
+ 			setflags(NFSEXP_NOHIDE, active, ep);
+ 		else if (!strcmp(opt, "hide"))
+diff -up nfs-utils-1.3.0/utils/exportfs/exportfs.c.orig nfs-utils-1.3.0/utils/exportfs/exportfs.c
+--- nfs-utils-1.3.0/utils/exportfs/exportfs.c.orig	2017-03-27 10:08:58.441794848 -0400
++++ nfs-utils-1.3.0/utils/exportfs/exportfs.c	2017-03-27 10:11:00.939046616 -0400
+@@ -835,6 +835,8 @@ dump(int verbose, int export_format)
+ 				c = dumpopt(c, "no_subtree_check");
+ 			if (ep->e_flags & NFSEXP_NOAUTHNLM)
+ 				c = dumpopt(c, "insecure_locks");
++			if (ep->e_flags & NFSEXP_SECURITY_LABEL)
++				c = dumpopt(c, "security_label");
+ 			if (ep->e_flags & NFSEXP_NOACL)
+ 				c = dumpopt(c, "no_acl");
+ 			if (ep->e_flags & NFSEXP_PNFS)
+diff -up nfs-utils-1.3.0/utils/exportfs/exports.man.orig nfs-utils-1.3.0/utils/exportfs/exports.man
+--- nfs-utils-1.3.0/utils/exportfs/exports.man.orig	2017-03-27 10:07:41.515398698 -0400
++++ nfs-utils-1.3.0/utils/exportfs/exports.man	2017-03-27 10:08:58.441794848 -0400
+@@ -417,6 +417,14 @@ devices. The default can be explicitly r
+ .I no_pnfs
+ option.
+ 
++.TP
++.IR security_label
++With this option set, clients using NFSv4.2 or higher will be able to
++set and retrieve security labels (such as those used by SELinux).  This
++will only work if all clients use a consistent security policy.  Note
++that early kernels did not support this export option, and instead
++enabled security labels by default.
++
+ .SS User ID Mapping
+ .PP
+ .B nfsd
diff --git a/SOURCES/nfs-utils-1.3.0-gssd-default-tcp.patch b/SOURCES/nfs-utils-1.3.0-gssd-default-tcp.patch
new file mode 100644
index 0000000..cdea6ec
--- /dev/null
+++ b/SOURCES/nfs-utils-1.3.0-gssd-default-tcp.patch
@@ -0,0 +1,35 @@
+commit 1ee2184248251ff44ae1ba557f12151cb8cf93ff
+Author: Chuck Lever <chuck.lever@oracle.com>
+Date:   Mon Nov 2 08:47:41 2015 -0500
+
+    gssd: Make TCP the default protocol for GSSD connections.
+    
+    No failure case if gssd doesn't recognize the kernel's requested
+    protocol. Caught with "protocol=rdma" upcall.
+    
+    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+
+diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c
+index 11168b2..cee8991 100644
+--- a/utils/gssd/gssd_proc.c
++++ b/utils/gssd/gssd_proc.c
+@@ -348,16 +348,9 @@ create_auth_rpc_client(struct clnt_info *clp,
+ 	printerr(2, "creating %s client for server %s\n", clp->protocol,
+ 			clp->servername);
+ 
+-	if ((strcmp(clp->protocol, "tcp")) == 0) {
+-		protocol = IPPROTO_TCP;
+-	} else if ((strcmp(clp->protocol, "udp")) == 0) {
++	protocol = IPPROTO_TCP;
++	if ((strcmp(clp->protocol, "udp")) == 0)
+ 		protocol = IPPROTO_UDP;
+-	} else {
+-		printerr(0, "WARNING: unrecognized protocol, '%s', requested "
+-			 "for connection to server %s for user with uid %d\n",
+-			 clp->protocol, clp->servername, uid);
+-		goto out_fail;
+-	}
+ 
+ 	switch (addr->sa_family) {
+ 	case AF_INET:
diff --git a/SOURCES/nfs-utils-1.3.0-gssd-rdma-to-tcp.patch b/SOURCES/nfs-utils-1.3.0-gssd-rdma-to-tcp.patch
new file mode 100644
index 0000000..24a6986
--- /dev/null
+++ b/SOURCES/nfs-utils-1.3.0-gssd-rdma-to-tcp.patch
@@ -0,0 +1,26 @@
+diff -up nfs-utils-1.3.0/utils/gssd/gssd.c.orig nfs-utils-1.3.0/utils/gssd/gssd.c
+--- nfs-utils-1.3.0/utils/gssd/gssd.c.orig	2017-02-28 14:24:20.296676493 -0500
++++ nfs-utils-1.3.0/utils/gssd/gssd.c	2017-02-28 14:45:36.140482510 -0500
+@@ -305,6 +305,22 @@ gssd_read_service_info(int dirfd, struct
+ 		goto fail;
+ 	}
+ 
++	/*
++	 * The user space RPC library has no support for
++	 * RPC-over-RDMA at this time, so change 'rdma'
++	 * to 'tcp', and '20049' to '2049'.
++	 */
++	if (strcmp(protoname, "rdma") == 0) {
++		free(protoname);
++		protoname = strdup("tcp");
++		if (!protoname)
++			goto fail;
++		free(port);
++		port = strdup("2049");
++		if (!port)
++			goto fail;
++	}
++
+ 	if (!gssd_addrstr_to_sockaddr((struct sockaddr *)&clp->addr,
+ 				 address, port ? port : ""))
+ 		goto fail;
diff --git a/SOURCES/nfs-utils-1.3.0-gssd-thread-safe.patch b/SOURCES/nfs-utils-1.3.0-gssd-thread-safe.patch
new file mode 100644
index 0000000..6f5fd86
--- /dev/null
+++ b/SOURCES/nfs-utils-1.3.0-gssd-thread-safe.patch
@@ -0,0 +1,69 @@
+diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c
+index 646d7e3..14cf7b8 100644
+--- a/utils/gssd/gssd_proc.c
++++ b/utils/gssd/gssd_proc.c
+@@ -728,10 +728,18 @@ handle_gssd_upcall(struct clnt_upcall_info *info)
+ 	char			*target = NULL;
+ 	char			*service = NULL;
+ 	char			*enctypes = NULL;
++	char			*upcall_str;
++	char			*pbuf = info->lbuf;
+ 
+ 	printerr(2, "\n%s: '%s' (%s)\n", __func__, info->lbuf, clp->relpath);
+ 
+-	for (p = strtok(info->lbuf, " "); p; p = strtok(NULL, " ")) {
++	upcall_str = strdup(info->lbuf);
++	if (upcall_str == NULL) {
++		printerr(0, "ERROR: malloc failure\n");
++		goto out_nomem;
++	}
++
++	while ((p = strsep(&pbuf, " "))) {
+ 		if (!strncmp(p, "mech=", strlen("mech=")))
+ 			mech = p + strlen("mech=");
+ 		else if (!strncmp(p, "uid=", strlen("uid=")))
+@@ -747,7 +755,7 @@ handle_gssd_upcall(struct clnt_upcall_info *info)
+ 	if (!mech || strlen(mech) < 1) {
+ 		printerr(0, "WARNING: handle_gssd_upcall: "
+ 			    "failed to find gss mechanism name "
+-			    "in upcall string '%s'\n", info->lbuf);
++			    "in upcall string '%s'\n", upcall_str);
+ 		goto out;
+ 	}
+ 
+@@ -760,7 +768,7 @@ handle_gssd_upcall(struct clnt_upcall_info *info)
+ 	if (!uidstr) {
+ 		printerr(0, "WARNING: handle_gssd_upcall: "
+ 			    "failed to find uid "
+-			    "in upcall string '%s'\n", info->lbuf);
++			    "in upcall string '%s'\n", upcall_str);
+ 		goto out;
+ 	}
+ 
+@@ -773,7 +781,7 @@ handle_gssd_upcall(struct clnt_upcall_info *info)
+ 	if (target && strlen(target) < 1) {
+ 		printerr(0, "WARNING: handle_gssd_upcall: "
+ 			 "failed to parse target name "
+-			 "in upcall string '%s'\n", info->lbuf);
++			 "in upcall string '%s'\n", upcall_str);
+ 		goto out;
+ 	}
+ 
+@@ -788,7 +796,7 @@ handle_gssd_upcall(struct clnt_upcall_info *info)
+ 	if (service && strlen(service) < 1) {
+ 		printerr(0, "WARNING: handle_gssd_upcall: "
+ 			 "failed to parse service type "
+-			 "in upcall string '%s'\n", info->lbuf);
++			 "in upcall string '%s'\n", upcall_str);
+ 		goto out;
+ 	}
+ 
+@@ -801,6 +809,8 @@ handle_gssd_upcall(struct clnt_upcall_info *info)
+ 		do_error_downcall(clp->gssd_fd, uid, -EACCES);
+ 	}
+ out:
++	free(upcall_str);
++out_nomem:
+ 	free(info);
+ 	return;
+ }
diff --git a/SOURCES/nfs-utils-1.3.0-mount-default-v42.patch b/SOURCES/nfs-utils-1.3.0-mount-default-v42.patch
new file mode 100644
index 0000000..c715ccc
--- /dev/null
+++ b/SOURCES/nfs-utils-1.3.0-mount-default-v42.patch
@@ -0,0 +1,590 @@
+diff --git a/configure.ac b/configure.ac
+index 56f7f3e..802fd58 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -172,10 +172,12 @@ AC_ARG_ENABLE(ipv6,
+ if test "$enable_mount" = yes; then
+ 	AC_ARG_ENABLE(mountconfig,
+ 	[AC_HELP_STRING([--enable-mountconfig],
+-                        [enable mount to use a configuration file])],
++        [enable mount to use a configuration file @<:@default=yes@:>@])],
+ 	mountconfig=$enableval,
+-	mountconfig=no)
+-	if test "$enable_mountconfig" = yes; then
++	mountconfig=yes)
++	if test "$enable_mountconfig" = no; then
++		enable_mountconfig=
++	else
+ 		AC_DEFINE(MOUNT_CONFIG, 1, 
+ 			[Define this if you want mount to read a configuration file])
+ 		AC_ARG_WITH(mountfile,
+@@ -187,8 +189,6 @@ if test "$enable_mount" = yes; then
+ 		AC_SUBST(mountfile)
+ 		AC_DEFINE_UNQUOTED(MOUNTOPTS_CONFFILE, "$mountfile", 
+ 			[This defines the location of the NFS mount configuration file])
+-	else
+-		enable_mountconfig=
+ 	fi
+ 	AC_SUBST(enable_mountconfig)
+ 	AM_CONDITIONAL(MOUNT_CONFIG, [test "$enable_mountconfig" = "yes"])
+diff --git a/utils/mount/configfile.c b/utils/mount/configfile.c
+index 39d3741..0a4cc04 100644
+--- a/utils/mount/configfile.c
++++ b/utils/mount/configfile.c
+@@ -228,37 +228,8 @@ void free_all(void)
+ 		free(entry);
+ 	}
+ }
+-static char *versions[] = {"v2", "v3", "v4", "vers", "nfsvers", NULL};
+-static int 
+-check_vers(char *mopt, char *field)
+-{
+-	int i, found=0;
+-
+-	/*
+-	 * First check to see if the config setting is one 
+-	 * of the many version settings
+-	 */
+-	for (i=0; versions[i]; i++) { 
+-		if (strcasestr(field, versions[i]) != NULL) {
+-			found++;
+-			break;
+-		}
+-	}
+-	if (!found)
+-		return 0;
+-	/*
+-	 * It appears the version is being set, now see
+-	 * if the version appears on the command 
+-	 */
+-	for (i=0; versions[i]; i++)  {
+-		if (strcasestr(mopt, versions[i]) != NULL)
+-			return 1;
+-	}
+-
+-	return 0;
+-}
+ 
+-unsigned long config_default_vers;
++struct nfs_version config_default_vers;
+ unsigned long config_default_proto;
+ extern sa_family_t config_default_family;
+ 
+@@ -331,11 +302,6 @@ conf_parse_mntopts(char *section, char *arg, char *opts)
+ 		snprintf(buf, BUFSIZ, "%s=", node->field);
+ 		if (opts && strcasestr(opts, buf) != NULL)
+ 			continue;
+-		/* 
+-		 * Protocol verions can be set in a number of ways
+-		 */
+-		if (opts && check_vers(opts, node->field))
+-			continue;
+ 
+ 		if (lookup_entry(node->field) != NULL)
+ 			continue;
+diff --git a/utils/mount/network.c b/utils/mount/network.c
+index 515249b..088caa1 100644
+--- a/utils/mount/network.c
++++ b/utils/mount/network.c
+@@ -92,9 +92,6 @@ static const char *nfs_version_opttbl[] = {
+ 	"v4",
+ 	"vers",
+ 	"nfsvers",
+-	"v4.0",
+-	"v4.1",
+-	"v4.2",
+ 	NULL,
+ };
+ 
+@@ -1249,71 +1246,69 @@ nfs_nfs_program(struct mount_options *options, unsigned long *program)
+  * or FALSE if the option was specified with an invalid value.
+  */
+ int
+-nfs_nfs_version(struct mount_options *options, unsigned long *version)
++nfs_nfs_version(struct mount_options *options, struct nfs_version *version)
+ {
+-	long tmp;
++	char *version_key, *version_val, *cptr;
++	int i, found = 0;
+ 
+-	switch (po_rightmost(options, nfs_version_opttbl)) {
+-	case 0:	/* v2 */
+-		*version = 2;
+-		return 1;
+-	case 1: /* v3 */
+-		*version = 3;
+-		return 1;
+-	case 2: /* v4 */
+-		*version = 4;
+-		return 1;
+-	case 3:	/* vers */
+-		switch (po_get_numeric(options, "vers", &tmp)) {
+-		case PO_FOUND:
+-			if (tmp >= 2 && tmp <= 4) {
+-				*version = tmp;
+-				return 1;
+-			}
+-			nfs_error(_("%s: parsing error on 'vers=' option\n"),
+-					progname);
+-			return 0;
+-		case PO_NOT_FOUND:
+-			nfs_error(_("%s: parsing error on 'vers=' option\n"),
+-					progname);
+-			return 0;
+-		case PO_BAD_VALUE:
+-			nfs_error(_("%s: invalid value for 'vers=' option"),
+-					progname);
+-			return 0;
+-		}
+-	case 4: /* nfsvers */
+-		switch (po_get_numeric(options, "nfsvers", &tmp)) {
+-		case PO_FOUND:
+-			if (tmp >= 2 && tmp <= 4) {
+-				*version = tmp;
+-				return 1;
+-			}
+-			nfs_error(_("%s: parsing error on 'nfsvers=' option\n"),
+-					progname);
+-			return 0;
+-		case PO_NOT_FOUND:
+-			nfs_error(_("%s: parsing error on 'nfsvers=' option\n"),
+-					progname);
+-			return 0;
+-		case PO_BAD_VALUE:
+-			nfs_error(_("%s: invalid value for 'nfsvers=' option"),
+-					progname);
+-			return 0;
++	version->v_mode = V_DEFAULT;
++
++	for (i = 0; nfs_version_opttbl[i]; i++) {
++		if (po_contains_prefix(options, nfs_version_opttbl[i],
++								&version_key) == PO_FOUND) {
++			found++;
++			break;
+ 		}
+-	case 5: /* v4.0 */
+-	case 6: /* v4.1 */
+-	case 7: /* v4.2 */
+-		*version = 4;
++	}
++
++	if (!found)
+ 		return 1;
++
++	if (i <= 2 ) {
++		/* v2, v3, v4 */
++		version_val = version_key + 1;
++		version->v_mode = V_SPECIFIC;
++	} else if (i > 2 ) {
++		/* vers=, nfsvers= */
++		version_val = po_get(options, version_key);
+ 	}
+ 
+-	/*
+-	 * NFS version wasn't specified.  The pmap version value
+-	 * will be filled in later by an rpcbind query in this case.
+-	 */
+-	*version = 0;
++	if (!version_val)
++		goto ret_error;
++
++	if (!(version->major = strtol(version_val, &cptr, 10)))
++		goto ret_error;
++
++	if (version->major < 4)
++		version->v_mode = V_SPECIFIC;
++
++	if (*cptr == '.') {
++		version_val = ++cptr;
++		if (!(version->minor = strtol(version_val, &cptr, 10)) && cptr == version_val)
++			goto ret_error;
++		version->v_mode = V_SPECIFIC;
++	} else if (version->major > 3 && *cptr == '\0')
++		version->v_mode = V_GENERAL;
++
++	if (*cptr != '\0')
++		goto ret_error;
++
+ 	return 1;
++
++ret_error:
++	if (i <= 2 ) {
++		nfs_error(_("%s: parsing error on 'v' option"),
++			progname);
++	} else if (i == 3 ) {
++		nfs_error(_("%s: parsing error on 'vers=' option"),
++			progname);
++	} else if (i == 4) {
++		nfs_error(_("%s: parsing error on 'nfsvers=' option"),
++			progname);
++	}
++	version->v_mode = V_PARSE_ERR;
++	errno = EINVAL;
++	return 0;
+ }
+ 
+ /*
+@@ -1632,10 +1627,13 @@ out_err:
+ int nfs_options2pmap(struct mount_options *options,
+ 		     struct pmap *nfs_pmap, struct pmap *mnt_pmap)
+ {
++	struct nfs_version version;
++
+ 	if (!nfs_nfs_program(options, &nfs_pmap->pm_prog))
+ 		return 0;
+-	if (!nfs_nfs_version(options, &nfs_pmap->pm_vers))
++	if (!nfs_nfs_version(options, &version))
+ 		return 0;
++	nfs_pmap->pm_vers = version.major;
+ 	if (!nfs_nfs_protocol(options, &nfs_pmap->pm_prot))
+ 		return 0;
+ 	if (!nfs_nfs_port(options, &nfs_pmap->pm_port))
+diff --git a/utils/mount/network.h b/utils/mount/network.h
+index d7636d7..9cc5dec 100644
+--- a/utils/mount/network.h
++++ b/utils/mount/network.h
+@@ -57,9 +57,22 @@ int clnt_ping(struct sockaddr_in *, const unsigned long,
+ 
+ struct mount_options;
+ 
++enum {
++	V_DEFAULT = 0,
++	V_GENERAL,
++	V_SPECIFIC,
++	V_PARSE_ERR,
++};
++
++struct nfs_version {
++	unsigned long major;
++	unsigned long minor;
++	int v_mode;
++};
++
+ int nfs_nfs_proto_family(struct mount_options *options, sa_family_t *family);
+ int nfs_mount_proto_family(struct mount_options *options, sa_family_t *family);
+-int nfs_nfs_version(struct mount_options *options, unsigned long *version);
++int nfs_nfs_version(struct mount_options *options, struct nfs_version *version);
+ int  nfs_nfs_protocol(struct mount_options *options, unsigned long *protocol);
+ 
+ int nfs_options2pmap(struct mount_options *,
+diff --git a/utils/mount/nfsumount.c b/utils/mount/nfsumount.c
+index 3538d88..de284f2 100644
+--- a/utils/mount/nfsumount.c
++++ b/utils/mount/nfsumount.c
+@@ -179,10 +179,10 @@ static int nfs_umount_is_vers4(const struct mntentchn *mc)
+ 
+ 		options = po_split(pmc->m.mnt_opts);
+ 		if (options != NULL) {
+-			unsigned long version;
++			struct nfs_version version;
+ 			int rc = nfs_nfs_version(options, &version);
+ 			po_destroy(options);
+-			if (rc && version == 4)
++			if (rc && version.major == 4)
+ 				goto out_nfs4;
+ 		}
+ 
+diff --git a/utils/mount/parse_opt.c b/utils/mount/parse_opt.c
+index 75a0daa..7ba61c4 100644
+--- a/utils/mount/parse_opt.c
++++ b/utils/mount/parse_opt.c
+@@ -391,7 +391,7 @@ po_return_t po_append(struct mount_options *options, char *str)
+ }
+ 
+ /**
+- * po_contains - check for presense of an option in a group
++ * po_contains - check for presence of an option in a group
+  * @options: pointer to mount options
+  * @keyword: pointer to a C string containing option keyword for which to search
+  *
+@@ -410,6 +410,30 @@ po_found_t po_contains(struct mount_options *options, char *keyword)
+ }
+ 
+ /**
++ * po_contains_prefix - check for presence of an option matching a prefix
++ * @options: pointer to mount options
++ * @prefix: pointer to prefix to match against a keyword
++ * @keyword: pointer to a C string containing the option keyword if found
++ *
++ * On success, *keyword contains the pointer of the matching option's keyword.
++ */
++po_found_t po_contains_prefix(struct mount_options *options,
++								const char *prefix, char **keyword)
++{
++	struct mount_option *option;
++
++	if (options && prefix) {
++		for (option = options->head; option; option = option->next)
++			if (strncmp(option->keyword, prefix, strlen(prefix)) == 0) {
++				*keyword = option->keyword;
++				return PO_FOUND;
++			}
++	}
++
++	return PO_NOT_FOUND;
++}
++
++/**
+  * po_get - return the value of the rightmost instance of an option
+  * @options: pointer to mount options
+  * @keyword: pointer to a C string containing option keyword for which to search
+diff --git a/utils/mount/parse_opt.h b/utils/mount/parse_opt.h
+index 5037207..0745e0f 100644
+--- a/utils/mount/parse_opt.h
++++ b/utils/mount/parse_opt.h
+@@ -45,6 +45,8 @@ po_return_t		po_join(struct mount_options *, char **);
+ 
+ po_return_t		po_append(struct mount_options *, char *);
+ po_found_t		po_contains(struct mount_options *, char *);
++po_found_t		po_contains_prefix(struct mount_options *options,
++						const char *prefix, char **keyword);
+ char *			po_get(struct mount_options *, char *);
+ po_found_t		po_get_numeric(struct mount_options *,
+ 					char *, long *);
+diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
+index 5d80ed7..207a476 100644
+--- a/utils/mount/stropts.c
++++ b/utils/mount/stropts.c
+@@ -88,30 +88,50 @@ struct nfsmount_info {
+ 	struct mount_options	*options;	/* parsed mount options */
+ 	char			**extra_opts;	/* string for /etc/mtab */
+ 
+-	unsigned long		version;	/* NFS version */
++	struct nfs_version	version;	/* NFS version */
+ 	int			flags,		/* MS_ flags */
+ 				fake,		/* actually do the mount? */
+ 				child;		/* forked bg child? */
+ };
+ 
+-#ifdef MOUNT_CONFIG
+-static void nfs_default_version(struct nfsmount_info *mi);
+ 
+ static void nfs_default_version(struct nfsmount_info *mi)
+ {
+-	extern unsigned long config_default_vers;
++#ifdef MOUNT_CONFIG
++	extern struct nfs_version config_default_vers;
+ 	/*
+ 	 * Use the default value set in the config file when
+ 	 * the version has not been explicitly set.
+ 	 */
+-	if (mi->version == 0 && config_default_vers) {
+-		if (config_default_vers < 4)
+-			mi->version = config_default_vers;
++	if (config_default_vers.v_mode == V_PARSE_ERR) {
++		mi->version.v_mode = V_PARSE_ERR;
++		return;
+ 	}
+-}
+-#else
+-inline void nfs_default_version(__attribute__ ((unused)) struct nfsmount_info *mi) {}
++
++	if (mi->version.v_mode == V_GENERAL &&
++		config_default_vers.v_mode == V_DEFAULT) {
++		mi->version.v_mode = V_SPECIFIC;
++		return;
++	}
++
++	if (mi->version.v_mode == V_DEFAULT &&
++		config_default_vers.v_mode != V_DEFAULT) {
++		mi->version.major = config_default_vers.major;
++		mi->version.minor = config_default_vers.minor;
++		return;
++	}
++
++	if (mi->version.v_mode == V_GENERAL &&
++		config_default_vers.v_mode != V_DEFAULT) {
++		if (mi->version.major == config_default_vers.major)
++			mi->version.minor = config_default_vers.minor;
++		return;
++	}
++
+ #endif /* MOUNT_CONFIG */
++	mi->version.major = 4;
++	mi->version.minor = 2;
++}
+ 
+ /*
+  * Obtain a retry timeout value based on the value of the "retry=" option.
+@@ -300,7 +320,7 @@ static int nfs_set_version(struct nfsmount_info *mi)
+ 		return 0;
+ 
+ 	if (strncmp(mi->type, "nfs4", 4) == 0)
+-		mi->version = 4;
++		mi->version.major = 4;
+ 
+ 	/*
+ 	 * Before 2.6.32, the kernel NFS client didn't
+@@ -308,28 +328,44 @@ static int nfs_set_version(struct nfsmount_info *mi)
+ 	 * 4 cannot be included when autonegotiating
+ 	 * while running on those kernels.
+ 	 */
+-	if (mi->version == 0 &&
+-	    linux_version_code() <= MAKE_VERSION(2, 6, 31))
+-		mi->version = 3;
++	if (mi->version.v_mode == V_DEFAULT &&
++	    linux_version_code() <= MAKE_VERSION(2, 6, 31)) {
++		mi->version.major = 3;
++		mi->version.v_mode = V_SPECIFIC;
++	}
+ 
+ 	/*
+ 	 * If we still don't know, check for version-specific
+ 	 * mount options.
+ 	 */
+-	if (mi->version == 0) {
++	if (mi->version.v_mode == V_DEFAULT) {
+ 		if (po_contains(mi->options, "mounthost") ||
+ 		    po_contains(mi->options, "mountaddr") ||
+ 		    po_contains(mi->options, "mountvers") ||
+-		    po_contains(mi->options, "mountproto"))
+-			mi->version = 3;
++		    po_contains(mi->options, "mountproto")) {
++			mi->version.major = 3;
++			mi->version.v_mode = V_SPECIFIC;
++		}
+ 	}
+ 
+ 	/*
+ 	 * If enabled, see if the default version was
+ 	 * set in the config file
+ 	 */
+-	nfs_default_version(mi);
+-	
++	if (mi->version.v_mode != V_SPECIFIC) {
++		nfs_default_version(mi);
++		/*
++		 * If the version was not specifically set, it will
++		 * be set by autonegotiation later, so remove it now:
++		 */
++		po_remove_all(mi->options, "v4");
++		po_remove_all(mi->options, "vers");
++		po_remove_all(mi->options, "nfsvers");
++	}
++
++	if (mi->version.v_mode == V_PARSE_ERR)
++		return 0;
++
+ 	return 1;
+ }
+ 
+@@ -693,6 +729,7 @@ static int nfs_do_mount_v4(struct nfsmount_info *mi,
+ {
+ 	struct mount_options *options = po_dup(mi->options);
+ 	int result = 0;
++	char version_opt[16];
+ 	char *extra_opts = NULL;
+ 
+ 	if (!options) {
+@@ -700,20 +737,24 @@ static int nfs_do_mount_v4(struct nfsmount_info *mi,
+ 		return result;
+ 	}
+ 
+-	if (mi->version == 0) {
+-		if (po_contains(options, "mounthost") ||
+-			po_contains(options, "mountaddr") ||
+-			po_contains(options, "mountvers") ||
+-			po_contains(options, "mountproto")) {
+-		/*
+-		 * Since these mountd options are set assume version 3
+-		 * is wanted so error out with EPROTONOSUPPORT so the
+-		 * protocol negation starts with v3.
+-		 */
+-			errno = EPROTONOSUPPORT;
+-			goto out_fail;
+-		}
+-		if (po_append(options, "vers=4") == PO_FAILED) {
++	if (po_contains(options, "mounthost") ||
++		po_contains(options, "mountaddr") ||
++		po_contains(options, "mountvers") ||
++		po_contains(options, "mountproto")) {
++	/*
++	 * Since these mountd options are set assume version 3
++	 * is wanted so error out with EPROTONOSUPPORT so the
++	 * protocol negation starts with v3.
++	 */
++		errno = EPROTONOSUPPORT;
++		goto out_fail;
++	}
++
++	if (mi->version.v_mode != V_SPECIFIC) {
++		snprintf(version_opt, sizeof(version_opt) - 1,
++			"vers=%lu.%lu", mi->version.major, mi->version.minor);
++
++		if (po_append(options, version_opt) == PO_FAILED) {
+ 			errno = EINVAL;
+ 			goto out_fail;
+ 		}
+@@ -801,14 +842,28 @@ static int nfs_autonegotiate(struct nfsmount_info *mi)
+ 	int result;
+ 
+ 	result = nfs_try_mount_v4(mi);
++check_result:
+ 	if (result)
+ 		return result;
+ 
+-check_errno:
+ 	switch (errno) {
+ 	case EPROTONOSUPPORT:
+ 		/* A clear indication that the server or our
+-		 * client does not support NFS version 4. */
++		 * client does not support NFS version 4 and minor */
++	case EINVAL:
++		/* A less clear indication that our client
++		 * does not support NFSv4 minor version. */
++		if (mi->version.v_mode == V_GENERAL &&
++			mi->version.minor == 0)
++				return result;
++		if (mi->version.v_mode != V_SPECIFIC) {
++			if (mi->version.minor > 0) {
++				mi->version.minor--;
++				result = nfs_try_mount_v4(mi);
++				goto check_result;
++			}
++		}
++
+ 		goto fall_back;
+ 	case ENOENT:
+ 		/* Legacy Linux servers don't export an NFS
+@@ -827,7 +882,7 @@ check_errno:
+ 			/* v4 server seems to be registered now. */
+ 			result = nfs_try_mount_v4(mi);
+ 			if (result == 0 && errno != ECONNREFUSED)
+-				goto check_errno;
++				goto check_result;
+ 		}
+ 		return result;
+ 	default:
+@@ -848,19 +903,19 @@ static int nfs_try_mount(struct nfsmount_info *mi)
+ {
+ 	int result = 0;
+ 
+-	switch (mi->version) {
+-	case 0:
+-		result = nfs_autonegotiate(mi);
+-		break;
+-	case 2:
+-	case 3:
+-		result = nfs_try_mount_v3v2(mi, FALSE);
+-		break;
+-	case 4:
+-		result = nfs_try_mount_v4(mi);
+-		break;
+-	default:
+-		errno = EIO;
++	switch (mi->version.major) {
++		case 2:
++		case 3:
++			result = nfs_try_mount_v3v2(mi, FALSE);
++			break;
++		case 4:
++			if (mi->version.v_mode != V_SPECIFIC)
++				result = nfs_autonegotiate(mi);
++			else
++				result = nfs_try_mount_v4(mi);
++			break;
++		default:
++			errno = EIO;
+ 	}
+ 
+ 	return result;
diff --git a/SOURCES/nfs-utils-1.3.0-mount-explicit-rback.patch b/SOURCES/nfs-utils-1.3.0-mount-explicit-rback.patch
new file mode 100644
index 0000000..4e1241b
--- /dev/null
+++ b/SOURCES/nfs-utils-1.3.0-mount-explicit-rback.patch
@@ -0,0 +1,46 @@
+diff -up nfs-utils-1.3.0/utils/mount/stropts.c.orig nfs-utils-1.3.0/utils/mount/stropts.c
+--- nfs-utils-1.3.0/utils/mount/stropts.c.orig	2017-06-01 11:24:19.925018714 -0400
++++ nfs-utils-1.3.0/utils/mount/stropts.c	2017-06-01 11:25:20.033023121 -0400
+@@ -313,9 +313,10 @@ static int nfs_set_version(struct nfsmou
+ 	if (!nfs_nfs_version(mi->options, &mi->version))
+ 		return 0;
+ 
+-	if (strncmp(mi->type, "nfs4", 4) == 0)
++	if (strncmp(mi->type, "nfs4", 4) == 0) {
+ 		mi->version.major = 4;
+-
++		mi->version.v_mode = V_GENERAL;
++	}
+ 	/*
+ 	 * Before 2.6.32, the kernel NFS client didn't
+ 	 * support "-t nfs vers=4" mounts, so NFS version
+@@ -856,9 +857,6 @@ check_result:
+ 	case EINVAL:
+ 		/* A less clear indication that our client
+ 		 * does not support NFSv4 minor version. */
+-		if (mi->version.v_mode == V_GENERAL &&
+-			mi->version.minor == 0)
+-				return result;
+ 		if (mi->version.v_mode != V_SPECIFIC) {
+ 			if (mi->version.minor > 0) {
+ 				mi->version.minor--;
+@@ -880,6 +878,9 @@ check_result:
+ 		/* UDP-Only servers won't support v4, but maybe it
+ 		 * just isn't ready yet.  So try v3, but double-check
+ 		 * with rpcbind for v4. */
++		if (mi->version.v_mode == V_GENERAL)
++			/* Mustn't try v2,v3 */
++			return result;
+ 		result = nfs_try_mount_v3v2(mi, TRUE);
+ 		if (result == 0 && errno == EAGAIN) {
+ 			/* v4 server seems to be registered now. */
+@@ -893,6 +894,9 @@ check_result:
+ 	}
+ 
+ fall_back:
++	if (mi->version.v_mode == V_GENERAL)
++		/* v2,3 fallback not allowed */
++		return result;
+ 	return nfs_try_mount_v3v2(mi, FALSE);
+ }
+ 
diff --git a/SOURCES/nfs-utils-1.3.0-mount-prognotreg.patch b/SOURCES/nfs-utils-1.3.0-mount-prognotreg.patch
new file mode 100644
index 0000000..6fea773
--- /dev/null
+++ b/SOURCES/nfs-utils-1.3.0-mount-prognotreg.patch
@@ -0,0 +1,82 @@
+diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
+index bdd7c24..89b90a1 100644
+--- a/utils/mount/stropts.c
++++ b/utils/mount/stropts.c
+@@ -931,19 +931,45 @@ static int nfs_try_mount(struct nfsmount_info *mi)
+  * failed so far, but fail immediately if there is a local
+  * error (like a bad mount option).
+  *
+- * ESTALE is also a temporary error because some servers
+- * return ESTALE when a share is temporarily offline.
++ * If there is a remote error, like ESTALE or RPC_PROGNOTREGISTERED
++ * then it is probably permanent, but there is a small chance
++ * the it is temporary can we caught the server at an awkward
++ * time during start-up.  So require that we see three of those
++ * before treating them as permanent.
++ * For ECONNREFUSED, wait a bit longer as there is often a longer
++ * gap between the network being ready and the NFS server starting.
+  *
+  * Returns 1 if we should fail immediately, or 0 if we
+  * should retry.
+  */
+ static int nfs_is_permanent_error(int error)
+ {
++	static int prev_error;
++	static int rpt_cnt;
++
++	if (error == prev_error)
++		rpt_cnt += 1;
++	else
++		rpt_cnt = 1;
++	prev_error = error;
++
+ 	switch (error) {
+ 	case ESTALE:
+-	case ETIMEDOUT:
++	case EOPNOTSUPP:	/* aka RPC_PROGNOTREGISTERED */
++		/* If two in a row, assume permanent */
++		return rpt_cnt >= 3;
+ 	case ECONNREFUSED:
++		/* Like the above, this can be temporary during a
++		 * small window.  However it is typically a larger
++		 * window than for the others, and we have historically
++		 * treated this as a temporary (i.e. long timeout)
++		 * error with no complaints, so continue to treat
++		 * it as temporary.
++		 */
++		return 0;	/* temporary */
++	case ETIMEDOUT:
+ 	case EHOSTUNREACH:
++	case EAGAIN:
+ 		return 0;	/* temporary */
+ 	default:
+ 		return 1;	/* permanent */
+@@ -987,7 +1013,7 @@ static int nfsmount_fg(struct nfsmount_info *mi)
+ 			if (secs > 10)
+ 				secs = 10;
+ 		}
+-	};
++	}
+ 
+ 	mount_error(mi->spec, mi->node, errno);
+ 	return EX_FAIL;
+@@ -1005,8 +1031,7 @@ static int nfsmount_parent(struct nfsmount_info *mi)
+ 	if (nfs_try_mount(mi))
+ 		return EX_SUCCESS;
+ 
+-	/* retry background mounts when the server is not up */
+-	if (nfs_is_permanent_error(errno) && errno != EOPNOTSUPP) {
++	if (nfs_is_permanent_error(errno)) {
+ 		mount_error(mi->spec, mi->node, errno);
+ 		return EX_FAIL;
+ 	}
+@@ -1041,8 +1066,7 @@ static int nfsmount_child(struct nfsmount_info *mi)
+ 		if (nfs_try_mount(mi))
+ 			return EX_SUCCESS;
+ 
+-		/* retry background mounts when the server is not up */
+-		if (nfs_is_permanent_error(errno) && errno != EOPNOTSUPP)
++		if (nfs_is_permanent_error(errno))
+ 			break;
+ 
+ 		if (time(NULL) > timeout)
diff --git a/SOURCES/nfs-utils-1.3.0-mount-restore-econn.patch b/SOURCES/nfs-utils-1.3.0-mount-restore-econn.patch
new file mode 100644
index 0000000..8247a1a
--- /dev/null
+++ b/SOURCES/nfs-utils-1.3.0-mount-restore-econn.patch
@@ -0,0 +1,156 @@
+diff --git a/utils/mount/network.c b/utils/mount/network.c
+index 751f9b8..b2e4374 100644
+--- a/utils/mount/network.c
++++ b/utils/mount/network.c
+@@ -33,11 +33,13 @@
+ #include <errno.h>
+ #include <netdb.h>
+ #include <time.h>
++#include <grp.h>
+ 
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <sys/wait.h>
+ #include <sys/stat.h>
++#include <linux/in6.h>
+ #include <netinet/in.h>
+ #include <rpc/rpc.h>
+ #include <rpc/pmap_prot.h>
+@@ -802,6 +804,7 @@ int start_statd(void)
+ 			pid_t pid = fork();
+ 			switch (pid) {
+ 			case 0: /* child */
++				setgroups(0, NULL);
+ 				setgid(0);
+ 				setuid(0);
+ 				execle(START_STATD, START_STATD, NULL, envp);
+@@ -1112,6 +1115,7 @@ static int nfs_ca_sockname(const struct sockaddr *sap, const socklen_t salen,
+ 		.sin6_addr		= IN6ADDR_ANY_INIT,
+ 	};
+ 	int sock, result = 0;
++	int val;
+ 
+ 	sock = socket(sap->sa_family, SOCK_DGRAM, IPPROTO_UDP);
+ 	if (sock < 0)
+@@ -1123,6 +1127,9 @@ static int nfs_ca_sockname(const struct sockaddr *sap, const socklen_t salen,
+ 			goto out;
+ 		break;
+ 	case AF_INET6:
++		/* Make sure the call-back address is public/permanent */
++		val = IPV6_PREFER_SRC_PUBLIC;
++		setsockopt(sock, SOL_IPV6, IPV6_ADDR_PREFERENCES, &val, sizeof(val));
+ 		if (bind(sock, SAFE_SOCKADDR(&sin6), sizeof(sin6)) < 0)
+ 			goto out;
+ 		break;
+diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
+index fc68d41..57e932f 100644
+--- a/utils/mount/stropts.c
++++ b/utils/mount/stropts.c
+@@ -91,6 +91,7 @@ struct nfsmount_info {
+ 				*type;		/* "nfs" or "nfs4" */
+ 	char			*hostname;	/* server's hostname */
+ 	struct addrinfo		*address;	/* server's addresses */
++	sa_family_t		family;		/* Address family */
+ 
+ 	struct mount_options	*options;	/* parsed mount options */
+ 	char			**extra_opts;	/* string for /etc/mtab */
+@@ -388,39 +389,19 @@ static int nfs_set_version(struct nfsmount_info *mi)
+  */
+ static int nfs_validate_options(struct nfsmount_info *mi)
+ {
+-	struct addrinfo hint = {
+-		.ai_protocol	= (int)IPPROTO_UDP,
+-	};
+-	sa_family_t family;
+-	int error;
+-
+ 	if (!nfs_parse_devname(mi->spec, &mi->hostname, NULL))
+ 		return 0;
+ 
+-	if (!nfs_nfs_proto_family(mi->options, &family))
++	if (!nfs_nfs_proto_family(mi->options, &mi->family))
+ 		return 0;
+ 
+ 	/*
+ 	 * A remount is not going to be able to change the server's address,
+ 	 * nor should we try to resolve another address for the server as we
+ 	 * may end up with a different address.
++	 * A non-remount will set 'addr' from ->hostname
+ 	 */
+-	if (mi->flags & MS_REMOUNT) {
+-		po_remove_all(mi->options, "addr");
+-	} else {
+-		hint.ai_family = (int)family;
+-		error = getaddrinfo(mi->hostname, NULL, &hint, &mi->address);
+-		if (error != 0) {
+-			nfs_error(_("%s: Failed to resolve server %s: %s"),
+-				progname, mi->hostname, gai_strerror(error));
+-			mi->address = NULL;
+-			return 0;
+-		}
+-
+-		if (!nfs_append_addr_option(mi->address->ai_addr,
+-						mi->address->ai_addrlen, mi->options))
+-			return 0;
+-	}
++	po_remove_all(mi->options, "addr");
+ 
+ 	if (!nfs_set_version(mi))
+ 		return 0;
+@@ -900,7 +881,10 @@ check_result:
+ 			result = nfs_try_mount_v4(mi);
+ 			if (result == 0 && errno != ECONNREFUSED)
+ 				goto check_result;
+-		}
++		} else if (result == 0)
++			/* Restore original errno with v3 failures */
++			errno = ECONNREFUSED;
++
+ 		return result;
+ 	default:
+ 		return result;
+@@ -923,6 +907,32 @@ static int nfs_try_mount(struct nfsmount_info *mi)
+ {
+ 	int result = 0;
+ 
++	if (mi->address == NULL) {
++		struct addrinfo hint = {
++			.ai_protocol	= (int)IPPROTO_UDP,
++		};
++		int error;
++		struct addrinfo *address;
++
++		hint.ai_family = (int)mi->family;
++		error = getaddrinfo(mi->hostname, NULL, &hint, &address);
++		if (error != 0) {
++			if (error == EAI_AGAIN)
++				errno = EAGAIN;
++			else {
++				nfs_error(_("%s: Failed to resolve server %s: %s"),
++					  progname, mi->hostname, gai_strerror(error));
++				errno = EALREADY;
++			}
++			return 0;
++		}
++
++		if (!nfs_append_addr_option(address->ai_addr,
++					    address->ai_addrlen, mi->options))
++			return 0;
++		mi->address = address;
++	}
++
+ 	switch (mi->version.major) {
+ 		case 2:
+ 		case 3:
+@@ -1018,10 +1028,8 @@ static int nfsmount_fg(struct nfsmount_info *mi)
+ 		if (nfs_is_permanent_error(errno))
+ 			break;
+ 
+-		if (time(NULL) > timeout) {
+-			errno = ETIMEDOUT;
++		if (time(NULL) > timeout)
+ 			break;
+-		}
+ 
+ 		if (errno != ETIMEDOUT) {
+ 			if (sleep(secs))
diff --git a/SOURCES/nfs-utils-1.3.0-mount-uninit-structs.patch b/SOURCES/nfs-utils-1.3.0-mount-uninit-structs.patch
new file mode 100644
index 0000000..1cfbc67
--- /dev/null
+++ b/SOURCES/nfs-utils-1.3.0-mount-uninit-structs.patch
@@ -0,0 +1,100 @@
+commit 0712b5507866d6b3c900623eb1f81fffaec80ae2
+Author: Jianhong Yin <yin-jianhong@163.com>
+Date:   Thu Feb 2 06:21:15 2017 -0500
+
+    mount: fix mount fail that caused by uninitialized struct
+    
+    From: "Jianhong.Yin" <yin-jianhong@163.com>
+    
+    recent changes of utils/mount cause a regression mount fail:
+      https://bugzilla.redhat.com/show_bug.cgi?id=1415024
+    can not reproduce it on x86_64(gcc on x86_64 might do struct
+    initialize by default, I'm not sure). but it can be reproduced
+    always on platform ppc64le aarch64.
+    
+    Signed-off-by: Jianhong Yin <yin-jianhong@163.com>
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+
+diff --git a/utils/gssd/gssd.c b/utils/gssd/gssd.c
+index 4d18d35..77125f1 100644
+--- a/utils/gssd/gssd.c
++++ b/utils/gssd/gssd.c
+@@ -87,6 +87,7 @@ int  root_uses_machine_creds = 1;
+ unsigned int  context_timeout = 0;
+ unsigned int  rpc_timeout = 5;
+ char *preferred_realm = NULL;
++char *ccachedir = NULL;
+ /* Avoid DNS reverse lookups on server names */
+ static bool avoid_dns = true;
+ int thread_started = false;
+@@ -837,18 +838,9 @@ usage(char *progname)
+ 	exit(1);
+ }
+ 
+-int
+-main(int argc, char *argv[])
++inline static void 
++read_gss_conf(void)
+ {
+-	int fg = 0;
+-	int verbosity = 0;
+-	int rpc_verbosity = 0;
+-	int opt;
+-	int i;
+-	extern char *optarg;
+-	char *progname;
+-	char *ccachedir = NULL;
+-	struct event sighup_ev;
+ 	char *s;
+ 
+ 	conf_init();
+@@ -877,6 +869,22 @@ main(int argc, char *argv[])
+ 	if (s)
+ 		preferred_realm = s;
+ 
++}
++
++int
++main(int argc, char *argv[])
++{
++	int fg = 0;
++	int verbosity = 0;
++	int rpc_verbosity = 0;
++	int opt;
++	int i;
++	extern char *optarg;
++	char *progname;
++	struct event sighup_ev;
++
++	read_gss_conf();
++
+ 	while ((opt = getopt(argc, argv, "DfvrlmnMp:k:d:t:T:R:")) != -1) {
+ 		switch (opt) {
+ 			case 'f':
+diff --git a/utils/mount/network.c b/utils/mount/network.c
+index 7dceb2d..d1c8fec 100644
+--- a/utils/mount/network.c
++++ b/utils/mount/network.c
+@@ -1638,6 +1638,7 @@ int nfs_options2pmap(struct mount_options *options,
+ 		     struct pmap *nfs_pmap, struct pmap *mnt_pmap)
+ {
+ 	struct nfs_version version;
++	memset(&version, 0, sizeof(version));
+ 
+ 	if (!nfs_nfs_program(options, &nfs_pmap->pm_prog))
+ 		return 0;
+diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
+index 387d734..a9ff95d 100644
+--- a/utils/mount/stropts.c
++++ b/utils/mount/stropts.c
+@@ -517,6 +517,10 @@ nfs_rewrite_pmap_mount_options(struct mount_options *options, int checkv4)
+ 	unsigned long protocol;
+ 	struct pmap mnt_pmap;
+ 
++	/* initialize structs */
++	memset(&nfs_pmap, 0, sizeof(struct pmap));
++	memset(&mnt_pmap, 0, sizeof(struct pmap));
++
+ 	/*
+ 	 * Version and transport negotiation is not required
+ 	 * and does not work for RDMA mounts.
diff --git a/SOURCES/nfs-utils-1.3.0-mount-use-minor-default.patch b/SOURCES/nfs-utils-1.3.0-mount-use-minor-default.patch
new file mode 100644
index 0000000..fb68b7e
--- /dev/null
+++ b/SOURCES/nfs-utils-1.3.0-mount-use-minor-default.patch
@@ -0,0 +1,89 @@
+diff -up nfs-utils-1.3.0/nfs.conf.orig nfs-utils-1.3.0/nfs.conf
+--- nfs-utils-1.3.0/nfs.conf.orig	2017-06-19 11:15:31.661716122 -0400
++++ nfs-utils-1.3.0/nfs.conf	2017-06-19 11:15:51.945058695 -0400
+@@ -66,6 +66,3 @@
+ # outgoing-port=
+ # outgoing-addr=
+ # lift-grace=y
+-#
+-#[svcgssd]
+-# principal=
+diff -up nfs-utils-1.3.0/utils/mount/stropts.c.orig nfs-utils-1.3.0/utils/mount/stropts.c
+--- nfs-utils-1.3.0/utils/mount/stropts.c.orig	2017-06-19 11:15:31.667716223 -0400
++++ nfs-utils-1.3.0/utils/mount/stropts.c	2017-06-19 11:25:53.000204600 -0400
+@@ -73,6 +73,13 @@
+ #define NFS_DEF_BG_TIMEOUT_MINUTES	(10000u)
+ #endif
+ 
++#ifndef NFS_DEFAULT_MAJOR
++#define NFS_DEFAULT_MAJOR	4
++#endif
++#ifndef NFS_DEFAULT_MINOR
++#define NFS_DEFAULT_MINOR	1
++#endif
++
+ extern int nfs_mount_data_version;
+ extern char *progname;
+ extern int verbose;
+@@ -111,20 +118,28 @@ static void nfs_default_version(struct n
+ 	if (mi->version.v_mode == V_DEFAULT &&
+ 		config_default_vers.v_mode != V_DEFAULT) {
+ 		mi->version.major = config_default_vers.major;
+-		mi->version.minor = config_default_vers.minor;
++		if (config_default_vers.v_mode == V_SPECIFIC)
++			mi->version.minor = config_default_vers.minor;
++		else 
++			mi->version.minor = NFS_DEFAULT_MINOR;
+ 		return;
+ 	}
+ 
+ 	if (mi->version.v_mode == V_GENERAL) {
+ 		if (config_default_vers.v_mode != V_DEFAULT &&
+-		    mi->version.major == config_default_vers.major)
+-			mi->version.minor = config_default_vers.minor;
++		    mi->version.major == config_default_vers.major) {
++			if (config_default_vers.v_mode == V_SPECIFIC)
++				mi->version.minor = config_default_vers.minor;
++			else
++				mi->version.minor = NFS_DEFAULT_MINOR;
++		} else
++			mi->version.minor = NFS_DEFAULT_MINOR;
+ 		return;
+ 	}
+ 
+ #endif /* MOUNT_CONFIG */
+-	mi->version.major = 4;
+-	mi->version.minor = 1;
++	mi->version.major = NFS_DEFAULT_MAJOR;
++	mi->version.minor = NFS_DEFAULT_MINOR;
+ }
+ 
+ /*
+@@ -314,7 +329,9 @@ static int nfs_set_version(struct nfsmou
+ 		return 0;
+ 
+ 	if (strncmp(mi->type, "nfs4", 4) == 0) {
+-		mi->version.major = 4;
++		/* Set to default values */
++		mi->version.major = NFS_DEFAULT_MAJOR;
++		mi->version.minor = NFS_DEFAULT_MINOR;
+ 		mi->version.v_mode = V_GENERAL;
+ 	}
+ 	/*
+@@ -750,13 +767,9 @@ static int nfs_do_mount_v4(struct nfsmou
+ 	}
+ 
+ 	if (mi->version.v_mode != V_SPECIFIC) {
+-		if (mi->version.v_mode == V_GENERAL)
+-			snprintf(version_opt, sizeof(version_opt) - 1,
+-				"vers=%lu", mi->version.major);
+-		else
+-			snprintf(version_opt, sizeof(version_opt) - 1,
+-				"vers=%lu.%lu", mi->version.major,
+-				mi->version.minor);
++		snprintf(version_opt, sizeof(version_opt) - 1,
++			"vers=%lu.%lu", mi->version.major,
++			mi->version.minor);
+ 
+ 		if (po_append(options, version_opt) == PO_FAILED) {
+ 			errno = EINVAL;
diff --git a/SOURCES/nfs-utils-1.3.0-mount-v41.patch b/SOURCES/nfs-utils-1.3.0-mount-v41.patch
new file mode 100644
index 0000000..73c38d0
--- /dev/null
+++ b/SOURCES/nfs-utils-1.3.0-mount-v41.patch
@@ -0,0 +1,12 @@
+diff -up nfs-utils-1.3.0/utils/mount/stropts.c.orig nfs-utils-1.3.0/utils/mount/stropts.c
+--- nfs-utils-1.3.0/utils/mount/stropts.c.orig	2017-03-28 11:13:30.000000000 -0400
++++ nfs-utils-1.3.0/utils/mount/stropts.c	2017-03-28 11:24:11.000000000 -0400
+@@ -124,7 +124,7 @@ static void nfs_default_version(struct n
+ 
+ #endif /* MOUNT_CONFIG */
+ 	mi->version.major = 4;
+-	mi->version.minor = 2;
++	mi->version.minor = 1;
+ }
+ 
+ /*
diff --git a/SOURCES/nfs-utils-1.3.0-mount-v4arg-fix.patch b/SOURCES/nfs-utils-1.3.0-mount-v4arg-fix.patch
new file mode 100644
index 0000000..65c2a5b
--- /dev/null
+++ b/SOURCES/nfs-utils-1.3.0-mount-v4arg-fix.patch
@@ -0,0 +1,45 @@
+diff -up nfs-utils-1.3.0/utils/mount/stropts.c.orig nfs-utils-1.3.0/utils/mount/stropts.c
+--- nfs-utils-1.3.0/utils/mount/stropts.c.orig	2016-12-18 10:59:32.526389233 -0500
++++ nfs-utils-1.3.0/utils/mount/stropts.c	2016-12-18 11:02:17.564900647 -0500
+@@ -108,12 +108,6 @@ static void nfs_default_version(struct n
+ 		return;
+ 	}
+ 
+-	if (mi->version.v_mode == V_GENERAL &&
+-		config_default_vers.v_mode == V_DEFAULT) {
+-		mi->version.v_mode = V_SPECIFIC;
+-		return;
+-	}
+-
+ 	if (mi->version.v_mode == V_DEFAULT &&
+ 		config_default_vers.v_mode != V_DEFAULT) {
+ 		mi->version.major = config_default_vers.major;
+@@ -121,9 +115,9 @@ static void nfs_default_version(struct n
+ 		return;
+ 	}
+ 
+-	if (mi->version.v_mode == V_GENERAL &&
+-		config_default_vers.v_mode != V_DEFAULT) {
+-		if (mi->version.major == config_default_vers.major)
++	if (mi->version.v_mode == V_GENERAL) {
++		if (config_default_vers.v_mode != V_DEFAULT &&
++		    mi->version.major == config_default_vers.major)
+ 			mi->version.minor = config_default_vers.minor;
+ 		return;
+ 	}
+@@ -751,8 +745,13 @@ static int nfs_do_mount_v4(struct nfsmou
+ 	}
+ 
+ 	if (mi->version.v_mode != V_SPECIFIC) {
+-		snprintf(version_opt, sizeof(version_opt) - 1,
+-			"vers=%lu.%lu", mi->version.major, mi->version.minor);
++		if (mi->version.v_mode == V_GENERAL)
++			snprintf(version_opt, sizeof(version_opt) - 1,
++				"vers=%lu", mi->version.major);
++		else
++			snprintf(version_opt, sizeof(version_opt) - 1,
++				"vers=%lu.%lu", mi->version.major,
++				mi->version.minor);
+ 
+ 		if (po_append(options, version_opt) == PO_FAILED) {
+ 			errno = EINVAL;
diff --git a/SOURCES/nfs-utils-1.3.0-mountd-filedes.patch b/SOURCES/nfs-utils-1.3.0-mountd-filedes.patch
new file mode 100644
index 0000000..0e05ddb
--- /dev/null
+++ b/SOURCES/nfs-utils-1.3.0-mountd-filedes.patch
@@ -0,0 +1,633 @@
+diff -up nfs-utils-1.3.0/utils/mountd/cache.c.orig nfs-utils-1.3.0/utils/mountd/cache.c
+--- nfs-utils-1.3.0/utils/mountd/cache.c.orig	2017-01-06 09:31:53.155412013 -0500
++++ nfs-utils-1.3.0/utils/mountd/cache.c	2017-01-06 09:50:52.438190388 -0500
+@@ -61,15 +61,13 @@ enum nfsd_fsid {
+  * Record is terminated with newline.
+  *
+  */
+-static int cache_export_ent(char *domain, struct exportent *exp, char *p);
++static int cache_export_ent(char *buf, int buflen, char *domain, struct exportent *exp, char *path);
+ 
+ #define INITIAL_MANAGED_GROUPS 100
+ 
+-char *lbuf  = NULL;
+-int lbuflen = 0;
+ extern int use_ipaddr;
+ 
+-static void auth_unix_ip(FILE *f)
++static void auth_unix_ip(int f)
+ {
+ 	/* requests are
+ 	 *  class IP-ADDR
+@@ -78,23 +76,26 @@ static void auth_unix_ip(FILE *f)
+ 	 *
+ 	 *  "nfsd" IP-ADDR expiry domainname
+ 	 */
+-	char *cp;
+ 	char class[20];
+ 	char ipaddr[INET6_ADDRSTRLEN + 1];
+ 	char *client = NULL;
+ 	struct addrinfo *tmp = NULL;
+-	if (readline(fileno(f), &lbuf, &lbuflen) != 1)
+-		return;
++	char buf[RPC_CHAN_BUF_SIZE], *bp;
++	int blen;
++
++	blen = read(f, buf, sizeof(buf));
++	if (blen <= 0 || buf[blen-1] != '\n') return;
++	buf[blen-1] = 0;
+ 
+-	xlog(D_CALL, "auth_unix_ip: inbuf '%s'", lbuf);
++	xlog(D_CALL, "auth_unix_ip: inbuf '%s'", buf);
+ 
+-	cp = lbuf;
++	bp = buf;
+ 
+-	if (qword_get(&cp, class, 20) <= 0 ||
++	if (qword_get(&bp, class, 20) <= 0 ||
+ 	    strcmp(class, "nfsd") != 0)
+ 		return;
+ 
+-	if (qword_get(&cp, ipaddr, sizeof(ipaddr) - 1) <= 0)
++	if (qword_get(&bp, ipaddr, sizeof(ipaddr) - 1) <= 0)
+ 		return;
+ 
+ 	tmp = host_pton(ipaddr);
+@@ -113,16 +114,20 @@ static void auth_unix_ip(FILE *f)
+ 			freeaddrinfo(ai);
+ 		}
+ 	}
+-	qword_print(f, "nfsd");
+-	qword_print(f, ipaddr);
+-	qword_printtimefrom(f, DEFAULT_TTL);
++	bp = buf; blen = sizeof(buf);
++	qword_add(&bp, &blen, "nfsd");
++	qword_add(&bp, &blen, ipaddr);
++	qword_adduint(&bp, &blen, time(0) + DEFAULT_TTL);
+ 	if (use_ipaddr) {
+ 		memmove(ipaddr + 1, ipaddr, strlen(ipaddr) + 1);
+ 		ipaddr[0] = '$';
+-		qword_print(f, ipaddr);
++		qword_add(&bp, &blen, ipaddr);
+ 	} else if (client)
+-		qword_print(f, *client?client:"DEFAULT");
+-	qword_eol(f);
++		qword_add(&bp, &blen, *client?client:"DEFAULT");
++	qword_addeol(&bp, &blen);
++	if (blen <= 0 || write(f, buf, bp - buf) != bp - buf)
++		xlog(L_ERROR, "auth_unix_ip: error writing reply");
++
+ 	xlog(D_CALL, "auth_unix_ip: client %p '%s'", client, client?client: "DEFAULT");
+ 
+ 	free(client);
+@@ -130,7 +135,7 @@ static void auth_unix_ip(FILE *f)
+ 
+ }
+ 
+-static void auth_unix_gid(FILE *f)
++static void auth_unix_gid(int f)
+ {
+ 	/* Request are
+ 	 *  uid
+@@ -144,7 +149,8 @@ static void auth_unix_gid(FILE *f)
+ 	gid_t *more_groups;
+ 	int ngroups;
+ 	int rv, i;
+-	char *cp;
++	char buf[RPC_CHAN_BUF_SIZE], *bp;
++	int blen;
+ 
+ 	if (groups_len == 0) {
+ 		groups = malloc(sizeof(gid_t) * INITIAL_MANAGED_GROUPS);
+@@ -156,11 +162,12 @@ static void auth_unix_gid(FILE *f)
+ 
+ 	ngroups = groups_len;
+ 
+-	if (readline(fileno(f), &lbuf, &lbuflen) != 1)
+-		return;
++	blen = read(f, buf, sizeof(buf));
++	if (blen <= 0 || buf[blen-1] != '\n') return;
++	buf[blen-1] = 0;
+ 
+-	cp = lbuf;
+-	if (qword_get_uint(&cp, &uid) != 0)
++	bp = buf;
++	if (qword_get_uint(&bp, &uid) != 0)
+ 		return;
+ 
+ 	pw = getpwuid(uid);
+@@ -180,15 +187,19 @@ static void auth_unix_gid(FILE *f)
+ 			}
+ 		}
+ 	}
+-	qword_printuint(f, uid);
+-	qword_printtimefrom(f, DEFAULT_TTL);
++
++	bp = buf; blen = sizeof(buf);
++	qword_adduint(&bp, &blen, uid);
++	qword_adduint(&bp, &blen, time(0) + DEFAULT_TTL);
+ 	if (rv >= 0) {
+-		qword_printuint(f, ngroups);
++		qword_adduint(&bp, &blen, ngroups);
+ 		for (i=0; i<ngroups; i++)
+-			qword_printuint(f, groups[i]);
++			qword_adduint(&bp, &blen, groups[i]);
+ 	} else
+-		qword_printuint(f, 0);
+-	qword_eol(f);
++		qword_adduint(&bp, &blen, 0);
++	qword_addeol(&bp, &blen);
++	if (blen <= 0 || write(f, buf, bp - buf) != bp - buf)
++		xlog(L_ERROR, "auth_unix_gid: error writing reply");
+ }
+ 
+ #if USE_BLKID
+@@ -578,14 +589,13 @@ static struct addrinfo *lookup_client_ad
+ 	return ret;
+ }
+ 
+-static void nfsd_fh(FILE *f)
++static void nfsd_fh(int f)
+ {
+ 	/* request are:
+ 	 *  domain fsidtype fsid
+ 	 * interpret fsid, find export point and options, and write:
+ 	 *  domain fsidtype fsid expiry path
+ 	 */
+-	char *cp;
+ 	char *dom;
+ 	int fsidtype;
+ 	int fsidlen;
+@@ -597,24 +607,27 @@ static void nfsd_fh(FILE *f)
+ 	nfs_export *exp;
+ 	int i;
+ 	int dev_missing = 0;
++	char buf[RPC_CHAN_BUF_SIZE], *bp;
++	int blen;
+ 
+-	if (readline(fileno(f), &lbuf, &lbuflen) != 1)
+-		return;
++	blen = read(f, buf, sizeof(buf));
++	if (blen <= 0 || buf[blen-1] != '\n') return;
++	buf[blen-1] = 0;
+ 
+-	xlog(D_CALL, "nfsd_fh: inbuf '%s'", lbuf);
++	xlog(D_CALL, "nfsd_fh: inbuf '%s'", buf);
+ 
+-	cp = lbuf;
++	bp = buf;
+ 
+-	dom = malloc(strlen(cp));
++	dom = malloc(blen);
+ 	if (dom == NULL)
+ 		return;
+-	if (qword_get(&cp, dom, strlen(cp)) <= 0)
++	if (qword_get(&bp, dom, blen) <= 0)
+ 		goto out;
+-	if (qword_get_int(&cp, &fsidtype) != 0)
++	if (qword_get_int(&bp, &fsidtype) != 0)
+ 		goto out;
+ 	if (fsidtype < 0 || fsidtype > 7)
+ 		goto out; /* unknown type */
+-	if ((fsidlen = qword_get(&cp, fsid, 32)) <= 0)
++	if ((fsidlen = qword_get(&bp, fsid, 32)) <= 0)
+ 		goto out;
+ 	if (parse_fsid(fsidtype, fsidlen, fsid, &parsed))
+ 		goto out;
+@@ -715,12 +728,13 @@ static void nfsd_fh(FILE *f)
+ 	}
+ 
+ 	if (found)
+-		if (cache_export_ent(dom, found, found_path) < 0)
++		if (cache_export_ent(buf, sizeof(buf), dom, found, found_path) < 0)
+ 			found = 0;
+ 
+-	qword_print(f, dom);
+-	qword_printint(f, fsidtype);
+-	qword_printhex(f, fsid, fsidlen);
++	bp = buf; blen = sizeof(buf);
++	qword_add(&bp, &blen, dom);
++	qword_addint(&bp, &blen, fsidtype);
++	qword_addhex(&bp, &blen, fsid, fsidlen);
+ 	/* The fsid -> path lookup can be quite expensive as it
+ 	 * potentially stats and reads lots of devices, and some of those
+ 	 * might have spun-down.  The Answer is not likely to
+@@ -729,20 +743,21 @@ static void nfsd_fh(FILE *f)
+ 	 * timeout.  Maybe this should be configurable on the command
+ 	 * line.
+ 	 */
+-	qword_printint(f, 0x7fffffff);
++	qword_addint(&bp, &blen, 0x7fffffff);
+ 	if (found)
+-		qword_print(f, found_path);
+-	qword_eol(f);
+- out:
++		qword_add(&bp, &blen, found_path);
++	qword_addeol(&bp, &blen);
++	if (blen <= 0 || write(f, buf, bp - buf) != bp - buf)
++		xlog(L_ERROR, "nfsd_fh: error writing reply");
++out:
+ 	if (found_path)
+ 		free(found_path);
+ 	freeaddrinfo(ai);
+ 	free(dom);
+ 	xlog(D_CALL, "nfsd_fh: found %p path %s", found, found ? found->e_path : NULL);
+-	return;		
+ }
+ 
+-static void write_fsloc(FILE *f, struct exportent *ep)
++static void write_fsloc(char **bp, int *blen, struct exportent *ep)
+ {
+ 	struct servers *servers;
+ 
+@@ -752,20 +767,20 @@ static void write_fsloc(FILE *f, struct
+ 	servers = replicas_lookup(ep->e_fslocmethod, ep->e_fslocdata);
+ 	if (!servers)
+ 		return;
+-	qword_print(f, "fsloc");
+-	qword_printint(f, servers->h_num);
++	qword_add(bp, blen, "fsloc");
++	qword_addint(bp, blen, servers->h_num);
+ 	if (servers->h_num >= 0) {
+ 		int i;
+ 		for (i=0; i<servers->h_num; i++) {
+-			qword_print(f, servers->h_mp[i]->h_host);
+-			qword_print(f, servers->h_mp[i]->h_path);
++			qword_add(bp, blen, servers->h_mp[i]->h_host);
++			qword_add(bp, blen, servers->h_mp[i]->h_path);
+ 		}
+ 	}
+-	qword_printint(f, servers->h_referral);
++	qword_addint(bp, blen, servers->h_referral);
+ 	release_replicas(servers);
+ }
+ 
+-static void write_secinfo(FILE *f, struct exportent *ep, int flag_mask)
++static void write_secinfo(char **bp, int *blen, struct exportent *ep, int flag_mask)
+ {
+ 	struct sec_entry *p;
+ 
+@@ -776,45 +791,52 @@ static void write_secinfo(FILE *f, struc
+ 		return;
+ 	}
+ 	fix_pseudoflavor_flags(ep);
+-	qword_print(f, "secinfo");
+-	qword_printint(f, p - ep->e_secinfo);
++	qword_add(bp, blen, "secinfo");
++	qword_addint(bp, blen, p - ep->e_secinfo);
+ 	for (p = ep->e_secinfo; p->flav; p++) {
+-		qword_printint(f, p->flav->fnum);
+-		qword_printint(f, p->flags & flag_mask);
++		qword_addint(bp, blen, p->flav->fnum);
++		qword_addint(bp, blen, p->flags & flag_mask);
+ 	}
+ 
+ }
+ 
+-static int dump_to_cache(FILE *f, char *domain, char *path, struct exportent *exp)
++static int dump_to_cache(int f, char *buf, int buflen, char *domain, char *path, struct exportent *exp)
+ {
+-	qword_print(f, domain);
+-	qword_print(f, path);
++	char *bp = buf;
++	int blen = buflen;
++	time_t now = time(0);
++
++	qword_add(&bp, &blen, domain);
++	qword_add(&bp, &blen, path);
+ 	if (exp) {
+ 		int different_fs = strcmp(path, exp->e_path) != 0;
+ 		int flag_mask = different_fs ? ~NFSEXP_FSID : ~0;
+ 
+-		qword_printtimefrom(f, exp->e_ttl);
+-		qword_printint(f, exp->e_flags & flag_mask);
+-		qword_printint(f, exp->e_anonuid);
+-		qword_printint(f, exp->e_anongid);
+-		qword_printint(f, exp->e_fsid);
+-		write_fsloc(f, exp);
+-		write_secinfo(f, exp, flag_mask);
+- 		if (exp->e_uuid == NULL || different_fs) {
+- 			char u[16];
+- 			if (uuid_by_path(path, 0, 16, u)) {
+- 				qword_print(f, "uuid");
+- 				qword_printhex(f, u, 16);
+- 			}
+- 		} else {
+- 			char u[16];
+- 			get_uuid(exp->e_uuid, 16, u);
+- 			qword_print(f, "uuid");
+- 			qword_printhex(f, u, 16);
+- 		}
++		qword_adduint(&bp, &blen, now + exp->e_ttl);
++		qword_addint(&bp, &blen, exp->e_flags & flag_mask);
++		qword_addint(&bp, &blen, exp->e_anonuid);
++		qword_addint(&bp, &blen, exp->e_anongid);
++		qword_addint(&bp, &blen, exp->e_fsid);
++		write_fsloc(&bp, &blen, exp);
++		write_secinfo(&bp, &blen, exp, flag_mask);
++		if (exp->e_uuid == NULL || different_fs) {
++			char u[16];
++			if (uuid_by_path(path, 0, 16, u)) {
++				qword_add(&bp, &blen, "uuid");
++				qword_addhex(&bp, &blen, u, 16);
++			}
++		} else {
++			char u[16];
++			get_uuid(exp->e_uuid, 16, u);
++			qword_add(&bp, &blen, "uuid");
++			qword_addhex(&bp, &blen, u, 16);
++		}
+ 	} else
+-		qword_printtimefrom(f, DEFAULT_TTL);
+-	return qword_eol(f);
++		qword_adduint(&bp, &blen, now + DEFAULT_TTL);
++	qword_addeol(&bp, &blen);
++	if (blen <= 0) return -1;
++	if (write(f, buf, bp - buf) != bp - buf) return -1;
++	return 0;
+ }
+ 
+ static nfs_export *
+@@ -1164,27 +1186,27 @@ static struct exportent *lookup_junction
+ 	return exp;
+ }
+ 
+-static void lookup_nonexport(FILE *f, char *dom, char *path,
++static void lookup_nonexport(int f, char *buf, int buflen, char *dom, char *path,
+ 		struct addrinfo *ai)
+ {
+ 	struct exportent *eep;
+ 
+ 	eep = lookup_junction(dom, path, ai);
+-	dump_to_cache(f, dom, path, eep);
++	dump_to_cache(f, buf, buflen, dom, path, eep);
+ 	if (eep == NULL)
+ 		return;
+ 	exportent_release(eep);
+ 	free(eep);
+ }
+ #else	/* !HAVE_NFS_PLUGIN_H */
+-static void lookup_nonexport(FILE *f, char *dom, char *path,
++static void lookup_nonexport(int f, char *buf, int buflen, char *dom, char *path,
+ 		struct addrinfo *UNUSED(ai))
+ {
+-	dump_to_cache(f, dom, path, NULL);
++	dump_to_cache(f, buf, buflen, dom, path, NULL);
+ }
+ #endif	/* !HAVE_NFS_PLUGIN_H */
+ 
+-static void nfsd_export(FILE *f)
++static void nfsd_export(int f)
+ {
+ 	/* requests are:
+ 	 *  domain path
+@@ -1192,26 +1214,28 @@ static void nfsd_export(FILE *f)
+ 	 *  domain path expiry flags anonuid anongid fsid
+ 	 */
+ 
+-	char *cp;
+ 	char *dom, *path;
+ 	nfs_export *found = NULL;
+ 	struct addrinfo *ai = NULL;
++	char buf[RPC_CHAN_BUF_SIZE], *bp;
++	int blen;
+ 
+-	if (readline(fileno(f), &lbuf, &lbuflen) != 1)
+-		return;
+-
+-	xlog(D_CALL, "nfsd_export: inbuf '%s'", lbuf);
+-
+-	cp = lbuf;
+-	dom = malloc(strlen(cp));
+-	path = malloc(strlen(cp));
++	blen = read(f, buf, sizeof(buf));
++	if (blen <= 0 || buf[blen-1] != '\n') return;
++	buf[blen-1] = 0;
++
++	xlog(D_CALL, "nfsd_export: inbuf '%s'", buf);
++
++	bp = buf;
++	dom = malloc(blen);
++	path = malloc(blen);
+ 
+ 	if (!dom || !path)
+ 		goto out;
+ 
+-	if (qword_get(&cp, dom, strlen(lbuf)) <= 0)
++	if (qword_get(&bp, dom, blen) <= 0)
+ 		goto out;
+-	if (qword_get(&cp, path, strlen(lbuf)) <= 0)
++	if (qword_get(&bp, path, blen) <= 0)
+ 		goto out;
+ 
+ 	auth_reload();
+@@ -1225,14 +1249,14 @@ static void nfsd_export(FILE *f)
+ 	found = lookup_export(dom, path, ai);
+ 
+ 	if (found) {
+-		if (dump_to_cache(f, dom, path, &found->m_export) < 0) {
++		if (dump_to_cache(f, buf, sizeof(buf), dom, path, &found->m_export) < 0) {
+ 			xlog(L_WARNING,
+ 			     "Cannot export %s, possibly unsupported filesystem"
+ 			     " or fsid= required", path);
+-			dump_to_cache(f, dom, path, NULL);
++			dump_to_cache(f, buf, sizeof(buf), dom, path, NULL);
+ 		}
+ 	} else
+-		lookup_nonexport(f, dom, path, ai);
++		lookup_nonexport(f, buf, sizeof(buf), dom, path, ai);
+ 
+  out:
+ 	xlog(D_CALL, "nfsd_export: found %p path %s", found, path ? path : NULL);
+@@ -1244,15 +1268,14 @@ static void nfsd_export(FILE *f)
+ 
+ struct {
+ 	char *cache_name;
+-	void (*cache_handle)(FILE *f);
+-	FILE *f;
+-	char vbuf[RPC_CHAN_BUF_SIZE];
++	void (*cache_handle)(int f);
++	int f;
+ } cachelist[] = {
+-	{ "auth.unix.ip", auth_unix_ip, NULL, ""},
+-	{ "auth.unix.gid", auth_unix_gid, NULL, ""},
+-	{ "nfsd.export", nfsd_export, NULL, ""},
+-	{ "nfsd.fh", nfsd_fh, NULL, ""},
+-	{ NULL, NULL, NULL, ""}
++	{ "auth.unix.ip", auth_unix_ip, -1 },
++	{ "auth.unix.gid", auth_unix_gid, -1 },
++	{ "nfsd.export", nfsd_export, -1 },
++	{ "nfsd.fh", nfsd_fh, -1 },
++	{ NULL, NULL, -1 }
+ };
+ 
+ extern int manage_gids;
+@@ -1269,11 +1292,7 @@ void cache_open(void)
+ 		if (!manage_gids && cachelist[i].cache_handle == auth_unix_gid)
+ 			continue;
+ 		sprintf(path, "/proc/net/rpc/%s/channel", cachelist[i].cache_name);
+-		cachelist[i].f = fopen(path, "r+");
+-		if (cachelist[i].f != NULL) {
+-			setvbuf(cachelist[i].f, cachelist[i].vbuf, _IOLBF, 
+-				RPC_CHAN_BUF_SIZE);
+-		}
++		cachelist[i].f = open(path, O_RDWR);
+ 	}
+ }
+ 
+@@ -1285,8 +1304,8 @@ void cache_set_fds(fd_set *fdset)
+ {
+ 	int i;
+ 	for (i=0; cachelist[i].cache_name; i++) {
+-		if (cachelist[i].f)
+-			FD_SET(fileno(cachelist[i].f), fdset);
++		if (cachelist[i].f >= 0)
++			FD_SET(cachelist[i].f, fdset);
+ 	}
+ }
+ 
+@@ -1299,11 +1318,11 @@ int cache_process_req(fd_set *readfds)
+ 	int i;
+ 	int cnt = 0;
+ 	for (i=0; cachelist[i].cache_name; i++) {
+-		if (cachelist[i].f != NULL &&
+-		    FD_ISSET(fileno(cachelist[i].f), readfds)) {
++		if (cachelist[i].f >= 0 &&
++		    FD_ISSET(cachelist[i].f, readfds)) {
+ 			cnt++;
+ 			cachelist[i].cache_handle(cachelist[i].f);
+-			FD_CLR(fileno(cachelist[i].f), readfds);
++			FD_CLR(cachelist[i].f, readfds);
+ 		}
+ 	}
+ 	return cnt;
+@@ -1316,14 +1335,14 @@ int cache_process_req(fd_set *readfds)
+  * % echo $domain $path $[now+DEFAULT_TTL] $options $anonuid $anongid $fsid > /proc/net/rpc/nfsd.export/channel
+  */
+ 
+-static int cache_export_ent(char *domain, struct exportent *exp, char *path)
++static int cache_export_ent(char *buf, int buflen, char *domain, struct exportent *exp, char *path)
+ {
+-	int err;
+-	FILE *f = fopen("/proc/net/rpc/nfsd.export/channel", "w");
+-	if (!f)
+-		return -1;
++	int f, err;
++
++	f = open("/proc/net/rpc/nfsd.export/channel", O_WRONLY);
++	if (f < 0) return -1;
+ 
+-	err = dump_to_cache(f, domain, exp->e_path, exp);
++	err = dump_to_cache(f, buf, buflen, domain, exp->e_path, exp);
+ 	if (err) {
+ 		xlog(L_WARNING,
+ 		     "Cannot export %s, possibly unsupported filesystem or"
+@@ -1364,13 +1383,13 @@ static int cache_export_ent(char *domain
+ 				continue;
+ 			dev = stb.st_dev;
+ 			path[l] = 0;
+-			dump_to_cache(f, domain, path, exp);
++			dump_to_cache(f, buf, buflen, domain, path, exp);
+ 			path[l] = c;
+ 		}
+ 		break;
+ 	}
+ 
+-	fclose(f);
++	close(f);
+ 	return err;
+ }
+ 
+@@ -1381,27 +1400,25 @@ static int cache_export_ent(char *domain
+  */
+ int cache_export(nfs_export *exp, char *path)
+ {
+-	char buf[INET6_ADDRSTRLEN];
+-	int err;
+-	FILE *f;
++	char ip[INET6_ADDRSTRLEN];
++	char buf[RPC_CHAN_BUF_SIZE], *bp;
++	int blen, f;
+ 
+-	f = fopen("/proc/net/rpc/auth.unix.ip/channel", "w");
+-	if (!f)
++	f = open("/proc/net/rpc/auth.unix.ip/channel", O_WRONLY);
++	if (f < 0)
+ 		return -1;
+ 
++	bp = buf, blen = sizeof(buf);
++	qword_add(&bp, &blen, "nfsd");
++	qword_add(&bp, &blen, host_ntop(get_addrlist(exp->m_client, 0), ip, sizeof(ip)));
++	qword_adduint(&bp, &blen, time(0) + exp->m_export.e_ttl);
++	qword_add(&bp, &blen, exp->m_client->m_hostname);
++	qword_addeol(&bp, &blen);
++	if (blen <= 0 || write(f, buf, bp - buf) != bp - buf) blen = -1;
++	close(f);
++	if (blen < 0) return -1;
+ 
+-	qword_print(f, "nfsd");
+-	qword_print(f,
+-		host_ntop(get_addrlist(exp->m_client, 0), buf, sizeof(buf)));
+-	qword_printtimefrom(f, exp->m_export.e_ttl);
+-	qword_print(f, exp->m_client->m_hostname);
+-	err = qword_eol(f);
+-	
+-	fclose(f);
+-
+-	err = cache_export_ent(exp->m_client->m_hostname, &exp->m_export, path)
+-		|| err;
+-	return err;
++	return cache_export_ent(buf, sizeof(buf), exp->m_client->m_hostname, &exp->m_export, path);
+ }
+ 
+ /**
+@@ -1420,27 +1437,33 @@ int cache_export(nfs_export *exp, char *
+ struct nfs_fh_len *
+ cache_get_filehandle(nfs_export *exp, int len, char *p)
+ {
+-	FILE *f = fopen("/proc/fs/nfsd/filehandle", "r+");
+-	char buf[200];
+-	char *bp = buf;
+-	int failed;
+ 	static struct nfs_fh_len fh;
++	char buf[RPC_CHAN_BUF_SIZE], *bp;
++	int blen, f;
+ 
+-	if (!f)
+-		f = fopen("/proc/fs/nfs/filehandle", "r+");
+-	if (!f)
++	f = open("/proc/fs/nfsd/filehandle", O_RDWR);
++	if (f < 0) {
++		f = open("/proc/fs/nfs/filehandle", O_RDWR);
++		if (f < 0) return NULL;
++	}
++
++	bp = buf, blen = sizeof(buf);
++	qword_add(&bp, &blen, exp->m_client->m_hostname);
++	qword_add(&bp, &blen, p);
++	qword_addint(&bp, &blen, len);
++	qword_addeol(&bp, &blen);
++	if (blen <= 0 || write(f, buf, bp - buf) != bp - buf) {
++		close(f);
+ 		return NULL;
++	}
++	bp = buf;
++	blen = read(f, buf, sizeof(buf));
++	close(f);
+ 
+-	qword_print(f, exp->m_client->m_hostname);
+-	qword_print(f, p);
+-	qword_printint(f, len);	
+-	failed = qword_eol(f);
+-	
+-	if (!failed)
+-		failed = (fgets(buf, sizeof(buf), f) == NULL);
+-	fclose(f);
+-	if (failed)
++	if (blen <= 0 || buf[blen-1] != '\n')
+ 		return NULL;
++	buf[blen-1] = 0;
++
+ 	memset(fh.fh_handle, 0, sizeof(fh.fh_handle));
+ 	fh.fh_size = qword_get(&bp, (char *)fh.fh_handle, NFS3_FHSIZE);
+ 	return &fh;
diff --git a/SOURCES/nfs-utils-1.3.0-mountstats-iostats.patch b/SOURCES/nfs-utils-1.3.0-mountstats-iostats.patch
new file mode 100644
index 0000000..8efd060
--- /dev/null
+++ b/SOURCES/nfs-utils-1.3.0-mountstats-iostats.patch
@@ -0,0 +1,15 @@
+diff -up nfs-utils-1.3.0/tools/mountstats/mountstats.py.orig nfs-utils-1.3.0/tools/mountstats/mountstats.py
+--- nfs-utils-1.3.0/tools/mountstats/mountstats.py.orig	2017-04-08 15:23:53.524215286 -0400
++++ nfs-utils-1.3.0/tools/mountstats/mountstats.py	2017-04-08 15:30:45.862043179 -0400
+@@ -565,7 +565,10 @@ class DeviceData:
+         for the nfsstat command.
+         """
+         for op in new_stats.__rpc_data['ops']:
+-            self.__rpc_data[op] = list(map(add, self.__rpc_data[op], new_stats.__rpc_data[op]))
++            try:
++                self.__rpc_data[op] = list(map(add, self.__rpc_data[op], new_stats.__rpc_data[op]))
++            except KeyError:
++                continue
+ 
+     def __print_rpc_op_stats(self, op, sample_time):
+         """Print generic stats for one RPC op
diff --git a/SOURCES/nfs-utils-1.3.0-mountstats-pnfs.patch b/SOURCES/nfs-utils-1.3.0-mountstats-pnfs.patch
new file mode 100644
index 0000000..3f5f860
--- /dev/null
+++ b/SOURCES/nfs-utils-1.3.0-mountstats-pnfs.patch
@@ -0,0 +1,26 @@
+commit 3e2ab78a2cfbc2d11c31ced8d3f538d5aae757f1
+Author: Scott Mayhew <smayhew@redhat.com>
+Date:   Thu Sep 22 13:33:33 2016 -0400
+
+    mountstats: add pNFS READs and WRITEs
+    
+    These counters are already in /proc/self/mountstats but the mountstats
+    program doesn't display them.
+    
+    Signed-off-by: Scott Mayhew <smayhew@redhat.com>
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+    Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1377740
+
+diff --git a/tools/mountstats/mountstats.py b/tools/mountstats/mountstats.py
+index 4ca4bc4..88ccdae 100644
+--- a/tools/mountstats/mountstats.py
++++ b/tools/mountstats/mountstats.py
+@@ -412,6 +412,8 @@ class DeviceData:
+         print('  short reads: %d  short writes: %d' % \
+             (self.__nfs_data['shortreads'], self.__nfs_data['shortwrites']))
+         print('  NFSERR_DELAYs from server: %d' % self.__nfs_data['delay'])
++        print('  pNFS READs: %d' % self.__nfs_data['pnfsreads'])
++        print('  pNFS WRITEs: %d' % self.__nfs_data['pnfswrites'])
+ 
+     def display_nfs_bytes(self):
+         """Pretty-print the NFS event counters
diff --git a/SOURCES/nfs-utils-1.3.0-nfs-conf.patch b/SOURCES/nfs-utils-1.3.0-nfs-conf.patch
new file mode 100644
index 0000000..0252267
--- /dev/null
+++ b/SOURCES/nfs-utils-1.3.0-nfs-conf.patch
@@ -0,0 +1,1892 @@
+diff -up nfs-utils-1.3.0/configure.ac.orig nfs-utils-1.3.0/configure.ac
+--- nfs-utils-1.3.0/configure.ac.orig	2017-03-28 13:43:36.000000000 -0400
++++ nfs-utils-1.3.0/configure.ac	2017-03-28 13:43:53.000000000 -0400
+@@ -23,6 +23,12 @@ AC_ARG_WITH(statedir,
+ 	statedir=$withval,
+ 	statedir=/var/lib/nfs)
+ 	AC_SUBST(statedir)
++AC_ARG_WITH(nfsconfig,
++	[AC_HELP_STRING([--with-nfsconfig=/config/file],
++			[use general config file /config/file @<:@default=/etc/nfs.conf@:>@])],
++	nfsconfig=$withval,
++	nfsconfig=/etc/nfs.conf)
++	AC_SUBST(nfsconfig)
+ AC_ARG_WITH(statdpath,
+ 	[AC_HELP_STRING([--with-statdpath=/foo],
+ 			[define the statd state dir as /foo instead of the NFS statedir @<:@default=/var/lib/nfs@:>@])],
+@@ -442,6 +448,7 @@ dnl Export some path names to config.h
+ dnl *************************************************************
+ AC_DEFINE_UNQUOTED(NFS_STATEDIR, "$statedir", [This defines the location of the NFS state files. Warning: this must match definitions in config.mk!])
+ AC_DEFINE_UNQUOTED(NSM_DEFAULT_STATEDIR, "$statdpath", [Define this to the pathname where statd keeps its state file])
++AC_DEFINE_UNQUOTED(NFS_CONFFILE, "$nfsconfig", [This defines the location of NFS daemon config file])
+ 
+ if test "x$cross_compiling" = "xno"; then
+ 	CFLAGS_FOR_BUILD=${CFLAGS_FOR_BUILD-"$CFLAGS"}
+diff -up nfs-utils-1.3.0/support/include/conffile.h.orig nfs-utils-1.3.0/support/include/conffile.h
+--- nfs-utils-1.3.0/support/include/conffile.h.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/support/include/conffile.h	2017-03-28 13:43:53.000000000 -0400
+@@ -35,6 +35,8 @@
+ 
+ #include <sys/queue.h>
+ #include <ctype.h>
++#include <stdint.h>
++#include <stdbool.h>
+ 
+ struct conf_list_node {
+ 	TAILQ_ENTRY(conf_list_node) link;
+@@ -56,6 +58,7 @@ extern struct sockaddr *conf_get_address
+ extern struct conf_list *conf_get_list(char *, char *);
+ extern struct conf_list *conf_get_tag_list(char *, char *);
+ extern int      conf_get_num(char *, char *, int);
++extern _Bool    conf_get_bool(char *, char *, _Bool);
+ extern char    *conf_get_str(char *, char *);
+ extern char    *conf_get_section(char *, char *, char *);
+ extern void     conf_init(void);
+diff -up nfs-utils-1.3.0/support/include/xlog.h.orig nfs-utils-1.3.0/support/include/xlog.h
+--- nfs-utils-1.3.0/support/include/xlog.h.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/support/include/xlog.h	2017-03-28 13:43:53.000000000 -0400
+@@ -41,6 +41,7 @@ void			xlog_stderr(int on);
+ void			xlog_syslog(int on);
+ void			xlog_config(int fac, int on);
+ void			xlog_sconfig(char *, int on);
++void			xlog_from_conffile(char *);
+ int			xlog_enabled(int fac);
+ void			xlog(int fac, const char *fmt, ...);
+ void			xlog_warn(const char *fmt, ...);
+diff -up nfs-utils-1.3.0/support/nfs/conffile.c.orig nfs-utils-1.3.0/support/nfs/conffile.c
+--- nfs-utils-1.3.0/support/nfs/conffile.c.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/support/nfs/conffile.c	2017-03-28 13:43:53.000000000 -0400
+@@ -52,6 +52,7 @@
+ #pragma GCC visibility push(hidden)
+ 
+ static void conf_load_defaults(void);
++static int conf_load(int trans, char *path);
+ static int conf_set(int , char *, char *, char *, 
+ 	char *, int , int );
+ 
+@@ -107,8 +108,6 @@ struct conf_binding {
+ char *conf_path;
+ LIST_HEAD (conf_bindings, conf_binding) conf_bindings[256];
+ 
+-static char *conf_addr;
+-
+ static __inline__ u_int8_t
+ conf_hash(char *s)
+ {
+@@ -213,7 +212,7 @@ static void
+ conf_parse_line(int trans, char *line, size_t sz)
+ {
+ 	char *val, *ptr;
+-	size_t i, valsize;
++	size_t i;
+ 	size_t j;
+ 	static char *section = 0;
+ 	static char *arg = 0;
+@@ -300,18 +299,32 @@ conf_parse_line(int trans, char *line, s
+ 			}
+ 			line[strcspn (line, " \t=")] = '\0';
+ 			val = line + i + 1 + strspn (line + i + 1, " \t");
+-			valsize = 0;
+-			while (val[valsize++]);
+ 
+-			/* Skip trailing spaces and comments */
+-			for (j = 0; j < valsize; j++) {
+-				if (val[j] == '#' || val[j] == ';' || isspace(val[j])) {
+-					val[j] = '\0';
+-					break;
++			if (val[0] == '"') {
++				val ++;
++				j = strcspn(val, "\"");
++				val[j] = 0;
++			} else if (val[0] == '\'') {
++				val ++;
++				j = strcspn(val, "'");
++				val[j] = 0;
++			} else {
++				/* Skip trailing spaces and comments */
++				for (j = 0; val[j]; j++) {
++					if ((val[j] == '#' || val[j] == ';')
++					    && (j == 0 || isspace(val[j-1]))) {
++						val[j] = '\0';
++						break;
++					}
+ 				}
++				while (j && isspace(val[j-1]))
++					val[--j] = '\0';
+ 			}
+-			/* XXX Perhaps should we not ignore errors?  */
+-			conf_set(trans, section, arg, line, val, 0, 0);
++			if (strcasecmp(line, "include") == 0)
++				conf_load(trans, val);
++			else
++				/* XXX Perhaps should we not ignore errors?  */
++				conf_set(trans, section, arg, line, val, 0, 0);
+ 			return;
+ 		}
+ 	}
+@@ -368,23 +381,18 @@ conf_init (void)
+ 	conf_reinit();
+ }
+ 
+-/* Open the config file and map it into our address space, then parse it.  */
+-void
+-conf_reinit(void)
++static int
++conf_load(int trans, char *path)
+ {
+-	struct conf_binding *cb = 0;
+-	int fd, trans;
+-	unsigned int i;
+-	size_t sz;
+-	char *new_conf_addr = 0;
+ 	struct stat sb;
++	if ((stat (path, &sb) == 0) || (errno != ENOENT)) {
++		char *new_conf_addr;
++		size_t sz = sb.st_size;
++		int fd = open (path, O_RDONLY, 0);
+ 
+-	if ((stat (conf_path, &sb) == 0) || (errno != ENOENT)) {
+-		sz = sb.st_size;
+-		fd = open (conf_path, O_RDONLY, 0);
+ 		if (fd == -1) {
+-			xlog_warn("conf_reinit: open (\"%s\", O_RDONLY) failed", conf_path);
+-			return;
++			xlog_warn("conf_reinit: open (\"%s\", O_RDONLY) failed", path);
++			return -1;
+ 		}
+ 
+ 		new_conf_addr = malloc(sz);
+@@ -396,39 +404,46 @@ conf_reinit(void)
+ 		/* XXX I assume short reads won't happen here.  */
+ 		if (read (fd, new_conf_addr, sz) != (int)sz) {
+ 			xlog_warn("conf_reinit: read (%d, %p, %lu) failed",
+-   				fd, new_conf_addr, (unsigned long)sz);
++				fd, new_conf_addr, (unsigned long)sz);
+ 			goto fail;
+ 		}
+ 		close(fd);
+ 
+-		trans = conf_begin();
+ 		/* XXX Should we not care about errors and rollback?  */
+ 		conf_parse(trans, new_conf_addr, sz);
++		free(new_conf_addr);
++		return 0;
++	fail:
++		close(fd);
++		free(new_conf_addr);
+ 	}
+-	else
+-		trans = conf_begin();
++	return -1;
++}
++
++/* Open the config file and map it into our address space, then parse it.  */
++void
++conf_reinit(void)
++{
++	struct conf_binding *cb = 0;
++	int trans;
++	unsigned int i;
++
++	trans = conf_begin();
++	if (conf_load(trans, conf_path) < 0)
++		return;
+ 
+ 	/* Load default configuration values.  */
+ 	conf_load_defaults();
+ 
+ 	/* Free potential existing configuration.  */
+-	if (conf_addr) {
+-		for (i = 0; i < sizeof conf_bindings / sizeof conf_bindings[0]; i++) {
+-			cb = LIST_FIRST (&conf_bindings[i]);
+-			for (; cb; cb = LIST_FIRST (&conf_bindings[i]))
+-				conf_remove_now(cb->section, cb->tag);
+-		}
+-		free (conf_addr);
++	for (i = 0; i < sizeof conf_bindings / sizeof conf_bindings[0]; i++) {
++		cb = LIST_FIRST (&conf_bindings[i]);
++		for (; cb; cb = LIST_FIRST (&conf_bindings[i]))
++			conf_remove_now(cb->section, cb->tag);
+ 	}
+ 
+ 	conf_end(trans, 1);
+-	conf_addr = new_conf_addr;
+ 	return;
+-
+-fail:
+-	if (new_conf_addr)
+-		free(new_conf_addr);
+-	close (fd);
+ }
+ 
+ /*
+@@ -446,6 +461,38 @@ conf_get_num(char *section, char *tag, i
+ 	return def;
+ }
+ 
++/*
++ * Return the Boolean value denoted by TAG in section SECTION, or DEF
++ * if that tags does not exist.
++ * FALSE is returned for case-insensitve comparisons with 0, f, false, n, no, off
++ * TRUE is returned for 1, t, true, y, yes, on
++ * A failure to match one of these results in DEF
++ */
++_Bool
++conf_get_bool(char *section, char *tag, _Bool def)
++{
++	char *value = conf_get_str(section, tag);
++
++	if (!value)
++		return def;
++	if (strcasecmp(value, "1") == 0 ||
++	    strcasecmp(value, "t") == 0 ||
++	    strcasecmp(value, "true") == 0 ||
++	    strcasecmp(value, "y") == 0 ||
++	    strcasecmp(value, "yes") == 0 ||
++	    strcasecmp(value, "on") == 0)
++		return true;
++
++	if (strcasecmp(value, "0") == 0 ||
++	    strcasecmp(value, "f") == 0 ||
++	    strcasecmp(value, "false") == 0 ||
++	    strcasecmp(value, "n") == 0 ||
++	    strcasecmp(value, "no") == 0 ||
++	    strcasecmp(value, "off") == 0)
++		return false;
++	return def;
++}
++
+ /* Validate X according to the range denoted by TAG in section SECTION.  */
+ int
+ conf_match_num(char *section, char *tag, int x)
+@@ -476,12 +523,24 @@ char *
+ conf_get_str(char *section, char *tag)
+ {
+ 	struct conf_binding *cb;
+-
++retry:
+ 	cb = LIST_FIRST (&conf_bindings[conf_hash (section)]);
+ 	for (; cb; cb = LIST_NEXT (cb, link)) {
+ 		if (strcasecmp (section, cb->section) == 0
+-				&& strcasecmp (tag, cb->tag) == 0)
++		    && strcasecmp (tag, cb->tag) == 0) {
++			if (cb->value[0] == '$') {
++				/* expand $name from [environment] section,
++				 * or from environment
++				 */
++				char *env = getenv(cb->value+1);
++				if (env && *env)
++					return env;
++				section = "environment";
++				tag = cb->value + 1;
++				goto retry;
++			}
+ 			return cb->value;
++		}
+ 	}
+ 	return 0;
+ }
+@@ -705,6 +764,8 @@ conf_set(int transaction, char *section,
+ {
+ 	struct conf_trans *node;
+ 
++	if (!value || !*value)
++		return 0;
+ 	node = conf_trans_node(transaction, CONF_SET);
+ 	if (!node)
+ 		return 1;
+diff -up nfs-utils-1.3.0/support/nfs/xlog.c.orig nfs-utils-1.3.0/support/nfs/xlog.c
+--- nfs-utils-1.3.0/support/nfs/xlog.c.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/support/nfs/xlog.c	2017-03-28 13:43:53.000000000 -0400
+@@ -29,6 +29,7 @@
+ #include <syslog.h>
+ #include <errno.h>
+ #include "nfslib.h"
++#include "conffile.h"
+ 
+ #undef	VERBOSE_PRINTF
+ 
+@@ -125,6 +126,19 @@ xlog_sconfig(char *kind, int on)
+ 	xlog_config(tbl->df_fac, on);
+ }
+ 
++void
++xlog_from_conffile(char *service)
++{
++	struct conf_list *kinds;
++	struct conf_list_node *n;
++
++	kinds = conf_get_list(service, "debug");
++	if (!kinds || !kinds->cnt)
++		return;
++	TAILQ_FOREACH(n, &(kinds->fields), link)
++		xlog_sconfig(n->field, 1);
++}
++
+ int
+ xlog_enabled(int fac)
+ {
+diff -up nfs-utils-1.3.0/systemd/Makefile.am.orig nfs-utils-1.3.0/systemd/Makefile.am
+--- nfs-utils-1.3.0/systemd/Makefile.am.orig	2017-03-28 13:43:36.000000000 -0400
++++ nfs-utils-1.3.0/systemd/Makefile.am	2017-03-28 13:43:53.000000000 -0400
+@@ -20,7 +20,9 @@ unit_files =  \
+     proc-fs-nfsd.mount \
+     var-lib-nfs-rpc_pipefs.mount
+ 
+-EXTRA_DIST = $(unit_files)
++man5_MANS	= nfs.conf.man
++man7_MANS	= nfs.systemd.man
++EXTRA_DIST = $(unit_files) $(man5_MANS) $(man7_MANS)
+ 
+ unit_dir = /usr/lib/systemd/system
+ 
+diff -up nfs-utils-1.3.0/systemd/nfs.conf.man.orig nfs-utils-1.3.0/systemd/nfs.conf.man
+--- nfs-utils-1.3.0/systemd/nfs.conf.man.orig	2017-03-28 13:43:53.000000000 -0400
++++ nfs-utils-1.3.0/systemd/nfs.conf.man	2017-03-28 13:43:53.000000000 -0400
+@@ -0,0 +1,231 @@
++.TH NFS.CONF 5
++.SH NAME
++nfs.conf \- general configuration for NFS daemons and tools
++.SH SYNOPSIS
++.I /etc/nfs.conf
++.SH DESCRIPTION
++.PP
++This file contains 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
++configuration across different processes.
++.PP
++When command line options are provided, they override values set in
++this file.  When this file does not specify a particular parameter,
++and no command line option is provided, each tool provides its own
++default values.
++.PP
++The file format supports multiple sections, each of which can contain
++multiple value assignments.  A section is introduced by a line
++containing the section name enclosed in square brackets, so
++.RS
++.B [global]
++.RE
++would introduce a section called
++.BR global .
++A value assignment is a single line that has the name of the value, an
++equals sign, and a setting for the value, so
++.RS
++.B threads = 4
++.RE
++would set the value named
++.B threads
++in the current section to
++.BR 4 .
++Leading and trailing spaces and tab
++are ignored, as are spaces and tabs surrounding the equals sign.
++Single and double quotes surrounding the assigned value are also
++removed.  If the resulting string is empty, the whole assignment
++is ignored.
++.PP
++Any line starting with
++.RB \*(lq # \*(rq
++or
++.RB \*(lq ; \*(rq
++is ignored, as is any blank line.
++.PP
++If the assigned value started with a
++.RB \*(lq $ \*(rq
++then the remainder is treated as a name and looked for in the section
++.B [environment]
++or in the processes environment (see
++.BR environ (7)).
++The value found is used for this value.
++.PP
++The value name
++.B include
++is special.  If a section contains
++.RS
++.B include = /some/file/name
++.RE
++then the named file will be read, and any value assignments found
++there-in will be added to the current section.  If the file contains
++section headers, then new sections will be created just as if the
++included file appeared in place of the
++.B include
++line.
++.PP
++Lookup of section and value names is case-insensitive.
++
++Where a Boolean value is expected, any of
++.BR true ,
++.BR t ,
++.BR yes ,
++.BR y ,
++.BR on ", or"
++.B 1
++can be used for "true", while
++.BR false ,
++.BR f ,
++.BR no ,
++.BR n ,
++.BR off ", or"
++.B 0
++can be used for "false".  Comparisons are case-insensitive.
++
++.SH SECTIONS
++The following sections are known to various programs, and can contain
++the given named values.  Most sections can also contain a
++.B debug
++value, which can be one or more from the list
++.BR general ,
++.BR call ,
++.BR auth ,
++.BR parse ,
++.BR all .
++When a list is given, the members should be comma-separated.
++.TP
++.B nfsdcltrack
++Recognized values:
++.BR storagedir .
++
++The
++.B nfsdcltrack
++program is run directly by the Linux kernel and there is no
++opportunity to provide command line arguments, so the configuration
++file is the only way to configure this program.  See
++.BR nfsdcltrack (8)
++for details.
++
++.TP
++.B nfsd
++Recognized values:
++.BR threads ,
++.BR host ,
++.BR port ,
++.BR grace-time ,
++.BR lease-time ,
++.BR udp ,
++.BR tcp ,
++.BR vers2 ,
++.BR vers3 ,
++.BR vers4 ,
++.BR vers4.0 ,
++.BR vers4.1 ,
++.BR vers4.2 ,
++.BR rdma .
++
++Version and protocol values are Boolean values as described above,
++and are also used by
++.BR rpc.mountd .
++Threads and the two times are integers.
++.B port
++and
++.B rdma
++are service names or numbers.  See
++.BR rpc.nfsd (8)
++for details.
++
++.TP
++.B mountd
++Recognized values:
++.BR manage-gids ,
++.BR descriptors ,
++.BR port ,
++.BR threads ,
++.BR reverse-lookup ,
++.BR state-directory-path ,
++.BR ha-callout .
++
++These, together with the protocol and version values in the
++.B [nfsd]
++section, are used to configure mountd.  See
++.BR rpc.mountd (8)
++for details.
++
++.TP
++.B statd
++Recognized values:
++.BR port ,
++.BR outgoing-port ,
++.BR name ,
++.BR state-directory-path ,
++.BR ha-callout .
++
++See
++.BR rpc.statd (8)
++for details.
++
++.TP
++.B lockd
++Recognized values:
++.B port
++and
++.BR udp-port .
++
++See
++.BR rpc.statd (8)
++for details.
++
++.TP
++.B sm-notify
++Recognized values:
++.BR retry-time ,
++.BR outgoing-port ", and"
++.BR outgoing-addr .
++
++See
++.BR sm-notify (8)
++for details.
++
++.TP
++.B gssd
++Recognized values:
++.BR use-memcache ,
++.BR use-machine-creds ,
++.BR avoid-dns ,
++.BR limit-to-legacy-enctypes ,
++.BR context-timeout ,
++.BR rpc-timeout ,
++.BR pipefs-directory ,
++.BR keytab-file ,
++.BR cred-cache-directory ,
++.BR preferred-realm .
++
++See
++.BR rpc.gssd (8)
++for details.
++
++.TP
++.B svcgssd
++Recognized values:
++.BR principal .
++
++See
++.BR rpc.svcgssd (8)
++for details.
++
++.TP
++.B exportfs
++Only
++.B debug=
++is recognized.
++
++.SH FILES
++.I /etc/nfs.conf
++.SH SEE ALSO
++.BR nfsdcltrack (8),
++.BR rpc.nfsd (8),
++.BR rpc.mountd (8),
++.BR nfsmount.conf (5).
+diff -up nfs-utils-1.3.0/systemd/nfs.systemd.man.orig nfs-utils-1.3.0/systemd/nfs.systemd.man
+--- nfs-utils-1.3.0/systemd/nfs.systemd.man.orig	2017-03-28 13:45:11.000000000 -0400
++++ nfs-utils-1.3.0/systemd/nfs.systemd.man	2017-03-28 13:45:11.000000000 -0400
+@@ -0,0 +1,167 @@
++.TH NFS.SYSTEMD 7
++.SH NAME
++nfs.systemd \- managing NFS services through systemd.
++.SH SYNOPSIS
++nfs-utils.service
++.br
++nfs-server.service
++.br
++nfs-client.target
++.br
++.I etc
++.SH DESCRIPTION
++The
++.I nfs-utils
++package provides a suite of
++.I systemd
++unit files which allow the various services to be started and
++managed.  These unit files ensure that the services are started in the
++correct order, and the prerequisites are active before dependant
++services start.  As there are quite  few unit files, it is not
++immediately obvious how best to achieve certain results.  The
++following subsections attempt to cover the issues that are most likely
++to come up.
++.SS Configuration
++The standard systemd unit files do not provide any easy way to pass
++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
++distribution might provide systemd "drop-in" files which replace the
++.B ExecStart=
++setting to start the program with different arguments.  For example a
++drop-in file
++.B systemd/system/nfs-mountd.service.d/local.conf
++containing
++.RS
++.nf
++[Service]
++EnvironmentFile=/etc/sysconfig/nfs
++ExecStart=
++ExecStart= /usr/sbin/rpc.mountd $RPCMOUNTDOPTS
++.fi
++.RE
++would cause the
++.B nfs-mountd.service
++unit to run the
++.I rpc.mountd
++program using, for arguments, the value given for
++.B RPCMOUNTDOPTS
++in
++.IR /etc/sysconfig/nfs .
++This allows for seamless integration with existing configuration
++tools.
++.SS Enabling unit files
++There are three unit files which are designed to be manually enabled.
++All others are automatically run as required.  The three are:
++.TP
++.B nfs-client.target
++This should be enabled on any host which ever serves as an NFS client.
++There is little cost in transparently enabling it whenever NFS client
++software is installed.
++.TP
++.B nfs-server.service
++This must be enabled to provide NFS service to clients.  It starts and
++configures the required daemons in the required order.
++.TP
++.B nfs-blkmap.service
++The
++.B blkmapd
++daemon is only required on NFS clients which are using pNFS (parallel
++NFS), and particularly using the
++.B blocklayout
++layout protocol.  If you might use this particular extension to NFS,
++the
++.B nfs-blkmap.service
++unit should be enabled.
++.PP
++Several other units which might be considered to be optional, such as
++.I rpc-gssd.service
++are careful to only start if the required configuration file exists.
++.I rpc-gsdd.service
++will not start if the
++.I krb5.keytab
++file does not exist (typically in
++.IR /etc ).
++.SS Restarting NFS services
++Most NFS daemons can be restarted at any time.  They will reload any
++state that they need, and continue servicing requests.  This is rarely
++necessary though.
++.PP
++When configuration changesare make, it can be hard to know exactly
++which services need to be restarted to ensure that the configuration
++takes effect.  The simplest approach, which is often the best, is to
++restart everything.  To help with this, the
++.B nfs-utils.service
++unit is provided.  It declares appropriate dependencies with other
++unit files so that
++.RS
++.B systemctl restart nfs-utils
++.RE
++will restart all NFS daemons that are running.  This will cause all
++configuration changes to take effect
++.I except
++for changes to mount options lists in
++.I /etc/fstab
++or
++.IR /etc/nfsmount.conf .
++Mount options can only be changed by unmounting and remounting
++filesystem.  This can be a disruptive operation so it should only be
++done when the value justifies the cost.  The command
++.RS
++.B umount -a -t nfs; mount -a -t nfs
++.RE
++should unmount and remount all NFS filesystems.
++.SS Masking unwanted services
++Rarely there may be a desire to prohibit some services from running
++even though there are normally part of a working NFS system.  This may
++be needed to reduce system load to an absolute minimum, or to reduce
++attack surface by not running daemons that are not absolutely
++required.
++.PP
++Two particular services which this can apply to are
++.I rpcbind
++and
++.IR idmapd .
++.I rpcbind
++is not part of the
++.I nfs-utils
++package, but it used by several NFS services.  However it is
++.B not
++needed when only NFSv4 is in use.  If a site will never use NFSv3 (or
++NFSv2) and does not want
++.I rpcbind
++to be running, the correct approach is to run
++.RS
++.B systemctl mask rpcbind
++.RE
++This will disable
++.IR rpcbind ,
++and the various NFS services which depend on it (and are only needed
++for NFSv3) will refuse to start, without interfering with the
++operation of NFSv4 services.  In particular,
++.I rpc.statd
++will not run when
++.I rpcbind
++is masked.
++.PP
++.I idmapd
++is only needed for NFSv4, and even then is not needed when the client
++and server agree to use user-ids rather than user-names to identify the
++owners of files.  If
++.I idmapd
++is not needed and not wanted, it can be masked with
++.RS
++.B systemctl mask idmapd
++.RE
++.SH FILES
++/etc/nfs.conf
++.br
++/etc/nfsmount.conf
++.br
++/etc/idmapd.conf
++.SH SEE ALSO
++.BR systemd.unit (5),
++.BR nfs.conf (5),
++.BR nfsmount.conf (5).
+diff -up nfs-utils-1.3.0/systemd/rpc-statd.service.orig nfs-utils-1.3.0/systemd/rpc-statd.service
+--- nfs-utils-1.3.0/systemd/rpc-statd.service.orig	2017-03-28 13:43:36.000000000 -0400
++++ nfs-utils-1.3.0/systemd/rpc-statd.service	2017-03-28 13:43:53.000000000 -0400
+@@ -11,7 +11,8 @@ Wants=nfs-config.service
+ After=nfs-config.service
+ 
+ [Service]
++Environment=RPC_STATD_NO_NOTIFY=1
+ EnvironmentFile=-/run/sysconfig/nfs-utils
+ Type=forking
+ PIDFile=/var/run/rpc.statd.pid
+-ExecStart=/usr/sbin/rpc.statd --no-notify $STATDARGS
++ExecStart=/usr/sbin/rpc.statd $STATDARGS
+diff -up nfs-utils-1.3.0/utils/exportfs/exportfs.c.orig nfs-utils-1.3.0/utils/exportfs/exportfs.c
+--- nfs-utils-1.3.0/utils/exportfs/exportfs.c.orig	2017-03-28 13:43:36.000000000 -0400
++++ nfs-utils-1.3.0/utils/exportfs/exportfs.c	2017-03-28 13:43:53.000000000 -0400
+@@ -37,6 +37,7 @@
+ #include "nfslib.h"
+ #include "exportfs.h"
+ #include "xlog.h"
++#include "conffile.h"
+ 
+ static void	export_all(int verbose);
+ static void	exportfs(char *arg, char *options, int verbose);
+@@ -53,6 +54,7 @@ static void release_lockfile(void);
+ 
+ static const char *lockfile = EXP_LOCKFILE;
+ static int _lockfd = -1;
++char *conf_path = NFS_CONFFILE;
+ 
+ /*
+  * If we aren't careful, changes made by exportfs can be lost
+@@ -108,6 +110,9 @@ main(int argc, char **argv)
+ 	xlog_stderr(1);
+ 	xlog_syslog(0);
+ 
++	conf_init();
++	xlog_from_conffile("exportfs");
++
+ 	while ((c = getopt(argc, argv, "ad:fhio:ruvs")) != EOF) {
+ 		switch(c) {
+ 		case 'a':
+diff -up nfs-utils-1.3.0/utils/exportfs/exportfs.man.orig nfs-utils-1.3.0/utils/exportfs/exportfs.man
+--- nfs-utils-1.3.0/utils/exportfs/exportfs.man.orig	2017-03-28 13:43:36.000000000 -0400
++++ nfs-utils-1.3.0/utils/exportfs/exportfs.man	2017-03-28 13:43:53.000000000 -0400
+@@ -90,6 +90,13 @@ to be added to the kernel's export table
+ .TP
+ .B \-d kind " or " \-\-debug kind
+ Turn on debugging. Valid kinds are: all, auth, call, general and parse.
++Debugging can also be turned on by setting
++.B debug=
++in the
++.B [exportfs]
++section of
++.IR /etc/nfs.conf .
++
+ .TP
+ .B -a
+ Export or unexport all directories.
+@@ -295,6 +302,7 @@ master table of exports
+ table of clients accessing server's exports
+ .SH SEE ALSO
+ .BR exports (5),
++.BR nfs.conf (5),
+ .BR rpc.mountd (8),
+ .BR netgroup (5)
+ .SH AUTHORS
+diff -up nfs-utils-1.3.0/utils/gssd/gssd.c.orig nfs-utils-1.3.0/utils/gssd/gssd.c
+--- nfs-utils-1.3.0/utils/gssd/gssd.c.orig	2017-03-28 13:43:36.000000000 -0400
++++ nfs-utils-1.3.0/utils/gssd/gssd.c	2017-03-28 13:43:53.000000000 -0400
+@@ -71,6 +71,7 @@
+ #include "gss_util.h"
+ #include "krb5_util.h"
+ #include "nfslib.h"
++#include "conffile.h"
+ 
+ static char *pipefs_path = GSSD_PIPEFS_DIR;
+ static DIR *pipefs_dir;
+@@ -78,6 +79,7 @@ static int pipefs_fd;
+ static int inotify_fd;
+ struct event inotify_ev;
+ 
++char *conf_path = NFS_CONFFILE;
+ char *keytabfile = GSSD_DEFAULT_KEYTAB_FILE;
+ char **ccachesearch;
+ int  use_memcache = 0;
+@@ -831,6 +833,33 @@ main(int argc, char *argv[])
+ 	char *progname;
+ 	char *ccachedir = NULL;
+ 	struct event sighup_ev;
++	char *s;
++
++	conf_init();
++	use_memcache = conf_get_bool("gssd", "use-memcache", use_memcache);
++	root_uses_machine_creds = conf_get_bool("gssd", "use-machine-creds",
++						root_uses_machine_creds);
++	avoid_dns = conf_get_bool("gssd", "avoid-dns", avoid_dns);
++#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
++	limit_to_legacy_enctypes = conf_get_bool("gssd", "limit-to-legacy-enctypes",
++						 limit_to_legacy_enctypes);
++#endif
++	context_timeout = conf_get_num("gssd", "context-timeout", context_timeout);
++	rpc_timeout = conf_get_num("gssd", "rpc-timeout", rpc_timeout);
++	s = conf_get_str("gssd", "pipefs-directory");
++	if (!s)
++		s = conf_get_str("general", "pipefs-directory");
++	if (s)
++		pipefs_path = s;
++	s = conf_get_str("gssd", "keytab-file");
++	if (s)
++		keytabfile = s;
++	s = conf_get_str("gssd", "cred-cache-directory");
++	if (s)
++		ccachedir = s;
++	s = conf_get_str("gssd", "preferred-realm");
++	if (s)
++		preferred_realm = s;
+ 
+ 	while ((opt = getopt(argc, argv, "DfvrlmnMp:k:d:t:T:R:")) != -1) {
+ 		switch (opt) {
+diff -up nfs-utils-1.3.0/utils/gssd/gssd.man.orig nfs-utils-1.3.0/utils/gssd/gssd.man
+--- nfs-utils-1.3.0/utils/gssd/gssd.man.orig	2017-03-28 13:43:36.000000000 -0400
++++ nfs-utils-1.3.0/utils/gssd/gssd.man	2017-03-28 13:43:53.000000000 -0400
+@@ -297,6 +297,60 @@ The default timeout is set to 5 seconds.
+ If you get messages like "WARNING: can't create tcp rpc_clnt to server
+ %servername% for user with uid %uid%: RPC: Remote system error -
+ Connection timed out", you should consider an increase of this timeout.
++.SH CONFIGURATION FILE
++Many of the options that can be set on the command line can also be
++controlled through values set in the
++.B [gssd]
++section of the
++.I /etc/nfs.conf
++configuration file.  Values recognized include:
++.TP
++.B use-memcache
++A Boolean flag equivalent to
++.BR -M .
++.TP
++.B use-machine-creds
++A Boolean flag. Setting to
++.B false
++is equivalent to giving the
++.B -n
++flag.
++.TP
++.B avoid-dns
++Setting to
++.B false
++is equivalent to providing the
++.B -D
++flag.
++.TP
++.B limit-to-legacy-enctypes
++Equivalent to
++.BR -l .
++.TP
++.B context-timeout
++Equivalent to
++.BR -T .
++.TP
++.B rpc-timeout
++Equivalent to
++.BR -t .
++.TP
++.B pipefs-directory
++Equivalent to
++.BR -p .
++.TP
++.B keytab-file
++Equivalent to
++.BR -k .
++.TP
++.BR cred-cache-directory
++Equivalent to
++.BR -d .
++.TP
++.B preferred-realm
++Equivalent to
++.BR -R .
++
+ .SH SEE ALSO
+ .BR rpc.svcgssd (8),
+ .BR kerberos (1),
+diff -up nfs-utils-1.3.0/utils/gssd/svcgssd.c.orig nfs-utils-1.3.0/utils/gssd/svcgssd.c
+--- nfs-utils-1.3.0/utils/gssd/svcgssd.c.orig	2017-03-28 13:43:36.000000000 -0400
++++ nfs-utils-1.3.0/utils/gssd/svcgssd.c	2017-03-28 13:43:53.000000000 -0400
+@@ -61,6 +61,9 @@
+ #include "svcgssd.h"
+ #include "gss_util.h"
+ #include "err_util.h"
++#include "conffile.h"
++
++char *conf_path = NFS_CONFFILE;
+ 
+ void
+ sig_die(int signal)
+@@ -98,6 +101,17 @@ main(int argc, char *argv[])
+ 	extern char *optarg;
+ 	char *progname;
+ 	char *principal = NULL;
++	char *s;
++
++	conf_init();
++
++	s = conf_get_str("svcgssd", "principal");
++	if (!s)
++		;
++	else if (strcmp(s, "system")== 0)
++		get_creds = 0;
++	else
++		principal = s;
+ 
+ 	while ((opt = getopt(argc, argv, "fivrnp:")) != -1) {
+ 		switch (opt) {
+diff -up nfs-utils-1.3.0/utils/gssd/svcgssd.man.orig nfs-utils-1.3.0/utils/gssd/svcgssd.man
+--- nfs-utils-1.3.0/utils/gssd/svcgssd.man.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/utils/gssd/svcgssd.man	2017-03-28 13:43:53.000000000 -0400
+@@ -45,6 +45,23 @@ Use the system default credentials
+ .RI (host/ FQDN @ REALM )
+ rather than the default
+ .RI nfs/ FQDN @ REALM .
++.SH CONFIGURATION FILE
++Some of the options that can be set on the command line can also be
++controlled through values set in the
++.B [svcgssd]
++section of the
++.I /etc/nfs.conf
++configuration file.  Values recognized include:
++.TP
++.B principal
++If set to
++.B system
++this is equivalent to the
++.B -n
++option.  If set to any other value, that is used like the
++.B -p
++option.
++
+ .SH SEE ALSO
+ .BR rpc.gssd(8),
+ .SH AUTHORS
+diff -up nfs-utils-1.3.0/utils/mountd/mountd.c.orig nfs-utils-1.3.0/utils/mountd/mountd.c
+--- nfs-utils-1.3.0/utils/mountd/mountd.c.orig	2017-03-28 13:43:36.000000000 -0400
++++ nfs-utils-1.3.0/utils/mountd/mountd.c	2017-03-28 13:43:53.000000000 -0400
+@@ -22,6 +22,8 @@
+ #include <fcntl.h>
+ #include <sys/resource.h>
+ #include <sys/wait.h>
++
++#include "conffile.h"
+ #include "xmalloc.h"
+ #include "misc.h"
+ #include "mountd.h"
+@@ -39,6 +41,8 @@ int new_cache = 0;
+ int manage_gids;
+ int use_ipaddr = -1;
+ 
++char *conf_path = NFS_CONFFILE;
++
+ /* PRC: a high-availability callout program can be specified with -H
+  * When this is done, the program will receive callouts whenever clients
+  * send mount or unmount requests -- the callout is not needed for 2.6 kernel */
+@@ -692,6 +696,7 @@ main(int argc, char **argv)
+ 	char	*export_file = _PATH_EXPORTS;
+ 	char    *state_dir = NFS_STATEDIR;
+ 	char	*progname;
++	char	*s;
+ 	unsigned int listeners = 0;
+ 	int	foreground = 0;
+ 	int	port = 0;
+@@ -707,6 +712,38 @@ main(int argc, char **argv)
+ 	else
+ 		progname = argv[0];
+ 
++	conf_init();
++	xlog_from_conffile("mountd");
++	manage_gids = conf_get_bool("mountd", "manage-gids", manage_gids);
++	descriptors = conf_get_num("mountd", "descriptors", descriptors);
++	port = conf_get_num("mountd", "port", port);
++	num_threads = conf_get_num("mountd", "threads", num_threads);
++	reverse_resolve = conf_get_bool("mountd", "reverse-lookup", reverse_resolve);
++	ha_callout_prog = conf_get_str("mountd", "ha-callout");
++
++	s = conf_get_str("mountd", "state-directory-path");
++	if (s)
++		state_dir = s;
++
++	/* NOTE: following uses "nfsd" section of nfs.conf !!!! */
++	if (conf_get_bool("nfsd", "udp", NFSCTL_UDPISSET(_rpcprotobits)))
++		NFSCTL_UDPSET(_rpcprotobits);
++	else
++		NFSCTL_UDPUNSET(_rpcprotobits);
++	if (conf_get_bool("nfsd", "tcp", NFSCTL_TCPISSET(_rpcprotobits)))
++		NFSCTL_TCPSET(_rpcprotobits);
++	else
++		NFSCTL_TCPUNSET(_rpcprotobits);
++	for (vers = 2; vers <= 4; vers++) {
++		char tag[10];
++		sprintf(tag, "vers%d", vers);
++		if (conf_get_bool("nfsd", tag, NFSCTL_VERISSET(nfs_version, vers)))
++			NFSCTL_VERSET(nfs_version, vers);
++		else
++			NFSCTL_VERUNSET(nfs_version, vers);
++	}
++
++
+ 	/* Parse the command line options and arguments. */
+ 	opterr = 0;
+ 	while ((c = getopt_long(argc, argv, "o:nFd:f:p:P:hH:N:V:vurs:t:g", longopts, NULL)) != EOF)
+diff -up nfs-utils-1.3.0/utils/mountd/mountd.man.orig nfs-utils-1.3.0/utils/mountd/mountd.man
+--- nfs-utils-1.3.0/utils/mountd/mountd.man.orig	2017-03-28 13:43:36.000000000 -0400
++++ nfs-utils-1.3.0/utils/mountd/mountd.man	2017-03-28 13:43:53.000000000 -0400
+@@ -207,6 +207,39 @@ the server. Note that the 'primary' grou
+ .B newgroup
+ command on the client will still be effective.  This function requires
+ a Linux Kernel with version at least 2.6.21.
++
++.SH CONFIGURATION FILE
++Many of the options that can be set on the command line can also be
++controlled through values set in the
++.B [mountd]
++or, in some cases, the
++.B [nfsd]
++sections of the
++.I /etc/nfs.conf
++configuration file.
++Values recognized in the
++.B [mountd]
++section include
++.BR manage-gids ,
++.BR descriptors ,
++.BR port ,
++.BR threads ,
++.BR reverse-lookup ", and"
++.BR state-directory-path ,
++.B ha-callout
++which each have the same effect as the option with the same name.
++
++The values recognized in the
++.B [nfsd]
++section include
++.BR TCP ,
++.BR UDP ,
++.BR vers2 ,
++.BR vers3 ", and"
++.B vers4
++which each have same same meaning as given by
++.BR rpc.nfsd (8).
++
+ .SH TCP_WRAPPERS SUPPORT
+ You can protect your
+ .B rpc.mountd
+@@ -261,6 +294,7 @@ table of clients accessing server's expo
+ .BR rpc.nfsd (8),
+ .BR rpc.rquotad (8),
+ .BR nfs (5),
++.BR nfs.conf (5),
+ .BR tcpd (8),
+ .BR hosts_access (5),
+ .BR iptables (8),
+diff -up nfs-utils-1.3.0/utils/nfsdcltrack/nfsdcltrack.c.orig nfs-utils-1.3.0/utils/nfsdcltrack/nfsdcltrack.c
+--- nfs-utils-1.3.0/utils/nfsdcltrack/nfsdcltrack.c.orig	2017-03-28 13:43:36.000000000 -0400
++++ nfs-utils-1.3.0/utils/nfsdcltrack/nfsdcltrack.c	2017-03-28 13:43:53.000000000 -0400
+@@ -43,6 +43,7 @@
+ #include <sys/capability.h>
+ #endif
+ 
++#include "conffile.h"
+ #include "xlog.h"
+ #include "sqlite.h"
+ 
+@@ -55,6 +56,8 @@
+ /* defined by RFC 3530 */
+ #define NFS4_OPAQUE_LIMIT	1024
+ 
++char *conf_path = NFS_CONFFILE;
++
+ /* private data structures */
+ struct cltrack_cmd {
+ 	char *name;
+@@ -553,6 +556,7 @@ int
+ main(int argc, char **argv)
+ {
+ 	char arg;
++	char *val;
+ 	int rc = 0;
+ 	char *progname, *cmdarg = NULL;
+ 	struct cltrack_cmd *cmd;
+@@ -562,6 +566,15 @@ main(int argc, char **argv)
+ 	xlog_syslog(1);
+ 	xlog_stderr(0);
+ 
++	conf_init();
++	xlog_from_conffile("nfsdcltrack");
++	val = conf_get_str("nfsdcltrack", "storagedir");
++	if (val)
++		storagedir = val;
++	rc = conf_get_num("nfsdcltrack", "debug", 0);
++	if (rc > 0)
++		xlog_config(D_ALL, 1);
++
+ 	/* process command-line options */
+ 	while ((arg = getopt_long(argc, argv, "hdfs:", longopts,
+ 				  NULL)) != EOF) {
+diff -up nfs-utils-1.3.0/utils/nfsdcltrack/nfsdcltrack.man.orig nfs-utils-1.3.0/utils/nfsdcltrack/nfsdcltrack.man
+--- nfs-utils-1.3.0/utils/nfsdcltrack/nfsdcltrack.man.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/utils/nfsdcltrack/nfsdcltrack.man	2017-03-28 13:43:53.000000000 -0400
+@@ -66,6 +66,20 @@ Check to see if a nfs_client_id4 is allo
+ .IP "\fBgracedone\fR" 4
+ .IX Item "gracedone"
+ Remove any unreclaimed client records from the database. This command requires a epoch boot time as an argument.
++.SH "EXTERNAL CONFIGURATION"
++The directory for stable storage information can be set via the file
++.B /etc/nfs.conf
++by setting the
++.B storagedir
++value in the
++.B nfsdcltrack
++section.  For example:
++.in +5
++[nfsdcltrack]
++.br
++  storagedir = /shared/nfs/nfsdcltrack
++.in -5
++Debuging 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 -up nfs-utils-1.3.0/utils/nfsd/nfsd.c.orig nfs-utils-1.3.0/utils/nfsd/nfsd.c
+--- nfs-utils-1.3.0/utils/nfsd/nfsd.c.orig	2017-03-28 13:43:36.000000000 -0400
++++ nfs-utils-1.3.0/utils/nfsd/nfsd.c	2017-03-28 13:43:53.000000000 -0400
+@@ -23,14 +23,18 @@
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+ 
++#include "conffile.h"
+ #include "nfslib.h"
+ #include "nfssvc.h"
+ #include "xlog.h"
++#include "xcommon.h"
+ 
+ #ifndef NFSD_NPROC
+ #define NFSD_NPROC 8
+ #endif
+ 
++char *conf_path = NFS_CONFFILE;
++
+ static void	usage(const char *);
+ 
+ static struct option longopts[] =
+@@ -51,50 +55,6 @@ static struct option longopts[] =
+ 	{ NULL, 0, 0, 0 }
+ };
+ 
+-/* given a family and ctlbits, disable any that aren't listed in netconfig */
+-#ifdef HAVE_LIBTIRPC
+-static void
+-nfsd_enable_protos(unsigned int *proto4, unsigned int *proto6)
+-{
+-	struct netconfig *nconf;
+-	unsigned int *famproto;
+-	void *handle;
+-
+-	xlog(D_GENERAL, "Checking netconfig for visible protocols.");
+-
+-	handle = setnetconfig();
+-	while((nconf = getnetconfig(handle))) {
+-		if (!(nconf->nc_flag & NC_VISIBLE))
+-			continue;
+-
+-		if (!strcmp(nconf->nc_protofmly, NC_INET))
+-			famproto = proto4;
+-		else if (!strcmp(nconf->nc_protofmly, NC_INET6))
+-			famproto = proto6;
+-		else
+-			continue;
+-
+-		if (!strcmp(nconf->nc_proto, NC_TCP))
+-			NFSCTL_TCPSET(*famproto);
+-		else if (!strcmp(nconf->nc_proto, NC_UDP))
+-			NFSCTL_UDPSET(*famproto);
+-
+-		xlog(D_GENERAL, "Enabling %s %s.", nconf->nc_protofmly,
+-			nconf->nc_proto);
+-	}
+-	endnetconfig(handle);
+-	return;
+-}
+-#else /* HAVE_LIBTIRPC */
+-static void
+-nfsd_enable_protos(unsigned int *proto4, unsigned int *proto6)
+-{
+-	/* Enable all IPv4 protocols if no TIRPC support */
+-	*proto4 = NFSCTL_ALLBITS;
+-	*proto6 = 0;
+-}
+-#endif /* HAVE_LIBTIRPC */
+-
+ int
+ main(int argc, char **argv)
+ {
+@@ -102,44 +62,91 @@ main(int argc, char **argv)
+ 	char *p, *progname, *port, *rdma_port = NULL;
+ 	char **haddr = NULL;
+ 	int hcounter = 0;
++	struct conf_list *hosts;
+ 	int	socket_up = 0;
+ 	unsigned int minorvers = 0;
+ 	unsigned int minorversset = 0;
+ 	unsigned int versbits = NFSCTL_VERDEFAULT;
+ 	unsigned int protobits = NFSCTL_ALLBITS;
+-	unsigned int proto4 = 0;
+-	unsigned int proto6 = 0;
+ 	int grace = -1;
+ 	int lease = -1;
+ 
+-	progname = strdup(basename(argv[0]));
+-	if (!progname) {
+-		fprintf(stderr, "%s: unable to allocate memory.\n", argv[0]);
+-		exit(1);
+-	}
+-
+-	port = strdup("nfs");
+-	if (!port) {
+-		fprintf(stderr, "%s: unable to allocate memory.\n", progname);
+-		exit(1);
+-	}
+-
+-	haddr = malloc(sizeof(char *));
+-	if (!haddr) {
+-		fprintf(stderr, "%s: unable to allocate memory.\n", progname);
+-		exit(1);
+-	}
++	progname = basename(argv[0]);
++	haddr = xmalloc(sizeof(char *));
+ 	haddr[0] = NULL;
+ 
+ 	xlog_syslog(0);
+ 	xlog_stderr(1);
+ 
++	conf_init();
++	xlog_from_conffile("nfsd");
++	count = conf_get_num("nfsd", "threads", count);
++	grace = conf_get_num("nfsd", "grace-time", grace);
++	lease = conf_get_num("nfsd", "lease-time", lease);
++	port = conf_get_str("nfsd", "port");
++	if (!port)
++		port = "nfs";
++	rdma_port = conf_get_str("nfsd", "rdma");
++	if (conf_get_bool("nfsd", "udp", NFSCTL_UDPISSET(protobits)))
++		NFSCTL_UDPSET(protobits);
++	else
++		NFSCTL_UDPUNSET(protobits);
++	if (conf_get_bool("nfsd", "tcp", NFSCTL_TCPISSET(protobits)))
++		NFSCTL_TCPSET(protobits);
++	else
++		NFSCTL_TCPUNSET(protobits);
++	for (i = 2; i <= 4; i++) {
++		char tag[10];
++		sprintf(tag, "vers%d", i);
++		if (conf_get_bool("nfsd", tag, NFSCTL_VERISSET(versbits, i)))
++			NFSCTL_VERSET(versbits, i);
++		else
++			NFSCTL_VERUNSET(versbits, i);
++	}
++	/* We assume the kernel will default all minor versions to 'on',
++	 * and allow the config file to disable some.
++	 */
++	for (i = NFS4_MINMINOR; i <= NFS4_MAXMINOR; i++) {
++		char tag[20];
++		sprintf(tag, "vers4.%d", i);
++		/* The default for minor version support is to let the
++		 * kernel decide.  We could ask the kernel what that choice
++		 * will be, but that is needlessly complex.
++		 * Instead, perform a config-file lookup using each of the
++		 * two possible default.  If the result is different from the
++		 * default, then impose that value, else don't make a change
++		 * (i.e. don't set the bit in minorversset).
++		 */
++		if (!conf_get_bool("nfsd", tag, 1)) {
++			NFSCTL_VERSET(minorversset, i);
++			NFSCTL_VERUNSET(minorvers, i);
++		}
++		if (conf_get_bool("nfsd", tag, 0)) {
++			NFSCTL_VERSET(minorversset, i);
++			NFSCTL_VERSET(minorvers, i);
++		}
++	}
++
++	hosts = conf_get_list("nfsd", "host");
++	if (hosts && hosts->cnt) {
++		struct conf_list_node *n;
++		haddr = realloc(haddr, sizeof(char*) * hosts->cnt);
++		TAILQ_FOREACH(n, &(hosts->fields), link) {
++			haddr[hcounter] = n->field;
++			hcounter++;
++		}
++	}
++
+ 	while ((c = getopt_long(argc, argv, "dH:hN:V:p:P:sTUrG:L:", longopts, NULL)) != EOF) {
+ 		switch(c) {
+ 		case 'd':
+ 			xlog_config(D_ALL, 1);
+ 			break;
+ 		case 'H':
++			if (hosts) {
++				hosts = NULL;
++				hcounter = 0;
++			}
+ 			if (hcounter) {
+ 				haddr = realloc(haddr, sizeof(char*) * hcounter+1);
+ 				if(!haddr) {
+@@ -148,30 +155,13 @@ main(int argc, char **argv)
+ 					exit(1);
+ 				}
+ 			}
+-			haddr[hcounter] = strdup(optarg);
+-			if (!haddr[hcounter]) {
+-				fprintf(stderr, "%s: unable to allocate "
+-					"memory.\n", progname);
+-				exit(1);
+-			}
++			haddr[hcounter] = optarg;
+ 			hcounter++;
+ 			break;
+ 		case 'P':	/* XXX for nfs-server compatibility */
+ 		case 'p':
+ 			/* only the last -p option has any effect */
+-			portnum = atoi(optarg);
+-			if (portnum <= 0 || portnum > 65535) {
+-				fprintf(stderr, "%s: bad port number: %s\n",
+-					progname, optarg);
+-				usage(progname);
+-			}
+-			free(port);
+-			port = strdup(optarg);
+-			if (!port) {
+-				fprintf(stderr, "%s: unable to allocate "
+-						"memory.\n", progname);
+-				exit(1);
+-			}
++			port = optarg;
+ 			break;
+ 		case 'r':
+ 			rdma_port = "nfsrdma";
+@@ -188,7 +178,7 @@ main(int argc, char **argv)
+ 			case 4:
+ 				if (*p == '.') {
+ 					int i = atoi(p+1);
+-					if (i > NFS4_MAXMINOR) {
++					if (i < NFS4_MINMINOR || i > NFS4_MAXMINOR) {
+ 						fprintf(stderr, "%s: unsupported minor version\n", optarg);
+ 						exit(1);
+ 					}
+@@ -210,7 +200,7 @@ main(int argc, char **argv)
+ 			case 4:
+ 				if (*p == '.') {
+ 					int i = atoi(p+1);
+-					if (i > NFS4_MAXMINOR) {
++					if (i < NFS4_MINMINOR || i > NFS4_MAXMINOR) {
+ 						fprintf(stderr, "%s: unsupported minor version\n", optarg);
+ 						exit(1);
+ 					}
+@@ -277,18 +267,6 @@ main(int argc, char **argv)
+ 
+ 	xlog_open(progname);
+ 
+-	nfsd_enable_protos(&proto4, &proto6);
+-
+-	if (!NFSCTL_TCPISSET(protobits)) {
+-		NFSCTL_TCPUNSET(proto4);
+-		NFSCTL_TCPUNSET(proto6);
+-	}
+-
+-	if (!NFSCTL_UDPISSET(protobits)) {
+-		NFSCTL_UDPUNSET(proto4);
+-		NFSCTL_UDPUNSET(proto6);
+-	}
+-
+ 	/* make sure that at least one version is enabled */
+ 	found_one = 0;
+ 	for (c = NFSD_MINVERS; c <= NFSD_MAXVERS; c++) {
+@@ -301,8 +279,7 @@ main(int argc, char **argv)
+ 	}
+ 
+ 	if (NFSCTL_VERISSET(versbits, 4) &&
+-	    !NFSCTL_TCPISSET(proto4) &&
+-	    !NFSCTL_TCPISSET(proto6)) {
++	    !NFSCTL_TCPISSET(protobits)) {
+ 		xlog(L_ERROR, "version 4 requires the TCP protocol");
+ 		exit(1);
+ 	}
+@@ -336,15 +313,10 @@ main(int argc, char **argv)
+ 
+ 	i = 0;
+ 	do {
+-		error = nfssvc_set_sockets(AF_INET, proto4, haddr[i], port);
+-		if (!error)
+-			socket_up = 1;
+-#ifdef IPV6_SUPPORTED
+-		error = nfssvc_set_sockets(AF_INET6, proto6, haddr[i], port);
++		error = nfssvc_set_sockets(protobits, haddr[i], port);
+ 		if (!error)
+ 			socket_up = 1;
+-#endif /* IPV6_SUPPORTED */
+-	} while (++i < hcounter); 
++	} while (++i < hcounter);
+ 
+ 	if (rdma_port) {
+ 		error = nfssvc_set_rdmaport(rdma_port);
+@@ -381,11 +353,7 @@ set_threads:
+ 	if ((error = nfssvc_threads(portnum, count)) < 0)
+ 		xlog(L_ERROR, "error starting threads: errno %d (%m)", errno);
+ out:
+-	free(port);
+-	for(i=0; i < hcounter; i++)
+-		free(haddr[i]);
+ 	free(haddr);
+-	free(progname);
+ 	return (error != 0);
+ }
+ 
+diff -up nfs-utils-1.3.0/utils/nfsd/nfsd.man.orig nfs-utils-1.3.0/utils/nfsd/nfsd.man
+--- nfs-utils-1.3.0/utils/nfsd/nfsd.man.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/utils/nfsd/nfsd.man	2017-03-28 13:43:53.000000000 -0400
+@@ -57,7 +57,7 @@ This option can be used to request that
+ .B rpc.nfsd
+ does not offer certain versions of NFS. The current version of
+ .B rpc.nfsd
+-can support NFS versions 2,3,4 and the newer version 4.1.
++can support major NFS versions 2,3,4 and the minor versions 4.1 and 4.2.
+ .TP
+ .B \-s " or " \-\-syslog
+ By default,
+@@ -82,7 +82,7 @@ This option can be used to request that
+ .B rpc.nfsd
+ offer certain versions of NFS. The current version of
+ .B rpc.nfsd
+-can support NFS versions 2,3,4 and the newer version 4.1.
++can support major NFS versions 2,3,4 and the minor versions 4.1 and 4.2.
+ .TP
+ .B \-L " or " \-\-lease-time seconds
+ Set the lease-time used for NFSv4.  This corresponds to how often
+@@ -95,11 +95,11 @@ New file open requests (NFSv4) and new f
+ allowed until after this time has passed to allow clients to recover state.
+ .TP
+ .I nproc
+-specify the number of NFS server threads. By default, just one
+-thread is started. However, for optimum performance several threads
++specify the number of NFS server threads. By default, eight
++threads are started. However, for optimum performance several threads
+ should be used. The actual figure depends on the number of and the work
+ load created by the NFS clients, but a useful starting point is
+-8 threads. Effects of modifying that number can be checked using
++eight threads. Effects of modifying that number can be checked using
+ the
+ .BR nfsstat (8)
+ program.
+@@ -114,6 +114,58 @@ In particular
+ .B rpc.nfsd 0
+ will stop all threads and thus close any open connections.
+ 
++.SH CONFIGURATION FILE
++Many of the options that can be set on the command line can also be
++controlled through values set in the
++.B [nfsd]
++section of the
++.I /etc/nfs.conf
++configuration file.  Values recognized include:
++.TP
++.B threads
++The number of threads to start.
++.TP
++.B host
++A host name, or comma separated list of host names, that
++.I rpc.nfsd
++will listen on.  Use of the
++.B --host
++option replaces all host names listed here.
++.TP
++.B grace-time
++The grace time, for both NFSv4 and NLM, in seconds.
++.TP
++.B lease-time
++The lease time for NFSv4, in seconds.
++.TP
++.B port
++Set the port for TCP/UDP to bind to.
++.TP
++.B rdma
++Set RDMA port.  Use "rdma=nfsrdma" to enable standard port.
++.TP
++.B UDP
++Enable (with "on" or "yes" etc) or disable ("off", "no") UDP support.
++.TP
++.B TCP
++Enable or disable TCP support.
++.TP
++.B vers2
++.TP
++.B vers3
++.TP
++.B vers4
++Enable or disable a major NFS version.  3 and 4 are normally enabled
++by default.
++.TP
++.B vers4.1
++.TP
++.B vers4.2
++Setting these to "off" or similar will disable the selected minor
++versions.  Setting to "on" will enable them.  The default values
++are determined by the kernel, and usually minor versions default to
++being enabled once the implementation is sufficiently complete.
++
+ .SH NOTES
+ If the program is built with TI-RPC support, it will enable any protocol and
+ address family combinations that are marked visible in the
+@@ -124,6 +176,7 @@ database.
+ .BR rpc.mountd (8),
+ .BR exports (5),
+ .BR exportfs (8),
++.BR nfs.conf (5),
+ .BR rpc.rquotad (8),
+ .BR nfsstat (8),
+ .BR netconfig(5).
+diff -up nfs-utils-1.3.0/utils/nfsd/nfssvc.c.orig nfs-utils-1.3.0/utils/nfsd/nfssvc.c
+--- nfs-utils-1.3.0/utils/nfsd/nfssvc.c.orig	2017-03-28 13:43:36.000000000 -0400
++++ nfs-utils-1.3.0/utils/nfsd/nfssvc.c	2017-03-28 13:43:53.000000000 -0400
+@@ -23,6 +23,7 @@
+ 
+ #include "nfslib.h"
+ #include "xlog.h"
++#include "nfssvc.h"
+ 
+ #ifndef NFSD_FS_DIR
+ #define NFSD_FS_DIR	  "/proc/fs/nfsd"
+@@ -123,22 +124,6 @@ nfssvc_setfds(const struct addrinfo *hin
+ 	if (fd < 0)
+ 		return 0;
+ 
+-	switch(hints->ai_family) {
+-	case AF_INET:
+-		family = "inet";
+-		break;
+-#ifdef IPV6_SUPPORTED
+-	case AF_INET6:
+-		family = "inet6";
+-		break;
+-#endif /* IPV6_SUPPORTED */
+-	default:
+-		xlog(L_ERROR, "Unknown address family specified: %d\n",
+-				hints->ai_family);
+-		rc = EAFNOSUPPORT;
+-		goto error;
+-	}
+-
+ 	rc = getaddrinfo(node, port, hints, &addrhead);
+ 	if (rc == EAI_NONAME && !strcmp(port, "nfs")) {
+ 		snprintf(buf, sizeof(buf), "%d", NFS_PORT);
+@@ -146,10 +131,10 @@ nfssvc_setfds(const struct addrinfo *hin
+ 	}
+ 
+ 	if (rc != 0) {
+-		xlog(L_ERROR, "unable to resolve %s:%s to %s address: "
+-				"%s", node ? node : "ANYADDR", port, family,
+-				rc == EAI_SYSTEM ? strerror(errno) :
+-					gai_strerror(rc));
++		xlog(L_ERROR, "unable to resolve %s:%s: %s",
++			node ? node : "ANYADDR", port,
++			rc == EAI_SYSTEM ? strerror(errno) :
++				gai_strerror(rc));
+ 		goto error;
+ 	}
+ 
+@@ -168,6 +153,20 @@ nfssvc_setfds(const struct addrinfo *hin
+ 			continue;
+ 		}
+ 
++		switch(addr->ai_addr->sa_family) {
++		case AF_INET:
++			family = "AF_INET";
++			break;
++#ifdef IPV6_SUPPORTED
++		case AF_INET6:
++			family = "AF_INET6";
++			break;
++#endif /* IPV6_SUPPORTED */
++		default:
++			addr = addr->ai_next;
++			continue;
++		}
++
+ 		xlog(D_GENERAL, "Creating %s %s socket.", family, proto);
+ 
+ 		/* open socket and prepare to hand it off to kernel */
+@@ -251,12 +250,16 @@ error:
+ }
+ 
+ int
+-nfssvc_set_sockets(const int family, const unsigned int protobits,
++nfssvc_set_sockets(const unsigned int protobits,
+ 		   const char *host, const char *port)
+ {
+ 	struct addrinfo hints = { .ai_flags = AI_PASSIVE };
+ 
+-	hints.ai_family = family;
++#ifdef IPV6_SUPPORTED
++	hints.ai_family = AF_UNSPEC;
++#else  /* IPV6_SUPPORTED */
++	hints.ai_family = AF_INET;
++#endif /* IPV6_SUPPORTED */
+ 
+ 	if (!NFSCTL_ANYPROTO(protobits))
+ 		return EPROTOTYPE;
+diff -up nfs-utils-1.3.0/utils/nfsd/nfssvc.h.orig nfs-utils-1.3.0/utils/nfsd/nfssvc.h
+--- nfs-utils-1.3.0/utils/nfsd/nfssvc.h.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/utils/nfsd/nfssvc.h	2017-03-28 13:43:53.000000000 -0400
+@@ -22,7 +22,7 @@
+ 
+ void	nfssvc_mount_nfsdfs(char *progname);
+ int	nfssvc_inuse(void);
+-int	nfssvc_set_sockets(const int family, const unsigned int protobits,
++int	nfssvc_set_sockets(const unsigned int protobits,
+ 			   const char *host, const char *port);
+ void	nfssvc_set_time(const char *type, const int seconds);
+ int	nfssvc_set_rdmaport(const char *port);
+diff -up nfs-utils-1.3.0/utils/statd/sm-notify.c.orig nfs-utils-1.3.0/utils/statd/sm-notify.c
+--- nfs-utils-1.3.0/utils/statd/sm-notify.c.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/utils/statd/sm-notify.c	2017-03-28 13:43:53.000000000 -0400
+@@ -29,6 +29,7 @@
+ #include <errno.h>
+ #include <grp.h>
+ 
++#include "conffile.h"
+ #include "sockaddr.h"
+ #include "xlog.h"
+ #include "nsm.h"
+@@ -64,6 +65,7 @@ static _Bool		opt_update_state = true;
+ static unsigned int	opt_max_retry = 15 * 60;
+ static char *		opt_srcaddr = NULL;
+ static char *		opt_srcport = NULL;
++char *			conf_path = NFS_CONFFILE;
+ 
+ static void		notify(const int sock);
+ static int		notify_host(int, struct nsm_host *);
+@@ -455,6 +457,7 @@ main(int argc, char **argv)
+ {
+ 	int	c, sock, force = 0;
+ 	char *	progname;
++	char *	s;
+ 
+ 	progname = strrchr(argv[0], '/');
+ 	if (progname != NULL)
+@@ -462,6 +465,15 @@ main(int argc, char **argv)
+ 	else
+ 		progname = argv[0];
+ 
++	conf_init();
++	xlog_from_conffile("sm-notify");
++	opt_max_retry = conf_get_num("sm-notify", "retry-time", opt_max_retry / 60) * 60;
++	opt_srcport = conf_get_str("sm-notify", "outgoing-port");
++	opt_srcaddr = conf_get_str("sm-notify", "outgoing-addr");
++	s = conf_get_str("statd", "state-directory-path");
++	if (s && !nsm_setup_pathnames(argv[0], s))
++		exit(1);
++
+ 	while ((c = getopt(argc, argv, "dm:np:v:P:f")) != -1) {
+ 		switch (c) {
+ 		case 'f':
+diff -up nfs-utils-1.3.0/utils/statd/sm-notify.man.orig nfs-utils-1.3.0/utils/statd/sm-notify.man
+--- nfs-utils-1.3.0/utils/statd/sm-notify.man.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/utils/statd/sm-notify.man	2017-03-28 13:43:53.000000000 -0400
+@@ -219,6 +219,33 @@ argument when sending SM_NOTIFY requests
+ .IP
+ This option can be useful in multi-homed configurations where
+ the remote requires notification from a specific network address.
++.SH CONFIGURATION FILE
++Many of the options that can be set on the command line can also be
++controlled through values set in the
++.B [sm-notify]
++or, in one case, the
++.B [statd]
++section of the
++.I /etc/nfs.conf
++configuration file.
++
++Values recognized in the
++.B [sm-notify]
++section include:
++.BR retry-time ,
++.BR outgoing-port ", and"
++.BR outgoing-addr .
++These have the same effect as the command line options
++.BR m ,
++.BR p ", and"
++.B v
++respectively.
++
++The value recognized in the
++.B [statd]
++section is
++.BR state-directory-path .
++
+ .SH SECURITY
+ The
+ .B sm-notify
+diff -up nfs-utils-1.3.0/utils/statd/statd.c.orig nfs-utils-1.3.0/utils/statd/statd.c
+--- nfs-utils-1.3.0/utils/statd/statd.c.orig	2017-03-28 13:43:36.000000000 -0400
++++ nfs-utils-1.3.0/utils/statd/statd.c	2017-03-28 13:43:53.000000000 -0400
+@@ -26,6 +26,7 @@
+ #include <sys/wait.h>
+ #include <grp.h>
+ 
++#include "conffile.h"
+ #include "statd.h"
+ #include "nfslib.h"
+ #include "nfsrpc.h"
+@@ -36,6 +37,7 @@
+ #include <sys/socket.h>
+ 
+ int	run_mode = 0;		/* foreground logging mode */
++char	*conf_path = NFS_CONFFILE;
+ 
+ /* LH - I had these local to main, but it seemed silly to have 
+  * two copies of each - one in main(), one static in log.c... 
+@@ -242,15 +244,21 @@ static void set_nlm_port(char *type, int
+ int main (int argc, char **argv)
+ {
+ 	extern char *optarg;
++	char *s;
+ 	int pid;
+ 	int arg;
+ 	int port = 0, out_port = 0;
+ 	int nlm_udp = 0, nlm_tcp = 0;
+ 	struct rlimit rlim;
++	char *env;
+ 
+ 	/* Default: daemon mode, no other options */
+ 	run_mode = 0;
+ 
++	env = getenv("RPC_STATD_NO_NOTIFY");
++	if (env && atoi(env) > 0)
++		run_mode |= MODE_NO_NOTIFY;
++
+ 	/* Log to stderr if there's an error during startup */
+ 	xlog_stderr(1);
+ 	xlog_syslog(0);
+@@ -265,6 +273,24 @@ int main (int argc, char **argv)
+ 	/* Set hostname */
+ 	MY_NAME = NULL;
+ 
++	conf_init();
++	xlog_from_conffile("statd");
++	out_port = conf_get_num("statd", "outgoing-port", out_port);
++	port = conf_get_num("statd", "port", port);
++	MY_NAME = conf_get_str("statd", "name");
++	if (MY_NAME)
++		run_mode |= STATIC_HOSTNAME;
++	s = conf_get_str("statd", "state-directory-path");
++	if (s && !nsm_setup_pathnames(argv[0], s))
++		exit(1);
++	s = conf_get_str("statd", "ha-callout");
++	if (s)
++		ha_callout_prog = s;
++
++	nlm_tcp = conf_get_num("lockd", "port", nlm_tcp);
++	/* udp defaults to the same as tcp ! */
++	nlm_udp = conf_get_num("lockd", "udp-port", nlm_tcp);
++
+ 	/* Process command line switches */
+ 	while ((arg = getopt_long(argc, argv, "h?vVFNH:dn:p:o:P:LT:U:", longopts, NULL)) != EOF) {
+ 		switch (arg) {
+diff -up nfs-utils-1.3.0/utils/statd/statd.man.orig nfs-utils-1.3.0/utils/statd/statd.man
+--- nfs-utils-1.3.0/utils/statd/statd.man.orig	2017-03-28 13:43:36.000000000 -0400
++++ nfs-utils-1.3.0/utils/statd/statd.man	2017-03-28 13:43:53.000000000 -0400
+@@ -8,7 +8,7 @@
+ .\" Rewritten by Chuck Lever <chuck.lever@oracle.com>, 2009.
+ .\" Copyright 2009 Oracle.  All rights reserved.
+ .\"
+-.TH RPC.STATD 8 "1 November 2009
++.TH RPC.STATD 8 "1 November 2009"
+ .SH NAME
+ rpc.statd \- NSM service daemon
+ .SH SYNOPSIS
+@@ -247,7 +247,7 @@ should listen on for
+ .B NLM
+ requests.
+ .TP
+-.BI "\-P, " "" \-\-state\-directory\-path " pathname
++.BI "\-P, " "" \-\-state\-directory\-path " pathname"
+ Specifies the pathname of the parent directory
+ where NSM state information resides.
+ If this option is not specified,
+@@ -267,6 +267,37 @@ Causes
+ to display version information on
+ .I stderr
+ and then exit.
++.SH CONFIGURATION FILE
++Many of the options that can be set on the command line can also be
++controlled through values set in the
++.B [statd]
++or, in some cases, the
++.B [lockd]
++sections of the
++.I /etc/nfs.conf
++configuration file.
++Values recognized in the
++.B [statd]
++section include
++.BR port ,
++.BR outgoing-port ,
++.BR name ,
++.BR state-directory-path ", and"
++.B ha-callout
++which each have the same effect as the option with the same name.
++
++The values recognized in the
++.B [lockd]
++section include
++.B port
++and
++.B udp-port
++which have the same effect as the
++.B --nlm-port
++and
++.B --nlm-udp-port
++options, respectively.
++
+ .SH SECURITY
+ The
+ .B rpc.statd
+@@ -387,6 +418,11 @@ it attempts to start listeners on networ
+ As long as at least one network transport listener starts successfully,
+ .B rpc.statd
+ will operate.
++.SH ENVIRONMENT
++.TP
++.B RPC_STATD_NO_NOTIFY=
++If set to a positive integer, has the same effect as
++.IR \-\-no\-notify .
+ .SH FILES
+ .TP 2.5i
+ .I /var/lib/nfs/sm
diff --git a/SOURCES/nfs-utils-1.3.0-nfsd-man-correction.patch b/SOURCES/nfs-utils-1.3.0-nfsd-man-correction.patch
new file mode 100644
index 0000000..8455de8
--- /dev/null
+++ b/SOURCES/nfs-utils-1.3.0-nfsd-man-correction.patch
@@ -0,0 +1,41 @@
+commit c7896bec9699473959fc51baf3686149a470a30b
+Author: Chris Siebenmann <cks.nfs01@cs.toronto.edu>
+Date:   Tue Mar 14 10:41:39 2017 -0400
+
+    Manual page bug: two inaccuracies in nfsd(7)
+    
+    Here is a patch that deletes the mention of auth.domain and changes the
+    wording around 'flush' files. I'm not attached to the revised wording;
+    it's just the best I could manage in something that felt that it was
+    within the same style and space as the current wording.
+    
+    Acked-by: NeilBrown <neilb@suse.com>
+    Signed-off-by: Chris Siebenmann <cks.nfs01@cs.toronto.edu>
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+
+diff --git a/utils/exportfs/nfsd.man b/utils/exportfs/nfsd.man
+index 0c516fa..9efa29f 100644
+--- a/utils/exportfs/nfsd.man
++++ b/utils/exportfs/nfsd.man
+@@ -105,11 +105,6 @@ clients have for different filesystems.
+ The caches are:
+ 
+ .TP
+-.B auth.domain
+-This cache maps the name of a client (or domain) to an internal data
+-structure.  The only access that is possible is to flush the cache.
+-
+-.TP
+ .B auth.unix.ip
+ This cache contains a mapping from IP address to the name of the
+ authentication domain that the ipaddress should be treated as part of.
+@@ -133,7 +128,8 @@ are:
+ .B flush
+ When a number of seconds since epoch (1 Jan 1970) is written to this
+ file, all entries in the cache that were last updated before that file
+-become invalidated and will be flushed out.  Writing 1 will flush
++become invalidated and will be flushed out.  Writing a time in the
++future (in seconds since epoch) will flush
+ everything.  This is the only file that will always be present.
+ 
+ .TP
diff --git a/SOURCES/nfs-utils-1.3.0-nfsdcltrack-errors.patch b/SOURCES/nfs-utils-1.3.0-nfsdcltrack-errors.patch
new file mode 100644
index 0000000..54af57f
--- /dev/null
+++ b/SOURCES/nfs-utils-1.3.0-nfsdcltrack-errors.patch
@@ -0,0 +1,37 @@
+commit 06bbb4ee6f5186e8e83d50767ad5b3b41968e5a6
+Author: Jeff Layton <jlayton@redhat.com>
+Date:   Wed Apr 26 12:13:50 2017 -0400
+
+    nfsdcltrack: silence some expected errors
+    
+    On a new install, we're unable to select from the parameters table, as
+    it doesn't exist yet. The code is set up to log that fact at L_ERROR
+    now, but it's an expected situation. Change it to log that at D_GENERAL
+    instead.
+    
+    Reported-and-Tested-by: ChunYu Wang <chunwang@redhat.com>
+    Signed-off-by: Jeff Layton <jlayton@redhat.com>
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+
+diff --git a/utils/nfsdcltrack/sqlite.c b/utils/nfsdcltrack/sqlite.c
+index 54cd748..1552eba 100644
+--- a/utils/nfsdcltrack/sqlite.c
++++ b/utils/nfsdcltrack/sqlite.c
+@@ -101,7 +101,7 @@ sqlite_query_schema_version(void)
+ 		"SELECT value FROM parameters WHERE key == \"version\";",
+ 		 -1, &stmt, NULL);
+ 	if (ret != SQLITE_OK) {
+-		xlog(L_ERROR, "Unable to prepare select statement: %s",
++		xlog(D_GENERAL, "Unable to prepare select statement: %s",
+ 			sqlite3_errmsg(dbh));
+ 		ret = 0;
+ 		goto out;
+@@ -110,7 +110,7 @@ sqlite_query_schema_version(void)
+ 	/* query schema version */
+ 	ret = sqlite3_step(stmt);
+ 	if (ret != SQLITE_ROW) {
+-		xlog(L_ERROR, "Select statement execution failed: %s",
++		xlog(D_GENERAL, "Select statement execution failed: %s",
+ 				sqlite3_errmsg(dbh));
+ 		ret = 0;
+ 		goto out;
diff --git a/SOURCES/nfs-utils-1.3.0-nfsdcltrack-usage.patch b/SOURCES/nfs-utils-1.3.0-nfsdcltrack-usage.patch
new file mode 100644
index 0000000..0d08563
--- /dev/null
+++ b/SOURCES/nfs-utils-1.3.0-nfsdcltrack-usage.patch
@@ -0,0 +1,21 @@
+commit daf0838e30f896d02ca51becc99578713c1be4cb
+Author: Steve Dickson <steved@redhat.com>
+Date:   Wed Dec 7 13:35:49 2016 -0500
+
+    Fixed typo in usage string
+    
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+
+diff --git a/utils/nfsdcltrack/nfsdcltrack.c b/utils/nfsdcltrack/nfsdcltrack.c
+index e6e514b..fd64153 100644
+--- a/utils/nfsdcltrack/nfsdcltrack.c
++++ b/utils/nfsdcltrack/nfsdcltrack.c
+@@ -100,7 +100,7 @@ static unsigned char blob[NFS4_OPAQUE_LIMIT];
+ static void
+ usage(char *progname)
+ {
+-	printf("%s [ -hfd ] [ -s dir ] < cmd > < arg >\n", progname);
++	printf("Usage: %s [ -hfd ] [ -s dir ] < cmd > < arg >\n", progname);
+ 	printf("Where < cmd > is one of the following and takes the following < arg >:\n");
+ 	printf("    init\n");
+ 	printf("    create <nfs_client_id4>\n");
diff --git a/SOURCES/nfs-utils-1.3.0-nfsman-minorversion.patch b/SOURCES/nfs-utils-1.3.0-nfsman-minorversion.patch
new file mode 100644
index 0000000..7198acb
--- /dev/null
+++ b/SOURCES/nfs-utils-1.3.0-nfsman-minorversion.patch
@@ -0,0 +1,27 @@
+diff -up nfs-utils-1.3.0/utils/mount/nfs.man.orig nfs-utils-1.3.0/utils/mount/nfs.man
+--- nfs-utils-1.3.0/utils/mount/nfs.man.orig	2017-03-31 16:15:33.487985468 -0400
++++ nfs-utils-1.3.0/utils/mount/nfs.man	2017-03-31 16:30:21.321755420 -0400
+@@ -769,6 +769,23 @@ so if this mount option is not specified
+ uses the TCP protocol.
+ Refer to the TRANSPORT METHODS section for more details.
+ .TP 1.5i
++.BI minorversion= n
++Specifies the protocol minor version number.
++NFSv4 introduces "minor versioning," where NFS protocol enhancements can
++be introduced without bumping the NFS protocol version number.
++Before kernel 2.6.38, the minor version is always zero, and this
++option is not recognized.
++After this kernel, specifying "minorversion=1" enables a number of
++advanced features, such as NFSv4 sessions.
++.IP
++Recent kernels allow the minor version to be specified using the
++.B vers=
++option.
++For example, specifying
++.B vers=4.1
++is the same as specifying
++.BR vers=4,minorversion=1 .
++.TP 1.5i
+ .BI port= n
+ The numeric value of the server's NFS service port.
+ If the server's NFS service is not available on the specified port,
diff --git a/SOURCES/nfs-utils-1.3.0-nfsstat-mounts.patch b/SOURCES/nfs-utils-1.3.0-nfsstat-mounts.patch
new file mode 100644
index 0000000..5cc704a
--- /dev/null
+++ b/SOURCES/nfs-utils-1.3.0-nfsstat-mounts.patch
@@ -0,0 +1,12 @@
+diff -up nfs-utils-1.3.0/utils/nfsstat/nfsstat.c.orig nfs-utils-1.3.0/utils/nfsstat/nfsstat.c
+--- nfs-utils-1.3.0/utils/nfsstat/nfsstat.c.orig	2017-04-09 04:32:28.951729219 -0400
++++ nfs-utils-1.3.0/utils/nfsstat/nfsstat.c	2017-04-09 04:34:49.686756801 -0400
+@@ -299,7 +299,7 @@ static struct option longopts[] =
+ 	{ "all", 0, 0, 'v' },
+ 	{ "auto", 0, 0, '\3' },
+ 	{ "client", 0, 0, 'c' },
+-	{ "mounted", 0, 0, 'm' },
++	{ "mounts", 0, 0, 'm' },
+ 	{ "nfs", 0, 0, 'n' },
+ 	{ "rpc", 0, 0, 'r' },
+ 	{ "server", 0, 0, 's' },
diff --git a/SOURCES/nfs-utils-1.3.0-nfsstat-retval.patch b/SOURCES/nfs-utils-1.3.0-nfsstat-retval.patch
new file mode 100644
index 0000000..0978d31
--- /dev/null
+++ b/SOURCES/nfs-utils-1.3.0-nfsstat-retval.patch
@@ -0,0 +1,30 @@
+diff -up nfs-utils-1.3.0/utils/nfsstat/nfsstat.c.orig nfs-utils-1.3.0/utils/nfsstat/nfsstat.c
+--- nfs-utils-1.3.0/utils/nfsstat/nfsstat.c.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/utils/nfsstat/nfsstat.c	2017-03-29 12:10:52.820709442 -0400
+@@ -348,7 +348,7 @@ main(int argc, char **argv)
+ 		switch (c) {
+ 		case 'a':
+ 			fprintf(stderr, "nfsstat: nfs acls are not yet supported.\n");
+-			return -1;
++			return 1;
+ 		case 'c':
+ 			opt_clt = 1;
+ 			break;
+@@ -410,7 +410,7 @@ main(int argc, char **argv)
+ 					"not yet supported\n");
+ 			return 2;
+ 		case 'm':
+-			return mounts(MOUNTSFILE);
++			return ! mounts(MOUNTSFILE);
+ 		case '\1':
+ 			usage(progname);
+ 			return 0;
+@@ -419,7 +419,7 @@ main(int argc, char **argv)
+ 			return 0;
+ 		default:
+ 			printf("Try `%s --help' for more information.\n", progname);
+-			return -1;
++			return 1;
+ 		}
+ 	}
+ 
diff --git a/SOURCES/nfs-utils-1.3.0-rpcgssd-preferred-realm.patch b/SOURCES/nfs-utils-1.3.0-rpcgssd-preferred-realm.patch
new file mode 100644
index 0000000..f8574f2
--- /dev/null
+++ b/SOURCES/nfs-utils-1.3.0-rpcgssd-preferred-realm.patch
@@ -0,0 +1,12 @@
+diff -up nfs-utils-1.3.0/utils/gssd/krb5_util.c.orig nfs-utils-1.3.0/utils/gssd/krb5_util.c
+--- nfs-utils-1.3.0/utils/gssd/krb5_util.c.orig	2017-03-31 16:34:11.775037704 -0400
++++ nfs-utils-1.3.0/utils/gssd/krb5_util.c	2017-04-08 15:18:53.619038636 -0400
+@@ -848,7 +848,7 @@ find_keytab_entry(krb5_context context,
+ 	i = 0;
+ 	realm = realmnames[i];
+ 
+-	if (strcmp (realm, preferred_realm) != 0) {
++	if (preferred_realm && strcmp (realm, preferred_realm) != 0) {
+ 		realm = preferred_realm;
+ 		/* resetting the realmnames index */
+ 		i = -1;
diff --git a/SOURCES/nfs-utils-1.3.0-server-generator.patch b/SOURCES/nfs-utils-1.3.0-server-generator.patch
new file mode 100644
index 0000000..6f2db6c
--- /dev/null
+++ b/SOURCES/nfs-utils-1.3.0-server-generator.patch
@@ -0,0 +1,467 @@
+diff -up nfs-utils-1.3.0/configure.ac.orig nfs-utils-1.3.0/configure.ac
+--- nfs-utils-1.3.0/configure.ac.orig	2017-03-31 15:55:05.544831618 -0400
++++ nfs-utils-1.3.0/configure.ac	2017-03-31 15:58:38.833955546 -0400
+@@ -64,8 +64,14 @@ unitdir=/usr/lib/systemd/system
+ AC_ARG_WITH(systemd,
+ 	[AC_HELP_STRING([--with-systemd@<:@=unit-dir-path@:>@],
+ 			[install systemd unit files @<:@Default: no, and path defaults to /usr/lib/systemd/system if not given@:>@])],
+-	test "$withval" = "no" && use_systemd=0 || unitdir=$withval use_systemd=1
+-	use_systemd=0
++	if test "$withval" != "no" ; then 
++		use_systemd=1
++		if test "$withval" != "yes" ; then 
++			unitdir=$withval
++		fi
++	else
++		use_systemd=0
++	fi
+ 	)
+ 	AM_CONDITIONAL(INSTALL_SYSTEMD, [test "$use_systemd" = 1])
+ 	AC_SUBST(unitdir)
+diff -up nfs-utils-1.3.0/.gitignore.orig nfs-utils-1.3.0/.gitignore
+--- nfs-utils-1.3.0/.gitignore.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/.gitignore	2017-03-31 15:55:47.123245655 -0400
+@@ -69,6 +69,7 @@ tests/nsm_client/nlm_sm_inter_clnt.c
+ tests/nsm_client/nlm_sm_inter_svc.c
+ tests/nsm_client/nlm_sm_inter_xdr.c
+ utils/nfsidmap/nfsidmap
++systemd/nfs-server-generator
+ # cscope database files
+ cscope.*
+ # generic editor backup et al
+diff -up nfs-utils-1.3.0/support/export/export.c.orig nfs-utils-1.3.0/support/export/export.c
+--- nfs-utils-1.3.0/support/export/export.c.orig	2017-03-31 15:55:05.528831459 -0400
++++ nfs-utils-1.3.0/support/export/export.c	2017-03-31 15:55:47.124245665 -0400
+@@ -15,6 +15,8 @@
+ #include <sys/param.h>
+ #include <netinet/in.h>
+ #include <stdlib.h>
++#include <dirent.h>
++#include <errno.h>
+ #include "xmalloc.h"
+ #include "nfslib.h"
+ #include "exportfs.h"
+@@ -68,11 +70,15 @@ static void warn_duplicated_exports(nfs_
+ /**
+  * export_read - read entries from /etc/exports
+  * @fname: name of file to read from
++ * @ignore_hosts: don't check validity of host names
+  *
+  * Returns number of read entries.
++ * @ignore_hosts can be set when the host names won't be used
++ * and when getting delays or errors due to problems with
++ * hostname looking is not acceptable.
+  */
+ int
+-export_read(char *fname)
++export_read(char *fname, int ignore_hosts)
+ {
+ 	struct exportent	*eep;
+ 	nfs_export		*exp;
+@@ -81,7 +87,7 @@ export_read(char *fname)
+ 
+ 	setexportent(fname, "r");
+ 	while ((eep = getexportent(0,1)) != NULL) {
+-		exp = export_lookup(eep->e_hostname, eep->e_path, 0);
++		exp = export_lookup(eep->e_hostname, eep->e_path, ignore_hosts);
+ 		if (!exp) {
+ 			if (export_create(eep, 0))
+ 				/* possible complaints already logged */
+@@ -94,6 +100,70 @@ export_read(char *fname)
+ 
+ 	return volumes;
+ }
++
++/**
++ * export_d_read - read entries from /etc/exports.
++ * @fname: name of directory to read from
++ * @ignore_hosts: don't check validity of host names
++ *
++ * Returns number of read entries.
++ * Based on mnt_table_parse_dir() in
++ *  util-linux-ng/shlibs/mount/src/tab_parse.c
++ */
++int
++export_d_read(const char *dname, int ignore_hosts)
++{
++	int n = 0, i;
++	struct dirent **namelist = NULL;
++	int volumes = 0;
++
++
++	n = scandir(dname, &namelist, NULL, versionsort);
++	if (n < 0) {
++		if (errno == ENOENT)
++			/* Silently return */
++			return volumes;
++		xlog(L_NOTICE, "scandir %s: %s", dname, strerror(errno));
++	} else if (n == 0)
++		return volumes;
++
++	for (i = 0; i < n; i++) {
++		struct dirent *d = namelist[i];
++		size_t namesz;
++		char fname[PATH_MAX + 1];
++		int fname_len;
++
++
++		if (d->d_type != DT_UNKNOWN
++		    && d->d_type != DT_REG
++		    && d->d_type != DT_LNK)
++			continue;
++		if (*d->d_name == '.')
++			continue;
++
++#define _EXT_EXPORT_SIZ   (sizeof(_EXT_EXPORT) - 1)
++		namesz = strlen(d->d_name);
++		if (!namesz
++		    || namesz < _EXT_EXPORT_SIZ + 1
++		    || strcmp(d->d_name + (namesz - _EXT_EXPORT_SIZ),
++			      _EXT_EXPORT))
++			continue;
++
++		fname_len = snprintf(fname, PATH_MAX +1, "%s/%s", dname, d->d_name);
++		if (fname_len > PATH_MAX) {
++			xlog(L_WARNING, "Too long file name: %s in %s", d->d_name, dname);
++			continue;
++		}
++
++		volumes += export_read(fname, ignore_hosts);
++	}
++
++	for (i = 0; i < n; i++)
++		free(namelist[i]);
++	free(namelist);
++
++	return volumes;
++}
+ 
+ /**
+  * export_create - create an in-core nfs_export record from an export entry
+diff -up nfs-utils-1.3.0/support/include/exportfs.h.orig nfs-utils-1.3.0/support/include/exportfs.h
+--- nfs-utils-1.3.0/support/include/exportfs.h.orig	2017-03-31 15:55:05.528831459 -0400
++++ nfs-utils-1.3.0/support/include/exportfs.h	2017-03-31 15:55:47.124245665 -0400
+@@ -133,7 +133,8 @@ struct addrinfo *		client_resolve(const
+ int 				client_member(const char *client,
+ 						const char *name);
+ 
+-int				export_read(char *fname);
++int				export_read(char *fname, int ignore_hosts);
++int				export_d_read(const char *dname, int ignore_hosts);
+ void				export_reset(nfs_export *);
+ nfs_export *			export_lookup(char *hname, char *path, int caconical);
+ nfs_export *			export_find(const struct addrinfo *ai,
+diff -up nfs-utils-1.3.0/systemd/Makefile.am.orig nfs-utils-1.3.0/systemd/Makefile.am
+--- nfs-utils-1.3.0/systemd/Makefile.am.orig	2017-03-31 15:55:05.545831628 -0400
++++ nfs-utils-1.3.0/systemd/Makefile.am	2017-03-31 15:55:47.124245665 -0400
+@@ -4,7 +4,6 @@ MAINTAINERCLEANFILES = Makefile.in
+ 
+ unit_files =  \
+     nfs-client.target \
+-    \
+     auth-rpcgss-module.service \
+     nfs-blkmap.service \
+     nfs-config.service \
+@@ -15,8 +14,6 @@ unit_files =  \
+     rpc-gssd.service \
+     rpc-statd-notify.service \
+     rpc-statd.service \
+-    rpc-svcgssd.service \
+-    \
+     proc-fs-nfsd.mount \
+     var-lib-nfs-rpc_pipefs.mount
+ 
+@@ -25,8 +22,16 @@ man7_MANS	= nfs.systemd.man
+ EXTRA_DIST = $(unit_files) $(man5_MANS) $(man7_MANS)
+ 
+ unit_dir = /usr/lib/systemd/system
++generator_dir = /usr/lib/systemd/system-generators
++
++EXTRA_PROGRAMS	= nfs-server-generator
++genexecdir = $(generator_dir)
++nfs_server_generator_LDADD = ../support/export/libexport.a \
++			     ../support/nfs/libnfs.a \
++			     ../support/misc/libmisc.a
+ 
+ if INSTALL_SYSTEMD
++genexec_PROGRAMS = nfs-server-generator
+ install-data-hook: $(unit_files)
+ 	mkdir -p $(DESTDIR)/$(unitdir)
+ 	cp $(unit_files) $(DESTDIR)/$(unitdir)
+diff -up nfs-utils-1.3.0/systemd/nfs-server-generator.c.orig nfs-utils-1.3.0/systemd/nfs-server-generator.c
+--- nfs-utils-1.3.0/systemd/nfs-server-generator.c.orig	2017-03-31 15:55:47.124245665 -0400
++++ nfs-utils-1.3.0/systemd/nfs-server-generator.c	2017-03-31 15:55:47.124245665 -0400
+@@ -0,0 +1,179 @@
++/*
++ * nfs-server-generator:
++ *   systemd generator to create ordering dependencies between
++ *   nfs-server and various filesystem mounts
++ *
++ * 1/ nfs-server should start Before any 'nfs' mountpoints are
++ *    mounted, in case they are loop-back mounts.  This ordering is particularly
++ *    important for the shutdown side, so the nfs-server is stopped
++ *    after the filesystems are unmounted.
++ * 2/ nfs-server should start After all exported filesystems are mounted
++ *    so there is no risk of exporting the underlying directory.
++ *    This is particularly important for _net mounts which
++ *    are not caught by "local-fs.target".
++ */
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif
++
++#include <sys/stat.h>
++#include <sys/types.h>
++#include <unistd.h>
++#include <stdlib.h>
++#include <string.h>
++#include <ctype.h>
++#include <stdio.h>
++#include <mntent.h>
++
++#include "misc.h"
++#include "nfslib.h"
++#include "exportfs.h"
++
++/* A simple "set of strings" to remove duplicates
++ * found in /etc/exports
++ */
++struct list {
++	struct list *next;
++	char *name;
++};
++static int is_unique(struct list **lp, char *path)
++{
++	struct list *l = *lp;
++
++	while (l) {
++		if (strcmp(l->name, path) == 0)
++			return 0;
++		l = l->next;
++	}
++	l = malloc(sizeof(*l));
++	if (l == NULL)
++		return 0;
++	l->name = path;
++	l->next = *lp;
++	*lp = l;
++	return 1;
++}
++
++/* We need to convert a path name to a systemd unit
++ * name.  This requires some translation ('/' -> '-')
++ * and some escaping.
++ */
++static void systemd_escape(FILE *f, char *path)
++{
++	while (*path == '/')
++		path++;
++	if (!*path) {
++		/* "/" becomes "-", otherwise leading "/" is ignored */
++		fputs("-", f);
++		return;
++	}
++	while (*path) {
++		char c = *path++;
++
++		if (c == '/') {
++			/* multiple non-trailing slashes become '-' */
++			while (*path == '/')
++				path++;
++			if (*path)
++				fputs("-", f);
++		} else if (isalnum(c) || c == ':' || c == '.')
++			fputc(c, f);
++		else
++			fprintf(f, "\\x%02x", c & 0xff);
++	}
++}
++
++static int has_noauto_flag(char *path)
++{
++	FILE		*fstab;
++	struct mntent	*mnt;
++
++	fstab = setmntent("/etc/fstab", "r");
++	if (!fstab)
++		return 0;
++
++	while ((mnt = getmntent(fstab)) != NULL) {
++		int l = strlen(mnt->mnt_dir);
++		if (strncmp(mnt->mnt_dir, path, l) != 0)
++			continue;
++		if (path[l] && path[l] != '/')
++			continue;
++		if (hasmntopt(mnt, "noauto"))
++			break;
++	}
++	fclose(fstab);
++	return mnt != NULL;
++}
++
++int main(int argc, char *argv[])
++{
++	char		*path;
++	char		dirbase[] = "/nfs-server.service.d";
++	char		filebase[] = "/order-with-mounts.conf";
++	nfs_export	*exp;
++	int		i;
++	struct list	*list = NULL;
++	FILE		*f, *fstab;
++	struct mntent	*mnt;
++
++	/* Avoid using any external services */
++	xlog_syslog(0);
++
++	if (argc != 4 || argv[1][0] != '/') {
++		fprintf(stderr, "nfs-server-generator: create systemd dependencies for nfs-server\n");
++		fprintf(stderr, "Usage: normal-dir early-dir late-dir\n");
++		exit(1);
++	}
++
++	path = malloc(strlen(argv[1]) + sizeof(dirbase) + sizeof(filebase));
++	if (!path)
++		exit(2);
++	if (export_read(_PATH_EXPORTS, 1) +
++	    export_d_read(_PATH_EXPORTS_D, 1) == 0)
++		/* Nothing is exported, so nothing to do */
++		exit(0);
++
++	strcat(strcpy(path, argv[1]), dirbase);
++	mkdir(path, 0755);
++	strcat(path, filebase);
++	f = fopen(path, "w");
++	if (!f)
++		exit(1);
++	fprintf(f, "# Automatically generated by nfs-server-generator\n\n[Unit]\n");
++
++	for (i = 0; i < MCL_MAXTYPES; i++) {
++		for (exp = exportlist[i].p_head; exp; exp = exp->m_next) {
++			if (!is_unique(&list, exp->m_export.e_path))
++				continue;
++			if (exp->m_export.e_mountpoint)
++				continue;
++			if (has_noauto_flag(exp->m_export.e_path))
++				continue;
++			if (strchr(exp->m_export.e_path, ' '))
++				fprintf(f, "RequiresMountsFor=\"%s\"\n",
++					exp->m_export.e_path);
++			else
++				fprintf(f, "RequiresMountsFor=%s\n",
++					exp->m_export.e_path);
++		}
++	}
++
++	fstab = setmntent("/etc/fstab", "r");
++	if (!fstab)
++		exit(1);
++
++	while ((mnt = getmntent(fstab)) != NULL) {
++		if (strcmp(mnt->mnt_type, "nfs") != 0 &&
++		    strcmp(mnt->mnt_type, "nfs4") != 0)
++			continue;
++		fprintf(f, "Before= ");
++		systemd_escape(f, mnt->mnt_dir);
++		fprintf(f, ".mount\n");
++	}
++
++	fclose(fstab);
++	fclose(f);
++
++	exit(0);
++}
+diff -up nfs-utils-1.3.0/utils/exportfs/exportfs.c.orig nfs-utils-1.3.0/utils/exportfs/exportfs.c
+--- nfs-utils-1.3.0/utils/exportfs/exportfs.c.orig	2017-03-31 15:55:05.553831708 -0400
++++ nfs-utils-1.3.0/utils/exportfs/exportfs.c	2017-03-31 15:55:47.125245675 -0400
+@@ -26,7 +26,6 @@
+ #include <fcntl.h>
+ #include <netdb.h>
+ #include <errno.h>
+-#include <dirent.h>
+ #include <limits.h>
+ #include <time.h>
+ 
+@@ -48,7 +47,6 @@ static void	error(nfs_export *exp, int e
+ static void	usage(const char *progname, int n);
+ static void	validate_export(nfs_export *exp);
+ static int	matchhostname(const char *hostname1, const char *hostname2);
+-static int	export_d_read(const char *dname);
+ static void grab_lockfile(void);
+ static void release_lockfile(void);
+ 
+@@ -190,8 +188,8 @@ main(int argc, char **argv)
+ 	atexit(release_lockfile);
+ 
+ 	if (f_export && ! f_ignore) {
+-		if (! (export_read(_PATH_EXPORTS) +
+-		       export_d_read(_PATH_EXPORTS_D))) {
++		if (! (export_read(_PATH_EXPORTS, 0) +
++		       export_d_read(_PATH_EXPORTS_D, 0))) {
+ 			if (f_verbose)
+ 				xlog(L_WARNING, "No file systems exported!");
+ 		}
+@@ -705,63 +703,6 @@ out:
+ 	return result;
+ }
+ 
+-/* Based on mnt_table_parse_dir() in
+-   util-linux-ng/shlibs/mount/src/tab_parse.c */
+-static int
+-export_d_read(const char *dname)
+-{
+-	int n = 0, i;
+-	struct dirent **namelist = NULL;
+-	int volumes = 0;
+-
+-
+-	n = scandir(dname, &namelist, NULL, versionsort);
+-	if (n < 0) {
+-		if (errno == ENOENT)
+-			/* Silently return */
+-			return volumes;
+-		xlog(L_NOTICE, "scandir %s: %s", dname, strerror(errno));
+-	} else if (n == 0)
+-		return volumes;
+-
+-	for (i = 0; i < n; i++) {
+-		struct dirent *d = namelist[i];
+-		size_t namesz;
+-		char fname[PATH_MAX + 1];
+-		int fname_len;
+-
+-
+-		if (d->d_type != DT_UNKNOWN
+-		    && d->d_type != DT_REG
+-		    && d->d_type != DT_LNK)
+-			continue;
+-		if (*d->d_name == '.')
+-			continue;
+-
+-#define _EXT_EXPORT_SIZ   (sizeof(_EXT_EXPORT) - 1)
+-		namesz = strlen(d->d_name);
+-		if (!namesz
+-		    || namesz < _EXT_EXPORT_SIZ + 1
+-		    || strcmp(d->d_name + (namesz - _EXT_EXPORT_SIZ),
+-			      _EXT_EXPORT))
+-			continue;
+-
+-		fname_len = snprintf(fname, PATH_MAX +1, "%s/%s", dname, d->d_name);
+-		if (fname_len > PATH_MAX) {
+-			xlog(L_WARNING, "Too long file name: %s in %s", d->d_name, dname);
+-			continue;
+-		}
+-
+-		volumes += export_read(fname);
+-	}
+-
+-	for (i = 0; i < n; i++)
+-		free(namelist[i]);
+-	free(namelist);
+-
+-	return volumes;
+-}
+-
+ static char
+ dumpopt(char c, char *fmt, ...)
+ {
diff --git a/SOURCES/nfs-utils-1.3.0-statd-notify-grace-period.patch b/SOURCES/nfs-utils-1.3.0-statd-notify-grace-period.patch
new file mode 100644
index 0000000..3ff539d
--- /dev/null
+++ b/SOURCES/nfs-utils-1.3.0-statd-notify-grace-period.patch
@@ -0,0 +1,167 @@
+diff --git a/nfs.conf b/nfs.conf
+new file mode 100644
+index 0000000..690645c
+--- /dev/null
++++ b/nfs.conf
+@@ -0,0 +1,71 @@
++#
++# This is a general conifguration for the 
++# NFS daemons and tools
++#
++#[exportfs]
++# debug=0
++#
++#[gssd]
++# use-memcache=0
++# use-machine-creds=1
++# avoid-dns=1
++# limit-to-legacy-enctypes=0
++# context-timeout=0
++# rpc-timeout=5
++# pipefs-directory=/var/lib/nfs/rpc_pipefs
++# keytab-file=/etc/krb5.keytab
++# cred-cache-directory=
++# preferred-realm=
++#
++#[lockd]
++# port=0
++# udp-port=0
++#
++#[mountd]
++# debug=0
++# manage_gids=n
++# descriptors=0
++# port=0
++# threads=1
++# reverse-lookup=n
++# state-directory-path=/var/lib/nfs
++# ha-callout=
++#
++#[nfsdcltrack]
++# debug=0
++# storagedir=/var/lib/nfs/nfsdcltrack
++#
++#[nfsd]
++# debug=0
++# threads=8
++# host=
++# port=0
++# grace-time=90
++# lease-time=90
++# udp=y
++# tcp=y
++# vers2=n
++# vers3=y
++# vers4=y
++# vers4.0=y
++# vers4.1=y
++# vers4.2=y
++# rdma=n
++#
++#[statd]
++# debug=0
++# port=0
++# outgoing-port=0
++# name=
++# state-directory-path=/var/lib/nfs/statd
++# ha-callout=
++#
++#[sm-notify]
++# debug=0
++# retry-time=900
++# outgoing-port=
++# outgoing-addr=
++# lift-grace=y
++#
++#[svcgssd]
++# principal=
+diff --git a/utils/statd/sm-notify.c b/utils/statd/sm-notify.c
+index dcb85a3..ec59311 100644
+--- a/utils/statd/sm-notify.c
++++ b/utils/statd/sm-notify.c
+@@ -46,6 +46,10 @@
+ #define NSM_TIMEOUT	2
+ #define NSM_MAX_TIMEOUT	120	/* don't make this too big */
+ 
++#define NLM_END_GRACE_FILE	"/proc/fs/lockd/nlm_end_grace"
++
++int lift_grace = 1;
++
+ struct nsm_host {
+ 	struct nsm_host *	next;
+ 	char *			name;
+@@ -456,6 +460,28 @@ retry:
+ 	return sock;
+ }
+ 
++/* Inform the kernel that it's OK to lift lockd's grace period */
++static void
++nsm_lift_grace_period(void)
++{
++	int fd;
++
++	fd = open(NLM_END_GRACE_FILE, O_WRONLY);
++	if (fd < 0) {
++		/* Don't warn if file isn't present */
++		if (errno != ENOENT)
++			xlog(L_WARNING, "Unable to open %s: %m",
++				NLM_END_GRACE_FILE);
++		return;
++	}
++
++	if (write(fd, "Y", 1) < 0)
++		xlog(L_WARNING, "Unable to write to %s: %m", NLM_END_GRACE_FILE);
++
++	close(fd);
++	return;
++}
++
+ int
+ main(int argc, char **argv)
+ {
+@@ -474,6 +500,7 @@ main(int argc, char **argv)
+ 	opt_max_retry = conf_get_num("sm-notify", "retry-time", opt_max_retry / 60) * 60;
+ 	opt_srcport = conf_get_str("sm-notify", "outgoing-port");
+ 	opt_srcaddr = conf_get_str("sm-notify", "outgoing-addr");
++	lift_grace = conf_get_bool("sm-notify", "lift-grace", lift_grace);
+ 	s = conf_get_str("statd", "state-directory-path");
+ 	if (s && !nsm_setup_pathnames(argv[0], s))
+ 		exit(1);
+@@ -550,6 +577,8 @@ usage:		fprintf(stderr,
+ 	(void)nsm_retire_monitored_hosts();
+ 	if (nsm_load_notify_list(smn_get_host) == 0) {
+ 		xlog(D_GENERAL, "No hosts to notify; exiting");
++		if (lift_grace)
++			nsm_lift_grace_period();
+ 		return 0;
+ 	}
+ 
+diff --git a/utils/statd/sm-notify.man b/utils/statd/sm-notify.man
+index 89627e5..4658d86 100644
+--- a/utils/statd/sm-notify.man
++++ b/utils/statd/sm-notify.man
+@@ -241,6 +241,24 @@ These have the same effect as the command line options
+ .B v
+ respectively.
+ 
++An additional value recognized in the
++.B [sm-notify]
++section is
++.BR lift-grace .
++By default,
++.B sm-notify
++will lift lockd's grace period early if it has no hosts to notify.
++Some high availability configurations will run one
++.B sm-notify
++per floating IP address.  In these configurations, lifting the
++grace period early may prevent clients from reclaiming locks.
++.RB "Setting " lift-grace " to " n
++will prevent
++.B sm-notify
++from ending the grace period early.
++.B lift-grace
++has no corresponding command line option.
++
+ The value recognized in the
+ .B [statd]
+ section is
diff --git a/SOURCES/nfs-utils-1.3.0-systemd-gssproxy.patch b/SOURCES/nfs-utils-1.3.0-systemd-gssproxy.patch
new file mode 100644
index 0000000..77dc453
--- /dev/null
+++ b/SOURCES/nfs-utils-1.3.0-systemd-gssproxy.patch
@@ -0,0 +1,77 @@
+diff -up nfs-utils-1.3.0/systemd/auth-rpcgss-module.service.orig nfs-utils-1.3.0/systemd/auth-rpcgss-module.service
+--- nfs-utils-1.3.0/systemd/auth-rpcgss-module.service.orig	2017-05-22 11:22:16.064030000 -0400
++++ nfs-utils-1.3.0/systemd/auth-rpcgss-module.service	2017-06-06 16:19:05.229155456 -0400
+@@ -7,8 +7,8 @@
+ [Unit]
+ 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
++Before=gssproxy.service rpc-gssd.service
++Wants=gssproxy.service rpc-gssd.service
+ ConditionPathExists=/etc/krb5.keytab
+ 
+ [Service]
+diff -up nfs-utils-1.3.0/systemd/nfs-client.target.orig nfs-utils-1.3.0/systemd/nfs-client.target
+--- nfs-utils-1.3.0/systemd/nfs-client.target.orig	2017-05-22 11:22:16.054029846 -0400
++++ nfs-utils-1.3.0/systemd/nfs-client.target	2017-06-06 16:19:26.653588268 -0400
+@@ -9,7 +9,7 @@ Wants=rpc-statd-notify.service
+ 
+ # GSS services dependencies and ordering
+ Wants=auth-rpcgss-module.service
+-After=rpc-gssd.service rpc-svcgssd.service gssproxy.service
++After=rpc-gssd.service gssproxy.service
+ 
+ [Install]
+ WantedBy=multi-user.target
+diff -up nfs-utils-1.3.0/systemd/nfs.conf.man.orig nfs-utils-1.3.0/systemd/nfs.conf.man
+--- nfs-utils-1.3.0/systemd/nfs.conf.man.orig	2017-05-22 11:22:16.118030830 -0400
++++ nfs-utils-1.3.0/systemd/nfs.conf.man	2017-06-06 16:20:11.502494296 -0400
+@@ -208,15 +208,6 @@ See
+ for details.
+ 
+ .TP
+-.B svcgssd
+-Recognized values:
+-.BR principal .
+-
+-See
+-.BR rpc.svcgssd (8)
+-for details.
+-
+-.TP
+ .B exportfs
+ Only
+ .B debug=
+diff -up nfs-utils-1.3.0/systemd/nfs-server.service.orig nfs-utils-1.3.0/systemd/nfs-server.service
+--- nfs-utils-1.3.0/systemd/nfs-server.service.orig	2017-05-22 11:22:16.138031137 -0400
++++ nfs-utils-1.3.0/systemd/nfs-server.service	2017-06-06 16:16:55.197527187 -0400
+@@ -14,7 +14,7 @@ Before= rpc-statd-notify.service
+ 
+ # GSS services dependencies and ordering
+ Wants=auth-rpcgss-module.service
+-After=rpc-gssd.service gssproxy.service rpc-svcgssd.service
++After=rpc-gssd.service gssproxy.service
+ 
+ Wants=nfs-config.service
+ After=nfs-config.service
+@@ -25,6 +25,7 @@ EnvironmentFile=-/run/sysconfig/nfs-util
+ Type=oneshot
+ RemainAfterExit=yes
+ ExecStartPre=-/usr/sbin/exportfs -r
++ExecStartPre=-/bin/sh -c '/bin/kill -HUP `cat /run/gssproxy.pid`'
+ ExecStart=/usr/sbin/rpc.nfsd $RPCNFSDARGS
+ ExecStop=/usr/sbin/rpc.nfsd 0
+ ExecStopPost=/usr/sbin/exportfs -au
+diff -up nfs-utils-1.3.0/systemd/rpc-gssd.service.orig nfs-utils-1.3.0/systemd/rpc-gssd.service
+--- nfs-utils-1.3.0/systemd/rpc-gssd.service.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/systemd/rpc-gssd.service	2017-06-06 16:24:08.932290804 -0400
+@@ -3,7 +3,7 @@ Description=RPC security service for NFS
+ DefaultDependencies=no
+ Conflicts=umount.target
+ Requires=var-lib-nfs-rpc_pipefs.mount
+-After=var-lib-nfs-rpc_pipefs.mount
++After=var-lib-nfs-rpc_pipefs.mount gssproxy.service
+ 
+ ConditionPathExists=/etc/krb5.keytab
+ 
diff --git a/SOURCES/nfs-utils-1.3.0-systemd-network-online.patch b/SOURCES/nfs-utils-1.3.0-systemd-network-online.patch
new file mode 100644
index 0000000..07cb8ca
--- /dev/null
+++ b/SOURCES/nfs-utils-1.3.0-systemd-network-online.patch
@@ -0,0 +1,69 @@
+diff --git a/systemd/nfs-mountd.service b/systemd/nfs-mountd.service
+index 8a39f3e..ed357a2 100644
+--- a/systemd/nfs-mountd.service
++++ b/systemd/nfs-mountd.service
+@@ -2,8 +2,10 @@
+ Description=NFS Mount Daemon
+ DefaultDependencies=no
+ Requires=proc-fs-nfsd.mount
++Wants=network-online.target
+ After=proc-fs-nfsd.mount
+-After=network.target local-fs.target
++After=network-online.target local-fs.target
++After=rpcbind.socket
+ BindsTo=nfs-server.service
+ 
+ Wants=nfs-config.service
+diff --git a/systemd/nfs-server.service b/systemd/nfs-server.service
+index 7f60f39..d285c6e 100644
+--- a/systemd/nfs-server.service
++++ b/systemd/nfs-server.service
+@@ -1,13 +1,14 @@
+ [Unit]
+ Description=NFS server and services
+ DefaultDependencies=no
+-Requires= network.target proc-fs-nfsd.mount rpcbind.target
++Requires= network.target proc-fs-nfsd.mount
+ Requires= nfs-mountd.service
++Wants=rpcbind.socket network-online.target
+ Wants=rpc-statd.service nfs-idmapd.service
+ Wants=rpc-statd-notify.service
+ 
+-After= local-fs.target
+-After= network.target proc-fs-nfsd.mount rpcbind.service nfs-mountd.service
++After= network-online.target local-fs.target
++After= proc-fs-nfsd.mount rpcbind.socket nfs-mountd.service
+ After= nfs-idmapd.service rpc-statd.service
+ Before= rpc-statd-notify.service
+ 
+diff --git a/systemd/rpc-statd-notify.service b/systemd/rpc-statd-notify.service
+index 7a37ce1..f27f76d 100644
+--- a/systemd/rpc-statd-notify.service
++++ b/systemd/rpc-statd-notify.service
+@@ -1,8 +1,8 @@
+ [Unit]
+ Description=Notify NFS peers of a restart
+ DefaultDependencies=no
+-Requires=network.target
+-After=local-fs.target network.target nss-lookup.target
++Wants=network-online.target
++After=local-fs.target network-online.target nss-lookup.target
+ 
+ # Do not start up in HA environments
+ ConditionPathExists=!/var/lib/nfs/statd/sm.ha
+diff --git a/systemd/rpc-statd.service b/systemd/rpc-statd.service
+index 2a054be..1ed60a8 100644
+--- a/systemd/rpc-statd.service
++++ b/systemd/rpc-statd.service
+@@ -2,8 +2,9 @@
+ Description=NFS status monitor for NFSv2/3 locking.
+ DefaultDependencies=no
+ Conflicts=umount.target
+-Requires=nss-lookup.target rpcbind.target
+-After=network.target nss-lookup.target rpcbind.service
++Requires=nss-lookup.target rpcbind.socket
++Wants=network-online.target
++After=network-online.target nss-lookup.target rpcbind.socket
+ 
+ PartOf=nfs-utils.service
+ 
diff --git a/SOURCES/nfs-utils_env.sh b/SOURCES/nfs-utils_env.sh
index aa41822..246e894 100644
--- a/SOURCES/nfs-utils_env.sh
+++ b/SOURCES/nfs-utils_env.sh
@@ -55,7 +55,6 @@ echo STATDARGS=\"$STATDARG\"
 echo SMNOTIFYARGS=\"$SMNOTIFYARGS\"
 echo RPCIDMAPDARGS=\"$RPCIDMAPDARGS\"
 echo GSSDARGS=\"$RPCGSSDARGS\"
-echo SVCGSSDARGS=\"$RPCSVCGSSDARGS\"
 echo BLKMAPDARGS=\"$BLKMAPDARGS\"
 echo GSS_USE_PROXY=\"$GSS_USE_PROXY\"
 } > /run/sysconfig/nfs-utils
diff --git a/SOURCES/nfs.sysconfig b/SOURCES/nfs.sysconfig
index 0fcbe56..7e0c827 100644
--- a/SOURCES/nfs.sysconfig
+++ b/SOURCES/nfs.sysconfig
@@ -51,8 +51,5 @@ RPCGSSDARGS=""
 # Enable usage of gssproxy. See gssproxy-mech(8).
 GSS_USE_PROXY="yes"
 #
-# Optional arguments passed to rpc.svcgssd. See rpc.svcgssd(8)
-RPCSVCGSSDARGS=""
-#
 # Optional arguments passed to blkmapd. See blkmapd(8)
 BLKMAPDARGS=""
diff --git a/SPECS/nfs-utils.spec b/SPECS/nfs-utils.spec
index 8a12c48..a8d651a 100644
--- a/SPECS/nfs-utils.spec
+++ b/SPECS/nfs-utils.spec
@@ -2,7 +2,7 @@ Summary: NFS utilities and supporting clients and daemons for the kernel NFS ser
 Name: nfs-utils
 URL: http://sourceforge.net/projects/nfs
 Version: 1.3.0
-Release: 0.33%{?dist}
+Release: 0.48%{?dist}
 Epoch: 1
 
 # group all 32bit related archs
@@ -14,6 +14,7 @@ Source1: id_resolver.conf
 Source2: nfs.sysconfig
 Source3: nfs-utils_env.sh
 Source4: lockd.conf
+Source5: 24-nfs-server.conf
 
 #
 # RHEL7.1
@@ -91,9 +92,39 @@ Patch064: nfs-utils-1.3.0-start-statd-flock.patch
 Patch065: nfs-utils-1.3.0-mountd-root.patch
 Patch066: nfs-utils-1.3.0-mount-nfs-types.patch
 #
-# RHEL7.3-Z
+# RHEL7.4
 #
-Patch067: nfs-utils-1.3.0-systemd-rpcpipefs.patch
+Patch067: nfs-utils-1.3.0-mount-default-v42.patch
+Patch068: nfs-utils-1.3.0-gssd-default-tcp.patch
+Patch069: nfs-utils-1.3.0-mountstats-pnfs.patch
+Patch070: nfs-utils-1.3.0-nfsdcltrack-usage.patch
+Patch071: nfs-utils-1.3.0-daemon_init-warning.patch
+Patch072: nfs-utils-1.3.0-mount-v4arg-fix.patch
+Patch073: nfs-utils-1.3.0-systemd-rpcpipefs.patch
+Patch074: nfs-utils-1.3.0-mountd-filedes.patch
+Patch075: nfs-utils-1.3.0-exportfs-redundant.patch
+Patch076: nfs-utils-1.3.0-nfs-conf.patch
+Patch077: nfs-utils-1.3.0-gssd-rdma-to-tcp.patch
+Patch078: nfs-utils-1.3.0-gssd-thread-safe.patch
+Patch079: nfs-utils-1.3.0-mount-uninit-structs.patch
+Patch080: nfs-utils-1.3.0-exportfs-securitylabel.patch
+Patch081: nfs-utils-1.3.0-mount-v41.patch
+Patch082: nfs-utils-1.3.0-nfsstat-retval.patch
+Patch083: nfs-utils-1.3.0-server-generator.patch
+Patch084: nfs-utils-1.3.0-nfsman-minorversion.patch
+Patch085: nfs-utils-1.3.0-rpcgssd-preferred-realm.patch
+Patch086: nfs-utils-1.3.0-mountstats-iostats.patch
+Patch087: nfs-utils-1.3.0-mount-prognotreg.patch
+Patch088: nfs-utils-1.3.0-statd-notify-grace-period.patch
+Patch089: nfs-utils-1.3.0-nfsstat-mounts.patch
+Patch090: nfs-utils-1.3.0-nfsd-man-correction.patch
+Patch091: nfs-utils-1.3.0-nfsdcltrack-errors.patch
+Patch092: nfs-utils-1.3.0-systemd-network-online.patch
+Patch093: nfs-utils-1.3.0-mount-explicit-rback.patch
+Patch094: nfs-utils-1.3.0-systemd-gssproxy.patch
+Patch095: nfs-utils-1.3.0-mount-use-minor-default.patch
+Patch096: nfs-utils-1.3.0-mount-restore-econn.patch
+Patch097: nfs-utils-1.3.0-exportfs-path-comp.patch
 
 Patch100: nfs-utils-1.2.1-statdpath-man.patch
 Patch101: nfs-utils-1.2.1-exp-subtree-warn-off.patch
@@ -110,7 +141,6 @@ Provides: rpc.mountd  = %{epoch}:%{version}-%{release}
 Provides: rpc.nfsd    = %{epoch}:%{version}-%{release}
 Provides: rpc.statd   = %{epoch}:%{version}-%{release}
 Provides: rpc.gssd    = %{epoch}:%{version}-%{release}
-Provides: rpc.svcgssd = %{epoch}:%{version}-%{release}
 Provides: mount.nfs   = %{epoch}:%{version}-%{release}
 Provides: mount.nfs4  = %{epoch}:%{version}-%{release}
 Provides: umount.nfs  = %{epoch}:%{version}-%{release}
@@ -135,7 +165,7 @@ Requires(post): systemd-units
 Requires(preun): systemd-units
 Requires(postun): systemd-units
 
-Requires: gssproxy >= 0.3.0-0
+Requires: gssproxy >= 0.7.0-3
 Conflicts: gssproxy < 0.3.0-10
 
 %description
@@ -284,8 +314,68 @@ This package also contains the mount.nfs and umount.nfs program.
 %patch065 -p1
 # 1363737 - man mount.nfs incorrectly mentions the default mount....
 %patch066 -p1
-# 1411653 - var-lib-nfs-rpc_pipefs.mount fails [rhel-7.3.z]
+# 1375259 - NFSv4.2 as default NFS mount protocol
 %patch067 -p1
+# 1386759 - nfs-utils requires a fix to support NFS/RDMA mounts....
+%patch068 -p1
+# 1377740 - Add pNFS READs and WRITEs to the mountstats program output 
+%patch069 -p1
+# 1001494 - RFE: feature, add "[Uu]sage:" string in the nfsdcltrack -h output info
+%patch070 -p1
+# 1377914 - Compiler Warning of support/nfs/mydaemon.c....
+%patch071 -p1
+# 1404617 - mount.nfs fall back to version 3 when specifying...
+%patch072 -p1
+# 1406164 - var-lib-nfs-rpc_pipefs.mount fails
+%patch073 -p1
+# 1409903 - Occasional SELinux denials when starting up knfsd
+%patch074 -p1
+# 1396402 - [exportfs] exportfs -s output some exports options twice, but..
+%patch075 -p1
+# 1418041 - Update nfs-utils to use latest upstream configuration style
+%patch076 -p1
+# 1386759 - nfs-utils requires a fix to support NFS/RDMA mounts....
+%patch077 -p1
+# 1419280 - Non-thread-safe functions used in multi-threaded rpc.gssd
+%patch078 -p1
+# 1415024 - [uninitialized struct] get wrong nfs version when doing nfs mount
+%patch079 -p1
+# 1435899 - exportfs: support "security_label" export option
+%patch080 -p1
+# 1435901 - mount.nfs: starts mount negation with v4.2 it should be v4.1 
+%patch081 -p1
+# 1400658 - nfsstat -m command returns false return code
+%patch082 -p1
+# 1437190 - nfs-server-generator: handle 'noauto' mounts correctly.
+%patch083 -p1
+# 1389827 - "minorversion=" mount option missing in nfs(5) man page
+%patch084 -p1
+# 1432643 - segfault in rpc.gssd in find_keytab_entry
+%patch085 -p1
+# 1400106 - mountstats: handle KeyError in accumulate_iostats
+%patch086 -p1
+# 1404121 - NFS fails to mount on boot if both client and server.... 
+%patch087 -p1
+# 1424599 - sm-notify ending grace period early can inhibit... 
+%patch088 -p1
+# 1425956 - nfsstat --mounts is unrecognized option
+%patch089 -p1
+# 1432750 - Manual page bug: two inaccuracies in nfsd(7) 
+%patch090 -p1
+# 1443176 - nfsdcltrack: Unable to prepare select statement...
+%patch091 -p1
+# 1409012 - nfs-server runs before network is ready...
+%patch092 -p1
+# 1447849 - mount.nfs4 falls back to version 3 when mounting...
+%patch093 -p1
+# 1459483 - nfs-utils need to cause gssproxy reload 
+%patch094 -p1
+# 1458504 mount.nfs: NFSv4 specified mount need to start negotiation...
+%patch095 -p1
+# 1404121 - NFS fails to mount on boot if both client and....
+%patch096 -p1
+# 1389046 Pacemaker node fenced out due to redundant export...
+%patch097 -p1
 
 %patch100 -p1
 %patch101 -p1
@@ -316,7 +406,8 @@ CFLAGS="`echo $RPM_OPT_FLAGS $ARCH_OPT_FLAGS $PIE $RELRO -D_FILE_OFFSET_BITS=64`
     --enable-mountconfig \
     --enable-ipv6 \
 	--with-statdpath=/var/lib/nfs/statd \
-	--enable-libmount-mount
+	--enable-libmount-mount \
+	--with-systemd
 
 make %{?_smp_mflags} all
 
@@ -333,25 +424,24 @@ mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/modprobe.d
 make DESTDIR=$RPM_BUILD_ROOT install
 install -s -m 755 tools/rpcdebug/rpcdebug $RPM_BUILD_ROOT%{_sbindir}
 install -m 644 utils/mount/nfsmount.conf  $RPM_BUILD_ROOT%{_sysconfdir}
+install -m 644 nfs.conf $RPM_BUILD_ROOT%{_sysconfdir}
 install -m 644 %{SOURCE1} $RPM_BUILD_ROOT%{_sysconfdir}/request-key.d
 install -m 644 %{SOURCE2} $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/nfs
 
-for file in systemd/*.service  ; do
-	install -m 644 $file $RPM_BUILD_ROOT%{_unitdir}
-done
-
-for file in systemd/*.target  ; do
-	install -m 644 $file $RPM_BUILD_ROOT%{_unitdir}
-done
-
-for file in systemd/*.mount  ; do
-	install -m 644 $file $RPM_BUILD_ROOT%{_unitdir}
-done
+#
+# Don't install code that is no longer supported
+#
+rm systemd/rpc-svcgssd.service
+rm $RPM_BUILD_ROOT%{_sbindir}/rpc.svcgssd
+rm $RPM_BUILD_ROOT%{_mandir}/man8/rpc.svcgssd.8
+rm $RPM_BUILD_ROOT%{_mandir}/man8/svcgssd.8
 
 mkdir -p $RPM_BUILD_ROOT/run/sysconfig
 mkdir -p $RPM_BUILD_ROOT/usr/lib/systemd/scripts
+mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/gssproxy
 install -m 755 %{SOURCE3} $RPM_BUILD_ROOT/usr/lib/systemd/scripts/nfs-utils_env.sh
 install -m 644 %{SOURCE4} $RPM_BUILD_ROOT%{_sysconfdir}/modprobe.d/lockd.conf
+install -m 644 %{SOURCE5} $RPM_BUILD_ROOT%{_sysconfdir}/gssproxy
 
 #
 # For backwards compatablity 
@@ -360,8 +450,6 @@ cd $RPM_BUILD_ROOT%{_unitdir}
 ln -s nfs-server.service nfs.service
 ln -s rpc-gssd.service nfs-secure.service
 ln -s rpc-gssd.service rpcgssd.service
-ln -s rpc-svcgssd.service nfs-secure-server.service
-ln -s rpc-svcgssd.service rpcsvcgssd.service
 ln -s nfs-idmapd.service  nfs-idmap.service
 ln -s nfs-idmapd.service  rpcidmapd.service
 ln -s rpc-statd.service nfs-lock.service
@@ -383,7 +471,7 @@ rm -rf $RPM_BUILD_ROOT/*
 
 %pre
 # move files so the running service will have this applied as well
-for x in gssd svcgssd idmapd ; do
+for x in gssd idmapd ; do
     if [ -f /var/lock/subsys/rpc.$x ]; then
 		mv /var/lock/subsys/rpc.$x /var/lock/subsys/rpc$x
     fi
@@ -482,21 +570,19 @@ fi
 %triggerun -- nfs-utils < 1:1.2.4-2
 /bin/systemctl enable nfs-lock.service >/dev/null 2>&1 || :
 
-%triggerin -- nfs-utils < 1:1.3.0-0.2
-/bin/systemctl stop rpc-svcgssd  >/dev/null 2>&1 || :
-/bin/systemctl enable nfs-client.target  >/dev/null 2>&1 || :
-
-%triggerin -- nfs-utils > 1:1.3.0-0.1
+%triggerin -- nfs-utils > 1:1.3.0-0.39
 # reset configuration files and running daemons
 if [ $1 -eq 2 ] ; then
 	/bin/systemctl enable nfs-client.target >/dev/null 2>&1 || :
 	/bin/systemctl restart nfs-config  >/dev/null 2>&1 || :
+	/bin/systemctl reload-or-try-restart gssproxy >/dev/null 2>&1 || :
 fi
 
 %files
 %defattr(-,root,root,-)
 %config(noreplace) /etc/sysconfig/nfs
 %config(noreplace) /etc/nfsmount.conf
+%config(noreplace) /etc/nfs.conf
 %dir %{_sysconfdir}/exports.d
 %dir %{_sharedstatedir}/nfs/v4recovery
 %dir %attr(555,root,root) %{_sharedstatedir}/nfs/rpc_pipefs
@@ -510,6 +596,7 @@ fi
 %config(noreplace) %verify(not md5 size mtime) %{_sharedstatedir}/nfs/rmtab
 %config(noreplace) %{_sysconfdir}/request-key.d/id_resolver.conf
 %config(noreplace) %{_sysconfdir}/modprobe.d/lockd.conf
+%attr(0600,root,root) %config(noreplace) /%{_sysconfdir}/gssproxy/24-nfs-server.conf
 %doc linux-nfs/ChangeLog linux-nfs/KNOWNBUGS linux-nfs/NEW linux-nfs/README
 %doc linux-nfs/THANKS linux-nfs/TODO
 /sbin/rpc.statd
@@ -522,7 +609,6 @@ fi
 %{_sbindir}/showmount
 %{_sbindir}/rpc.idmapd
 %{_sbindir}/rpc.gssd
-%{_sbindir}/rpc.svcgssd
 %{_sbindir}/sm-notify
 %{_sbindir}/start-statd
 %{_sbindir}/mountstats
@@ -533,6 +619,7 @@ fi
 %{_mandir}/*/*
 %{_unitdir}/*
 %attr(755,root,root) /usr/lib/systemd/scripts/nfs-utils_env.sh
+%{_prefix}/lib/systemd/system-generators/nfs-server-generator
 
 %attr(4755,root,root)	/sbin/mount.nfs
 /sbin/mount.nfs4
@@ -540,11 +627,78 @@ fi
 /sbin/umount.nfs4
 
 %changelog
-* Thu Jan 12 2017 Steve Dickson <steved@redhat.com> 1.3.0-0.33.el7_3
-- systemd: Set var-lib-nfs-rpc_pipefs.mount After= tmpfiles (bz 1411653)
+* Mon Jun 19 2017 Steve Dickson <steved@redhat.com> 1.3.0-0.48
+- exportfs: fix path comparison in unexportfs_parsed() (bz 1389046)
+- Correctly set the minor version when set in nfsmount.conf (1458504)
+
+* Wed Jun 14 2017 Steve Dickson <steved@redhat.com> 1.3.0-0.47
+- mount.nfs: Restore errno after v3 mounts on ECONNREFUSED errors (bz 1404121)
+
+* Mon Jun 12 2017 Steve Dickson <steved@redhat.com> 1.3.0-0.46
+- Use v4 minor default on all v4 mount types (bz 1458504)
+
+* Wed Jun  7 2017 Steve Dickson <steved@redhat.com> 1.3.0-0.45
+- Restart gssproxy when the server is reloaded (bz 1459483)
+
+* Thu Jun  1 2017 Steve Dickson <steved@redhat.com> 1.3.0-0.44
+- Updated patch for bz 1447849 with the upstream version (bz 1447849)
+
+* Mon May 22 2017 Steve Dickson <steved@redhat.com> 1.3.0-0.43
+- mount: explicit v4 mounts should not roll back to v3 (bz 1447849)
+- spec: Use reload-or-try-restart to restart gssproxy (bz 1440887)
+
+* Tue May  9 2017 Steve Dickson <steved@redhat.com> 1.3.0-0.42
+- Removed RPCSVCGSSDARGS nfs.sysconfig (bz 1431218)
+
+* Thu Apr 27 2017 Steve Dickson <steved@redhat.com> 1.3.0-0.41
+- nfsdcltrack: silence some expected errors (bz 1443176)
+- Conditionally restart gssproxy now that config file is installed (bz 1440887)
+- systemd: NFS server services should use network-online (bz 1409012)
+- Cleaned up some fuzzy patches (bz 1409012)
+
+* Sat Apr  8 2017 Steve Dickson <steved@redhat.com> 1.3.0-0.40
+- gssd: ensure that preferred_realm is non-NULL (bz 1432643)
+- mountstats: handle KeyError in accumulate_iostats() (bz 1400106)
+- mount: RPC_PROGNOTREGISTERED should not be a permanent error (bz 1404121)
+- sm-notify: ending the grace period early should be configurable (bz 1424599)
+- Fixed a couple typos that effected the '--mounts' nfsstat option (bz 1425956)
+- Manual page bug: two inaccuracies in nfsd(7) (bz 1432750)
+
+* Fri Mar 31 2017 Steve Dickson <steved@redhat.com> 1.3.0-0.39
+- nfsstats: fix some exit codes (bz 1400658)
+- Added server-generator to improve ordering (bz 1437190)
+- nfsman: document minorversion (bz 1389827)
+
+* Tue Mar 28 2017 Steve Dickson <steved@redhat.com> 1.3.0-0.38
+- spec.conf: Added gssproxy server config file (bz 1431273)
+
+* Tue Mar 28 2017 Steve Dickson <steved@redhat.com> 1.3.0-0.37
+- exportfs: support "security_label" export option (bz 1435899)
+- svcgssd: Don't install code that is not suppported (bz 1431218)
+- mount.nfs: start protocol negation with v4.1 instead of v4.2 (bz 1435901)
+- nfs.conf: update nfs-conf.patch to include nfs.systemd.man (bz 1418041)
+
+* Tue Feb 28 2017 Steve Dickson <steved@redhat.com> 1.3.0-0.36
+- exportfs: remove redundant exports options output (bz 1396402)
+- Add /etc/nfs.conf support (bz 1418041)
+- gssd: Convert 'rdma' to 'tcp' protocol (bz 1386759)
+- gssd: replace non-thread-safe strtok with strsep (bz 1419280)
+- mount: fix mount fail that caused by uninitialized struct (bz 1415024)
+
+* Fri Jan  6 2017 Steve Dickson <steved@redhat.com> 1.3.0-0.35
+- Fixed -o v4 from falling back to v3 (bz 1404617)
+- systemd: Set var-lib-nfs-rpc_pipefs.mount After= tmpfiles (bz 1406164)
+- mountd: talk to kernel using file descriptors instead of FILE (bz 1409903)
+
+* Wed Dec  7 2016 Steve Dickson <steved@redhat.com> 1.3.0-0.34
+- mount.nfs: Start the mount negation with v4.2 (bz 1375259)
+- gssd: Make TCP the default protocol for GSSD connections (bz 1386759)
+- mountstats: add pNFS READs and WRITEs (bz 1377740)
+- nfsdcltrack: Fixed typo in usage string (bz 1001494)
+- mydaemon.c: Removed a warning (bz 1377914)
 
 * Wed Aug 17 2016 Scott Mayhew <smayhew@redhat.com> 1.3.0-0.33
-spec: clean up cruft left over by upgrade from older versions (bz 1203765)
+- spec: clean up cruft left over by upgrade from older versions (bz 1203765)
 
 * Thu Aug  4 2016 Steve Dickson <steved@redhat.com> 1.3.0-0.32
 - mount.nfs.man, nfs.man: Update distinction between fstypes (bz 1363737)