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 #include @@ -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 +#include + #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 +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 + +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 + #include + #include ++#include + #include + + #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 +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 + Signed-off-by: Steve Dickson + +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 + #include + #include ++#include + + #include + #include + #include + #include ++#include + #include + #include + #include +@@ -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 +Date: Thu Feb 2 06:21:15 2017 -0500 + + mount: fix mount fail that caused by uninitialized struct + + From: "Jianhong.Yin" + + 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 + Signed-off-by: Steve Dickson + +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 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; ih_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 +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 + Signed-off-by: Steve Dickson + 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 + #include ++#include ++#include + + 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 + #include + #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 + #include + #include ++ ++#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 + #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 + #include + ++#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 + #include + ++#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 + #include + ++#include "conffile.h" + #include "statd.h" + #include "nfslib.h" + #include "nfsrpc.h" +@@ -36,6 +37,7 @@ + #include + + 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 , 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 +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 + Signed-off-by: Chris Siebenmann + Signed-off-by: Steve Dickson + +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 +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 + Signed-off-by: Jeff Layton + Signed-off-by: Steve Dickson + +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 +Date: Wed Dec 7 13:35:49 2016 -0500 + + Fixed typo in usage string + + Signed-off-by: Steve Dickson + +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 \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 + #include + #include ++#include ++#include + #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 ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 + #include + #include +-#include + #include + #include + +@@ -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 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 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 1.3.0-0.47 +- mount.nfs: Restore errno after v3 mounts on ECONNREFUSED errors (bz 1404121) + +* Mon Jun 12 2017 Steve Dickson 1.3.0-0.46 +- Use v4 minor default on all v4 mount types (bz 1458504) + +* Wed Jun 7 2017 Steve Dickson 1.3.0-0.45 +- Restart gssproxy when the server is reloaded (bz 1459483) + +* Thu Jun 1 2017 Steve Dickson 1.3.0-0.44 +- Updated patch for bz 1447849 with the upstream version (bz 1447849) + +* Mon May 22 2017 Steve Dickson 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 1.3.0-0.42 +- Removed RPCSVCGSSDARGS nfs.sysconfig (bz 1431218) + +* Thu Apr 27 2017 Steve Dickson 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 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 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 1.3.0-0.38 +- spec.conf: Added gssproxy server config file (bz 1431273) + +* Tue Mar 28 2017 Steve Dickson 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 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 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 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 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 1.3.0-0.32 - mount.nfs.man, nfs.man: Update distinction between fstypes (bz 1363737)