diff --git a/nfs-utils-1.2.1-exp-subtree-warn-off.patch b/nfs-utils-1.2.1-exp-subtree-warn-off.patch deleted file mode 100644 index 7708750..0000000 --- a/nfs-utils-1.2.1-exp-subtree-warn-off.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -up nfs-utils-2.1.1/support/nfs/exports.c.orig nfs-utils-2.1.1/support/nfs/exports.c ---- nfs-utils-2.1.1/support/nfs/exports.c.orig 2017-01-12 10:21:39.000000000 -0500 -+++ nfs-utils-2.1.1/support/nfs/exports.c 2017-04-26 12:46:24.186480312 -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) - { -- int had_subtree_opt = 0; -+ int had_subtree_opt = 1; - char *flname = efname?efname:"command line"; - int flline = efp?efp->x_line:0; - unsigned int active = 0; diff --git a/nfs-utils-2.3.3-nfsconf-usegssproxy.patch b/nfs-utils-2.3.3-nfsconf-usegssproxy.patch deleted file mode 100644 index b1883ec..0000000 --- a/nfs-utils-2.3.3-nfsconf-usegssproxy.patch +++ /dev/null @@ -1,21 +0,0 @@ -diff -up nfs-utils-2.7.1/nfs.conf.orig nfs-utils-2.7.1/nfs.conf ---- nfs-utils-2.7.1/nfs.conf.orig 2024-08-20 08:30:33.000000000 -0400 -+++ nfs-utils-2.7.1/nfs.conf 2024-08-22 09:11:11.086985495 -0400 -@@ -20,7 +20,7 @@ - # rpc-verbosity=0 - # use-memcache=0 - # use-machine-creds=1 --# use-gss-proxy=0 -+use-gss-proxy=1 - # avoid-dns=1 - # limit-to-legacy-enctypes=0 - # allowed-enctypes=aes256-cts-hmac-sha384-192,aes128-cts-hmac-sha256-128,camellia256-cts-cmac,camellia128-cts-cmac,aes256-cts-hmac-sha1-96,aes128-cts-hmac-sha1-96 -@@ -97,6 +97,5 @@ rdma-port=20049 - # outgoing-port= - # outgoing-addr= - # lift-grace=y --# --[svcgssd] --# principal= -+ -+#tag1234 - Used for install purposes only diff --git a/nfs-utils-2.4.2-systemd-svcgssd.patch b/nfs-utils-2.4.2-systemd-svcgssd.patch deleted file mode 100644 index c4247b0..0000000 --- a/nfs-utils-2.4.2-systemd-svcgssd.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -up nfs-utils-2.6.2/systemd/auth-rpcgss-module.service.orig nfs-utils-2.6.2/systemd/auth-rpcgss-module.service ---- nfs-utils-2.6.2/systemd/auth-rpcgss-module.service.orig 2023-01-10 09:58:33.559453143 -0500 -+++ nfs-utils-2.6.2/systemd/auth-rpcgss-module.service 2023-01-10 10:07:27.476996363 -0500 -@@ -7,7 +7,7 @@ - [Unit] - Description=Kernel Module supporting RPCSEC_GSS - DefaultDependencies=no --Before=gssproxy.service rpc-svcgssd.service rpc-gssd.service -+Before=gssproxy.service rpc-gssd.service - Wants=gssproxy.service rpc-gssd.service - ConditionPathExists=/etc/krb5.keytab - ConditionVirtualization=!container diff --git a/nfs-utils-2.6.1-overflow.patch b/nfs-utils-2.6.1-overflow.patch deleted file mode 100644 index 1f90bb4..0000000 --- a/nfs-utils-2.6.1-overflow.patch +++ /dev/null @@ -1,31 +0,0 @@ -commit 7f8463fe702174bd613df9d308cc899af25ae02e -Author: Steve Dickson -Date: Wed Feb 23 15:19:51 2022 -0500 - - systemd: Fix format-overflow warning - - rpc-pipefs-generator.c:35:23: error: '%s' directive output between 0 and 2147483653 bytes may exceed minimum required size of 4095 [-Werror=format-overflow=] - 35 | sprintf(path, "%s/%s", dirname, pipefs_unit); - | ^ - - Signed-off-by: Steve Dickson - -diff --git a/systemd/rpc-pipefs-generator.c b/systemd/rpc-pipefs-generator.c -index c24db56..7b2bb4f 100644 ---- a/systemd/rpc-pipefs-generator.c -+++ b/systemd/rpc-pipefs-generator.c -@@ -28,11 +28,12 @@ static int generate_mount_unit(const char *pipefs_path, const char *pipefs_unit, - { - char *path; - FILE *f; -+ size_t size = (strlen(dirname) + 1 + strlen(pipefs_unit)); - -- path = malloc(strlen(dirname) + 1 + strlen(pipefs_unit)); -+ path = malloc(size); - if (!path) - return 1; -- sprintf(path, "%s/%s", dirname, pipefs_unit); -+ snprintf(path, size, "%s/%s", dirname, pipefs_unit); - f = fopen(path, "w"); - if (!f) - { diff --git a/nfs-utils-2.6.2-nfsrahead.patch b/nfs-utils-2.6.2-nfsrahead.patch deleted file mode 100644 index b006b6d..0000000 --- a/nfs-utils-2.6.2-nfsrahead.patch +++ /dev/null @@ -1,134 +0,0 @@ -diff --git a/tools/nfsrahead/main.c b/tools/nfsrahead/main.c -index b3af3aa..5fae941 100644 ---- a/tools/nfsrahead/main.c -+++ b/tools/nfsrahead/main.c -@@ -26,27 +26,31 @@ struct device_info { - }; - - /* Convert a string in the format n:m to a device number */ --static dev_t dev_from_arg(const char *device_number) -+static int fill_device_number(struct device_info *info) - { -- char *s = strdup(device_number), *p; -+ char *s = strdup(info->device_number), *p; - char *maj_s, *min_s; - unsigned int maj, min; -- dev_t dev; -+ int err = -EINVAL; - - maj_s = p = s; -- for ( ; *p != ':'; p++) -+ for ( ; *p != ':' && *p != '\0'; p++) - ; - -+ if (*p == '\0') -+ goto out_free; -+ -+ err = 0; - *p = '\0'; - min_s = p + 1; - - maj = strtol(maj_s, NULL, 10); - min = strtol(min_s, NULL, 10); - -- dev = makedev(maj, min); -- -+ info->dev = makedev(maj, min); -+out_free: - free(s); -- return dev; -+ return err; - } - - #define sfree(ptr) if (ptr) free(ptr) -@@ -55,7 +59,7 @@ static dev_t dev_from_arg(const char *device_number) - static void init_device_info(struct device_info *di, const char *device_number) - { - di->device_number = strdup(device_number); -- di->dev = dev_from_arg(device_number); -+ di->dev = 0; - di->mountpoint = NULL; - di->fstype = NULL; - } -@@ -76,11 +80,15 @@ static int get_mountinfo(const char *device_number, struct device_info *device_i - char *target; - - init_device_info(device_info, device_number); -+ if ((ret = fill_device_number(device_info)) < 0) -+ goto out_free_device_info; - - mnttbl = mnt_new_table(); - -- if ((ret = mnt_table_parse_file(mnttbl, mountinfo_path)) < 0) -+ if ((ret = mnt_table_parse_file(mnttbl, mountinfo_path)) < 0) { -+ xlog(D_GENERAL, "Failed to parse %s\n", mountinfo_path); - goto out_free_tbl; -+ } - - if ((fs = mnt_table_find_devno(mnttbl, device_info->dev, MNT_ITER_FORWARD)) == NULL) { - ret = ENOENT; -@@ -101,6 +109,7 @@ out_free_fs: - mnt_free_fs(fs); - out_free_tbl: - mnt_free_table(mnttbl); -+out_free_device_info: - free(device_info->device_number); - device_info->device_number = NULL; - return ret; -@@ -123,19 +132,20 @@ static int conf_get_readahead(const char *kind) { - - return readahead; - } --#define L_DEFAULT (L_WARNING | L_ERROR | L_FATAL) - - int main(int argc, char **argv) - { - int ret = 0, retry; - struct device_info device; -- unsigned int readahead = 128, verbose = 0, log_stderr = 0; -+ unsigned int readahead = 128, log_level, log_stderr = 0; - char opt; - -+ -+ log_level = D_ALL & ~D_GENERAL; - while((opt = getopt(argc, argv, "dF")) != -1) { - switch (opt) { - case 'd': -- verbose = 1; -+ log_level = D_ALL; - break; - case 'F': - log_stderr = 1; -@@ -147,7 +157,7 @@ int main(int argc, char **argv) - - xlog_stderr(log_stderr); - xlog_syslog(~log_stderr); -- xlog_config(L_DEFAULT | (L_NOTICE & verbose), 1); -+ xlog_config(log_level, 1); - xlog_open(CONF_NAME); - - // xlog_err causes the system to exit -@@ -159,12 +169,12 @@ int main(int argc, char **argv) - break; - - if (ret != 0) { -- xlog(L_ERROR, "unable to find device %s\n", argv[optind]); -+ xlog(D_GENERAL, "unable to find device %s\n", argv[optind]); - goto out; - } - - if (strncmp("nfs", device.fstype, 3) != 0) { -- xlog(L_NOTICE, -+ xlog(D_GENERAL, - "not setting readahead for non supported fstype %s on device %s\n", - device.fstype, argv[optind]); - ret = -EINVAL; -@@ -173,7 +183,7 @@ int main(int argc, char **argv) - - readahead = conf_get_readahead(device.fstype); - -- xlog(L_WARNING, "setting %s readahead to %d\n", device.mountpoint, readahead); -+ xlog(D_FAC7, "setting %s readahead to %d\n", device.mountpoint, readahead); - - printf("%d\n", readahead); - diff --git a/nfs-utils-2.6.3-junction-regression.patch b/nfs-utils-2.6.3-junction-regression.patch deleted file mode 100644 index 764da79..0000000 --- a/nfs-utils-2.6.3-junction-regression.patch +++ /dev/null @@ -1,26 +0,0 @@ -commit 7916134e5d9b1641effd3b6d964c806a09cfdcee -Author: Steve Dickson -Date: Thu Aug 10 11:57:39 2023 -0400 - - Fixed a regression in the junction code - - commit cdbef4e9 created a regression in the - in the junction code by adding a O_PATH flag - to the open() in junction_open_path() - - Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=2213669 - Signed-off-by: Steve Dickson - -diff --git a/support/junction/junction.c b/support/junction/junction.c -index 0628bb0f..c1ec8ff8 100644 ---- a/support/junction/junction.c -+++ b/support/junction/junction.c -@@ -63,7 +63,7 @@ junction_open_path(const char *pathname, int *fd) - if (pathname == NULL || fd == NULL) - return FEDFS_ERR_INVAL; - -- tmp = open(pathname, O_PATH|O_DIRECTORY); -+ tmp = open(pathname, O_DIRECTORY); - if (tmp == -1) { - switch (errno) { - case EPERM: diff --git a/nfs-utils-2.7.1-strip-svcgssd.patch b/nfs-utils-2.7.1-strip-svcgssd.patch new file mode 100644 index 0000000..56c6b48 --- /dev/null +++ b/nfs-utils-2.7.1-strip-svcgssd.patch @@ -0,0 +1,21 @@ +diff -up nfs-utils-2.7.1/nfs.conf.orig nfs-utils-2.7.1/nfs.conf +--- nfs-utils-2.7.1/nfs.conf.orig 2024-08-20 08:30:33.000000000 -0400 ++++ nfs-utils-2.7.1/nfs.conf 2024-08-22 11:55:19.908675564 -0400 +@@ -98,5 +98,3 @@ rdma-port=20049 + # outgoing-addr= + # lift-grace=y + # +-[svcgssd] +-# principal= +diff -up nfs-utils-2.7.1/systemd/auth-rpcgss-module.service.orig nfs-utils-2.7.1/systemd/auth-rpcgss-module.service +--- nfs-utils-2.7.1/systemd/auth-rpcgss-module.service.orig 2024-08-20 08:30:33.000000000 -0400 ++++ nfs-utils-2.7.1/systemd/auth-rpcgss-module.service 2024-08-22 11:56:40.506176120 -0400 +@@ -7,7 +7,7 @@ + [Unit] + Description=Kernel Module supporting RPCSEC_GSS + DefaultDependencies=no +-Before=gssproxy.service rpc-svcgssd.service rpc-gssd.service ++Before=gssproxy.service rpc-gssd.service + Wants=gssproxy.service rpc-gssd.service + ConditionPathExists=/etc/krb5.keytab + ConditionVirtualization=!container diff --git a/nfs-utils.2.6.3-rc6.patch b/nfs-utils.2.6.3-rc6.patch deleted file mode 100644 index cc0ac67..0000000 --- a/nfs-utils.2.6.3-rc6.patch +++ /dev/null @@ -1,1051 +0,0 @@ -diff --git a/.gitignore b/.gitignore -index df791a8..682153d 100644 ---- a/.gitignore -+++ b/.gitignore -@@ -86,3 +86,5 @@ systemd/rpc-gssd.service - cscope.* - # generic editor backup et al - *~ -+# file generated by ctags -+tags -diff --git a/NEWS b/NEWS -index e70ae8a..77872c5 100644 ---- a/NEWS -+++ b/NEWS -@@ -1,32 +1,32 @@ - Significant changes for nfs-utils 1.1.0 - March/April 2007 - -- - rpc.lockd is gone. One 3 old kernel releases need it. -- - rpc.rquotad is gone. Use the one from the 'quota' package. -- Everone else does. -+ - rpc.lockd is gone. One 3 old kernel releases need it. -+ - rpc.rquotad is gone. Use the one from the 'quota' package. -+ Everyone else does. - - /sbin/{u,}mount.nfs{,4} are now installed so 'mount' will - use these to mount nfs filesystems instead of internal code. - + mount.nfs will check for 'statd' to be running when mounting -- a filesystem which requires it. If it is not running it will -+ a filesystem which requires it. If it is not running it will - run "/usr/sbin/start-statd" to try to start it. - If statd is not running and cannot be started, mount.nfs will - refuse to mount the filesystem and will suggest the 'nolock' - option. - - Substantial changes to statd - + The 'notify' process that must happen at boot has been split -- into a separate program "sm-notify". It ensures that it -- only runs once even if you restart statd. This is correct -+ into a separate program "sm-notify". It ensures that it -+ only runs once even if you restart statd. This is correct - behaviour. - + statd stores state in the files in /var/lib/nfs/sm/ so that - if you kill and restart it, it will restore that state and - continue working correctly. - + statd makes more use of DNS lookup and should handle -- multi-homed peers better. In particular, files in -+ multi-homed peers better. In particular, files in - /var/lib/nfs/sm/ are named with the Full Qualified Domain Name - if available. - - If you export a directory as 'crossmnt', all filesystems - mounted beneath are automatically exported with the same - options (unless explicitly exported with different options). -- - subtree_check is no-longer the default. The default is now -+ - subtree_check is no-longer the default. The default is now - no_subtree_check. - - By default the system 'rpcgen' is used while building - nfs-utils rather than the internal one. -@@ -43,14 +43,14 @@ Significant changes for nfs-utils 1.1.0 - March/April 2007 - - - A new option, -n, was added to rpc.gssd which specifies that - accesses by root should not use 'machine credentials' when -- accessing NFS file systems mounted with Kerberos. Using this -+ accessing NFS file systems mounted with Kerberos. Using this - option allows the root user to access the NFS space using any - Kerberos principal, rather than always using the machine -- credentials. However, its use also requires that root manually -+ credentials. However, its use also requires that root manually - authenticate before attempting a mount with Kerberos. - - When rpc.gssd uses machine credentials, the selection algorithm has -- been changed. Instead of simply using the first "nfs/*" key in the -+ been changed. Instead of simply using the first "nfs/*" key in the - keytab, the keytab is now searched for keys in the following - defined order: - -diff --git a/README b/README -index 5e98240..3b0e771 100644 ---- a/README -+++ b/README -@@ -25,7 +25,7 @@ Unpack the sources and run these commands: - # ./configure - # make - --To install binaries and documenation, run this command: -+To install binaries and documentation, run this command: - - # make install - -@@ -40,7 +40,7 @@ Updating to the latest head after you've already got it. - - git pull - --Building requires that autotools be installed. To invoke them -+Building requires that autotools be installed. To invoke them - simply - - sh autogen.sh -@@ -70,7 +70,7 @@ scripts can be written to work correctly. - 3.1. SERVER STARTUP - - -- A/ mount -t nfsd /proc/fs/nfsd -+ A/ mount -t nfsd nfsd /proc/fs/nfsd - This filesystem needs to be mount before most daemons, - particularly exportfs, mountd, svcgssd, idmapd. - It could be mounted once, or the script that starts each daemon -@@ -95,27 +95,27 @@ scripts can be written to work correctly. - - D/ rpc.statd --no-notify - It is best if statd is started before nfsd though this isn't -- critical. Certainly it should be at most a few seconds after -+ critical. Certainly, it should be at most a few seconds after - nfsd. - When nfsd starts it will start lockd. If lockd then receives a -- lock request it will communicate with statd. If statd is not -+ lock request, it will communicate with statd. If statd is not - running lockd will retry, but it won't wait forever for a - reply. - Note that if statd is started before nfsd, the --no-notify -- option must be used. If notify requests are sent out before -+ option must be used. If notify requests are sent out before - nfsd start, clients may try to reclaim locks and, on finding - that lockd isn't running, they will give up and never reclaim - the lock. - rpc.statd is only needed for NFSv2 and NFSv3 support. - - E/ rpc.nfsd -- Starting nfsd will automatically start lockd. The nfs server -+ Starting nfsd will automatically start lockd. The nfs server - will now be fully active and respond to any requests from - clients. - - F/ sm-notify - This will notify any client which might have locks from before -- a reboot to try to reclaim their locks. This should start -+ a reboot to try to reclaim their locks. This should start - immediately after rpc.nfsd is started so that clients have a - chance to reclaim locks within the 90 second grace period. - sm-notify is only needed for NFSv2 and NFSv3 support. -diff --git a/configure.ac b/configure.ac -index f1c46c5..7672a76 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -71,18 +71,6 @@ AC_ARG_WITH(systemd, - AM_CONDITIONAL(INSTALL_SYSTEMD, [test "$use_systemd" = 1]) - AC_SUBST(unitdir) - --modprobedir=/usr/lib/modprobe.d --AC_ARG_WITH(modprobedir, -- [AS_HELP_STRING([--with-modprobedir@<:@=modprobe-dir-path@:>@],[install modprobe config files @<:@Default: /usr/lib/modprobe.d@:>@])], -- if test "$withval" != "no" ; then -- modprobedir=$withval -- else -- modprobedir= -- fi -- ) -- AM_CONDITIONAL(INSTALL_MODPROBEDIR, [test -n "$modprobedir"]) -- AC_SUBST(modprobedir) -- - AC_ARG_ENABLE(nfsv4, - [AS_HELP_STRING([--disable-nfsv4],[disable support for NFSv4 @<:@default=no@:>@])], - enable_nfsv4=$enableval, -@@ -249,6 +237,16 @@ AC_ARG_ENABLE(nfsdcld, - enable_nfsdcld=$enableval, - enable_nfsdcld="yes") - -+AC_ARG_ENABLE(nfsrahead, -+ [AS_HELP_STRING([--disable-nfsrahead],[disable nfsrahead command @<:@default=no@:>@])], -+ enable_nfsrahead=$enableval, -+ enable_nfsrahead="yes") -+ AM_CONDITIONAL(CONFIG_NFSRAHEAD, [test "$enable_nfsrahead" = "yes" ]) -+ if test "$enable_nfsrahead" = yes; then -+ dnl Check for -lmount -+ PKG_CHECK_MODULES([LIBMOUNT], [mount]) -+ fi -+ - AC_ARG_ENABLE(nfsdcltrack, - [AS_HELP_STRING([--disable-nfsdcltrack],[disable NFSv4 clientid tracking programs @<:@default=no@:>@])], - enable_nfsdcltrack=$enableval, -@@ -678,12 +676,12 @@ AC_SUBST([AM_CFLAGS], ["$my_am_cflags $flg1 $flg2 $flg3 $flg4 $flg5"]) - # Make sure that $ACLOCAL_FLAGS are used during a rebuild - AC_SUBST([ACLOCAL_AMFLAGS], ["-I $ac_macro_dir \$(ACLOCAL_FLAGS)"]) - --# make _sysconfdir available for substituion in config files -+# make _sysconfdir available for substitution in config files - # 2 "evals" needed late to expand variable names. - AC_SUBST([_sysconfdir]) - AC_CONFIG_COMMANDS_PRE([eval eval _sysconfdir=$sysconfdir]) - --# make _statedir available for substituion in config files -+# make _statedir available for substitution in config files - # 2 "evals" needed late to expand variable names. - AC_SUBST([_statedir]) - AC_CONFIG_COMMANDS_PRE([eval eval _statedir=$statedir]) -@@ -695,7 +693,7 @@ else - fi - AC_SUBST(rpc_pipefsmount) - --# make _rpc_pipefsmount available for substituion in config files -+# make _rpc_pipefsmount available for substitution in config files - # 2 "evals" needed late to expand variable names. - AC_SUBST([_rpc_pipefsmount]) - AC_CONFIG_COMMANDS_PRE([eval eval _rpc_pipefsmount=$rpc_pipefsmount]) -diff --git a/support/export/auth.c b/support/export/auth.c -index 03ce4b8..2d7960f 100644 ---- a/support/export/auth.c -+++ b/support/export/auth.c -@@ -82,7 +82,7 @@ check_useipaddr(void) - } - - unsigned int --auth_reload() -+auth_reload(void) - { - struct stat stb; - static ino_t last_inode; -diff --git a/support/export/cache.c b/support/export/cache.c -index a5823e9..2497d4f 100644 ---- a/support/export/cache.c -+++ b/support/export/cache.c -@@ -346,27 +346,27 @@ static int uuid_by_path(char *path, int type, size_t uuidlen, char *uuid) - - /* Possible sources of uuid are - * - blkid uuid -- * - statfs64 uuid -+ * - statfs uuid - * -- * On some filesystems (e.g. vfat) the statfs64 uuid is simply an -+ * On some filesystems (e.g. vfat) the statfs uuid is simply an - * encoding of the device that the filesystem is mounted from, so - * it we be very bad to use that (as device numbers change). blkid - * must be preferred. -- * On other filesystems (e.g. btrfs) the statfs64 uuid contains -+ * On other filesystems (e.g. btrfs) the statfs uuid contains - * important info that the blkid uuid cannot contain: This happens - * when multiple subvolumes are exported (they have the same -- * blkid uuid but different statfs64 uuids). -+ * blkid uuid but different statfs uuids). - * We rely on get_uuid_blkdev *knowing* which is which and not returning -- * a uuid for filesystems where the statfs64 uuid is better. -+ * a uuid for filesystems where the statfs uuid is better. - * - */ -- struct statfs64 st; -+ struct statfs st; - char fsid_val[17]; - const char *blkid_val = NULL; - const char *val; - int rc; - -- rc = nfsd_path_statfs64(path, &st); -+ rc = nfsd_path_statfs(path, &st); - - if (type == 0 && rc == 0) { - const unsigned long *bad; -diff --git a/support/export/client.c b/support/export/client.c -index ea4f89d..79164fe 100644 ---- a/support/export/client.c -+++ b/support/export/client.c -@@ -699,6 +699,9 @@ check_netgroup(const nfs_client *clp, const struct addrinfo *ai) - - /* check whether the IP itself is in the netgroup */ - ip = calloc(INET6_ADDRSTRLEN, 1); -+ if (ip == NULL) -+ goto out; -+ - if (inet_ntop(ai->ai_family, &(((struct sockaddr_in *)ai->ai_addr)->sin_addr), ip, INET6_ADDRSTRLEN) == ip) { - if (innetgr(netgroup, ip, NULL, NULL)) { - free(hname); -diff --git a/support/export/v4clients.c b/support/export/v4clients.c -index 5f15b61..3230251 100644 ---- a/support/export/v4clients.c -+++ b/support/export/v4clients.c -@@ -26,7 +26,7 @@ void v4clients_init(void) - { - struct stat sb; - -- if (!stat("/proc/fs/nfsd/clients", &sb) == 0 || -+ if (stat("/proc/fs/nfsd/clients", &sb) != 0 || - !S_ISDIR(sb.st_mode)) - return; - if (clients_fd >= 0) -diff --git a/support/export/v4root.c b/support/export/v4root.c -index c12a7d8..fbb0ad5 100644 ---- a/support/export/v4root.c -+++ b/support/export/v4root.c -@@ -198,7 +198,7 @@ static int v4root_add_parents(nfs_export *exp) - * looking for components of the v4 mount. - */ - void --v4root_set() -+v4root_set(void) - { - nfs_export *exp; - int i; -diff --git a/support/export/xtab.c b/support/export/xtab.c -index c888a80..e210ca9 100644 ---- a/support/export/xtab.c -+++ b/support/export/xtab.c -@@ -135,7 +135,7 @@ xtab_write(char *xtab, char *xtabtmp, char *lockfn, int is_export) - } - - int --xtab_export_write() -+xtab_export_write(void) - { - return xtab_write(etab.statefn, etab.tmpfn, etab.lockfn, 1); - } -diff --git a/support/include/nfsd_path.h b/support/include/nfsd_path.h -index 3b73aad..aa1e1dd 100644 ---- a/support/include/nfsd_path.h -+++ b/support/include/nfsd_path.h -@@ -7,7 +7,7 @@ - #include - - struct file_handle; --struct statfs64; -+struct statfs; - - void nfsd_path_init(void); - -@@ -18,8 +18,8 @@ char * nfsd_path_prepend_dir(const char *dir, const char *pathname); - int nfsd_path_stat(const char *pathname, struct stat *statbuf); - int nfsd_path_lstat(const char *pathname, struct stat *statbuf); - --int nfsd_path_statfs64(const char *pathname, -- struct statfs64 *statbuf); -+int nfsd_path_statfs(const char *pathname, -+ struct statfs *statbuf); - - char * nfsd_realpath(const char *path, char *resolved_path); - -diff --git a/support/junction/junction.c b/support/junction/junction.c -index 41cce26..0628bb0 100644 ---- a/support/junction/junction.c -+++ b/support/junction/junction.c -@@ -63,7 +63,7 @@ junction_open_path(const char *pathname, int *fd) - if (pathname == NULL || fd == NULL) - return FEDFS_ERR_INVAL; - -- tmp = open(pathname, O_DIRECTORY); -+ tmp = open(pathname, O_PATH|O_DIRECTORY); - if (tmp == -1) { - switch (errno) { - case EPERM: -@@ -93,7 +93,7 @@ junction_is_directory(int fd, const char *path) - { - struct stat stb; - -- if (fstat(fd, &stb) == -1) { -+ if (fstatat(fd, "", &stb, AT_NO_AUTOMOUNT|AT_EMPTY_PATH) == -1) { - xlog(D_GENERAL, "%s: failed to stat %s: %m", - __func__, path); - return FEDFS_ERR_ACCESS; -@@ -121,7 +121,7 @@ junction_is_sticky_bit_set(int fd, const char *path) - { - struct stat stb; - -- if (fstat(fd, &stb) == -1) { -+ if (fstatat(fd, "", &stb, AT_NO_AUTOMOUNT|AT_EMPTY_PATH) == -1) { - xlog(D_GENERAL, "%s: failed to stat %s: %m", - __func__, path); - return FEDFS_ERR_ACCESS; -@@ -155,7 +155,7 @@ junction_set_sticky_bit(int fd, const char *path) - { - struct stat stb; - -- if (fstat(fd, &stb) == -1) { -+ if (fstatat(fd, "", &stb, AT_NO_AUTOMOUNT|AT_EMPTY_PATH) == -1) { - xlog(D_GENERAL, "%s: failed to stat %s: %m", - __func__, path); - return FEDFS_ERR_ACCESS; -@@ -393,7 +393,7 @@ junction_get_mode(const char *pathname, mode_t *mode) - if (retval != FEDFS_OK) - return retval; - -- if (fstat(fd, &stb) == -1) { -+ if (fstatat(fd, "", &stb, AT_NO_AUTOMOUNT|AT_EMPTY_PATH) == -1) { - xlog(D_GENERAL, "%s: failed to stat %s: %m", - __func__, pathname); - (void)close(fd); -diff --git a/support/misc/nfsd_path.c b/support/misc/nfsd_path.c -index 65e53c1..c3dea4f 100644 ---- a/support/misc/nfsd_path.c -+++ b/support/misc/nfsd_path.c -@@ -184,46 +184,46 @@ nfsd_path_lstat(const char *pathname, struct stat *statbuf) - return nfsd_run_stat(nfsd_wq, nfsd_lstatfunc, pathname, statbuf); - } - --struct nfsd_statfs64_data { -+struct nfsd_statfs_data { - const char *pathname; -- struct statfs64 *statbuf; -+ struct statfs *statbuf; - int ret; - int err; - }; - - static void --nfsd_statfs64func(void *data) -+nfsd_statfsfunc(void *data) - { -- struct nfsd_statfs64_data *d = data; -+ struct nfsd_statfs_data *d = data; - -- d->ret = statfs64(d->pathname, d->statbuf); -+ d->ret = statfs(d->pathname, d->statbuf); - if (d->ret < 0) - d->err = errno; - } - - static int --nfsd_run_statfs64(struct xthread_workqueue *wq, -+nfsd_run_statfs(struct xthread_workqueue *wq, - const char *pathname, -- struct statfs64 *statbuf) -+ struct statfs *statbuf) - { -- struct nfsd_statfs64_data data = { -+ struct nfsd_statfs_data data = { - pathname, - statbuf, - 0, - 0 - }; -- xthread_work_run_sync(wq, nfsd_statfs64func, &data); -+ xthread_work_run_sync(wq, nfsd_statfsfunc, &data); - if (data.ret < 0) - errno = data.err; - return data.ret; - } - - int --nfsd_path_statfs64(const char *pathname, struct statfs64 *statbuf) -+nfsd_path_statfs(const char *pathname, struct statfs *statbuf) - { - if (!nfsd_wq) -- return statfs64(pathname, statbuf); -- return nfsd_run_statfs64(nfsd_wq, pathname, statbuf); -+ return statfs(pathname, statbuf); -+ return nfsd_run_statfs(nfsd_wq, pathname, statbuf); - } - - struct nfsd_realpath_data { -diff --git a/support/nfs/xlog.c b/support/nfs/xlog.c -index e5861b9..fa125ce 100644 ---- a/support/nfs/xlog.c -+++ b/support/nfs/xlog.c -@@ -46,11 +46,13 @@ int export_errno = 0; - - static void xlog_toggle(int sig); - static struct xlog_debugfac debugnames[] = { -+ { "0", 0, }, - { "general", D_GENERAL, }, - { "call", D_CALL, }, - { "auth", D_AUTH, }, - { "parse", D_PARSE, }, - { "all", D_ALL, }, -+ { "1", D_ALL, }, - { NULL, 0, }, - }; - -@@ -119,13 +121,14 @@ xlog_sconfig(char *kind, int on) - { - struct xlog_debugfac *tbl = debugnames; - -- while (tbl->df_name != NULL && strcasecmp(tbl->df_name, kind)) -+ while (tbl->df_name != NULL && strcasecmp(tbl->df_name, kind)) - tbl++; - if (!tbl->df_name) { - xlog (L_WARNING, "Invalid debug facility: %s\n", kind); - return; - } -- xlog_config(tbl->df_fac, on); -+ if (tbl->df_fac) -+ xlog_config(tbl->df_fac, on); - } - - void -diff --git a/support/nfsidmap/regex.c b/support/nfsidmap/regex.c -index 958b4ac..8424179 100644 ---- a/support/nfsidmap/regex.c -+++ b/support/nfsidmap/regex.c -@@ -542,7 +542,7 @@ struct trans_func regex_trans = { - .gss_princ_to_grouplist = regex_gss_princ_to_grouplist, - }; - --struct trans_func *libnfsidmap_plugin_init() -+struct trans_func *libnfsidmap_plugin_init(void) - { - return (®ex_trans); - } -diff --git a/systemd/50-nfs.conf b/systemd/50-nfs.conf -deleted file mode 100644 -index 19e8ee7..0000000 ---- a/systemd/50-nfs.conf -+++ /dev/null -@@ -1,16 +0,0 @@ --# Ensure all NFS systctl settings get applied when modules load -- --# sunrpc module supports "sunrpc.*" sysctls --install sunrpc /sbin/modprobe --ignore-install sunrpc $CMDLINE_OPTS && { /sbin/sysctl -q --pattern sunrpc --system; exit 0; } -- --# rpcrdma module supports sunrpc.svc_rdma.* --install rpcrdma /sbin/modprobe --ignore-install rpcrdma $CMDLINE_OPTS && { /sbin/sysctl -q --pattern sunrpc.svc_rdma --system; exit 0; } -- --# lockd module supports "fs.nfs.nlm*" and "fs.nfs.nsm*" sysctls --install lockd /sbin/modprobe --ignore-install lockd $CMDLINE_OPTS && { /sbin/sysctl -q --pattern fs.nfs.n[sl]m --system; exit 0; } -- --# nfsv4 module supports "fs.nfs.*" sysctls (nfs_callback_tcpport and idmap_cache_timeout) --install nfsv4 /sbin/modprobe --ignore-install nfsv4 $CMDLINE_OPTS && { /sbin/sysctl -q --pattern 'fs.nfs.(nfs_callback_tcpport|idmap_cache_timeout)' --system; exit 0; } -- --# nfs module supports "fs.nfs.*" sysctls --install nfs /sbin/modprobe --ignore-install nfs $CMDLINE_OPTS && { /sbin/sysctl -q --pattern fs.nfs --system; exit 0; } -diff --git a/systemd/60-nfs.rules b/systemd/60-nfs.rules -new file mode 100644 -index 0000000..188423c ---- /dev/null -+++ b/systemd/60-nfs.rules -@@ -0,0 +1,21 @@ -+# Ensure all NFS systctl settings get applied when modules load -+ -+# sunrpc module supports "sunrpc.*" sysctls -+ACTION=="add", SUBSYSTEM=="module", KERNEL=="sunrpc", \ -+ RUN+="/sbin/sysctl -q --pattern ^sunrpc --system" -+ -+# rpcrdma module supports sunrpc.svc_rdma.* -+ACTION=="add", SUBSYSTEM=="module", KERNEL=="rpcrdma", \ -+ RUN+="/sbin/sysctl -q --pattern ^sunrpc.svc_rdma --system" -+ -+# lockd module supports "fs.nfs.nlm*" and "fs.nfs.nsm*" sysctls -+ACTION=="add", SUBSYSTEM=="module", KERNEL=="lockd", \ -+ RUN+="/sbin/sysctl -q --pattern ^fs.nfs.n[sl]m --system" -+ -+# nfsv4 module supports "fs.nfs.*" sysctls (nfs_callback_tcpport and idmap_cache_timeout) -+ACTION=="add", SUBSYSTEM=="module", KERNEL=="nfsv4", \ -+ RUN+="/sbin/sysctl -q --pattern ^fs.nfs.(nfs_callback_tcpport|idmap_cache_timeout) --system" -+ -+# nfs module supports "fs.nfs.*" sysctls -+ACTION=="add", SUBSYSTEM=="module", KERNEL=="nfs", \ -+ RUN+="/sbin/sysctl -q --pattern ^fs.nfs --system" -diff --git a/systemd/Makefile.am b/systemd/Makefile.am -index 7b5ab84..577c6a2 100644 ---- a/systemd/Makefile.am -+++ b/systemd/Makefile.am -@@ -2,7 +2,8 @@ - - MAINTAINERCLEANFILES = Makefile.in - --modprobe_files = 50-nfs.conf -+udev_rulesdir = /usr/lib/udev/rules.d/ -+udev_files = 60-nfs.rules - - unit_files = \ - nfs-client.target \ -@@ -53,7 +54,7 @@ endif - - man5_MANS = nfs.conf.man - man7_MANS = nfs.systemd.man --EXTRA_DIST = $(unit_files) $(modprobe_files) $(man5_MANS) $(man7_MANS) -+EXTRA_DIST = $(unit_files) $(udev_files) $(man5_MANS) $(man7_MANS) - - generator_dir = $(unitdir)/../system-generators - -@@ -75,14 +76,10 @@ rpc_pipefs_generator_LDADD = ../support/nfs/libnfs.la - - if INSTALL_SYSTEMD - genexec_PROGRAMS = nfs-server-generator rpc-pipefs-generator --install-data-hook: $(unit_files) $(modprobe_files) -+install-data-hook: $(unit_files) $(udev_files) - mkdir -p $(DESTDIR)/$(unitdir) - cp $(unit_files) $(DESTDIR)/$(unitdir) - cp $(rpc_pipefs_mount_file) $(DESTDIR)/$(unitdir)/$(rpc_pipefsmount) --else --install-data-hook: $(modprobe_files) --endif --if INSTALL_MODPROBEDIR -- mkdir -p $(DESTDIR)$(modprobedir) -- cp $(modprobe_files) $(DESTDIR)$(modprobedir) -+ mkdir -p $(DESTDIR)/$(udev_rulesdir) -+ cp $(udev_files) $(DESTDIR)/$(udev_rulesdir) - endif -diff --git a/systemd/auth-rpcgss-module.service b/systemd/auth-rpcgss-module.service -index 4548283..4a69a7b 100644 ---- a/systemd/auth-rpcgss-module.service -+++ b/systemd/auth-rpcgss-module.service -@@ -8,8 +8,9 @@ - Description=Kernel Module supporting RPCSEC_GSS - DefaultDependencies=no - Before=gssproxy.service rpc-svcgssd.service rpc-gssd.service --Wants=gssproxy.service rpc-svcgssd.service rpc-gssd.service -+Wants=gssproxy.service rpc-gssd.service - ConditionPathExists=/etc/krb5.keytab -+ConditionVirtualization=!container - - [Service] - Type=oneshot -diff --git a/systemd/nfs-server.service b/systemd/nfs-server.service -index b432f91..2cdd786 100644 ---- a/systemd/nfs-server.service -+++ b/systemd/nfs-server.service -@@ -15,7 +15,7 @@ After=nfsdcld.service - Before=rpc-statd-notify.service - - # GSS services dependencies and ordering --Wants=auth-rpcgss-module.service -+Wants=auth-rpcgss-module.service rpc-svcgssd.service - After=rpc-gssd.service gssproxy.service rpc-svcgssd.service - - [Service] -diff --git a/systemd/nfs.conf.man b/systemd/nfs.conf.man -index e74083e..bfd3380 100644 ---- a/systemd/nfs.conf.man -+++ b/systemd/nfs.conf.man -@@ -98,6 +98,12 @@ value, which can be one or more from the list - .BR parse , - .BR all . - When a list is given, the members should be comma-separated. -+The values -+.BR 0 -+and -+.BR 1 -+are also accepted, with '0' making no changes to the debug level, and '1' equivalent to specifying 'all'. -+ - .TP - .B general - Recognized values: -@@ -166,6 +172,7 @@ for details. - Recognized values: - .BR threads , - .BR host , -+.BR scope , - .BR port , - .BR grace-time , - .BR lease-time , -diff --git a/tools/Makefile.am b/tools/Makefile.am -index 40c17c3..48fd0cd 100644 ---- a/tools/Makefile.am -+++ b/tools/Makefile.am -@@ -12,6 +12,10 @@ if CONFIG_NFSDCLD - OPTDIRS += nfsdclddb - endif - --SUBDIRS = locktest rpcdebug nlmtest mountstats nfs-iostat rpcctl nfsdclnts nfsrahead $(OPTDIRS) -+if CONFIG_NFSRAHEAD -+OPTDIRS += nfsrahead -+endif -+ -+SUBDIRS = locktest rpcdebug nlmtest mountstats nfs-iostat rpcctl nfsdclnts $(OPTDIRS) - - MAINTAINERCLEANFILES = Makefile.in -diff --git a/tools/nfs-iostat/nfs-iostat.py b/tools/nfs-iostat/nfs-iostat.py -index 1df74ba..85294fb 100755 ---- a/tools/nfs-iostat/nfs-iostat.py -+++ b/tools/nfs-iostat/nfs-iostat.py -@@ -43,7 +43,7 @@ NfsEventCounters = [ - 'vfspermission', - 'vfsupdatepage', - 'vfsreadpage', -- 'vfsreadpages', -+ 'vfsreadpages', # or vfsreadahead in statvers=1.2 or above - 'vfswritepage', - 'vfswritepages', - 'vfsreaddir', -@@ -86,14 +86,14 @@ class DeviceData: - self.__nfs_data['export'] = words[1] - self.__nfs_data['mountpoint'] = words[4] - self.__nfs_data['fstype'] = words[7] -- if words[7] == 'nfs': -- self.__nfs_data['statvers'] = words[8] -+ if words[7] == 'nfs' or words[7] == 'nfs4': -+ self.__nfs_data['statvers'] = float(words[8].split('=',1)[1]) - elif 'nfs' in words or 'nfs4' in words: - self.__nfs_data['export'] = words[0] - self.__nfs_data['mountpoint'] = words[3] - self.__nfs_data['fstype'] = words[6] - if words[6] == 'nfs': -- self.__nfs_data['statvers'] = words[7] -+ self.__nfs_data['statvers'] = float(words[7].split('=',1)[1]) - elif words[0] == 'age:': - self.__nfs_data['age'] = int(words[1]) - elif words[0] == 'opts:': -@@ -294,8 +294,11 @@ class DeviceData: - print() - print('%d nfs_readpage() calls read %d pages' % \ - (vfsreadpage, vfsreadpage)) -- print('%d nfs_readpages() calls read %d pages' % \ -- (vfsreadpages, pages_read - vfsreadpage)) -+ multipageread = "readpages" -+ if self.__nfs_data['statvers'] >= 1.2: -+ multipageread = "readahead" -+ print('%d nfs_%s() calls read %d pages' % \ -+ (vfsreadpages, multipageread, pages_read - vfsreadpage)) - if vfsreadpages != 0: - print('(%.1f pages per call)' % \ - (float(pages_read - vfsreadpage) / vfsreadpages)) -diff --git a/tools/nfsrahead/Makefile.am b/tools/nfsrahead/Makefile.am -index 845ea0d..7e08233 100644 ---- a/tools/nfsrahead/Makefile.am -+++ b/tools/nfsrahead/Makefile.am -@@ -1,6 +1,6 @@ - libexec_PROGRAMS = nfsrahead - nfsrahead_SOURCES = main.c --nfsrahead_LDFLAGS= -lmount -+nfsrahead_LDFLAGS= $(LIBMOUNT_LIBS) - nfsrahead_LDADD = ../../support/nfs/libnfsconf.la - - man5_MANS = nfsrahead.man -diff --git a/tools/nfsrahead/main.c b/tools/nfsrahead/main.c -index c83c6f7..8a11cf1 100644 ---- a/tools/nfsrahead/main.c -+++ b/tools/nfsrahead/main.c -@@ -167,7 +167,7 @@ int main(int argc, char **argv) - if ((ret = get_device_info(argv[optind], &device)) == 0) - break; - -- if (ret != 0) { -+ if (ret != 0 || device.fstype == NULL) { - xlog(D_GENERAL, "unable to find device %s\n", argv[optind]); - goto out; - } -diff --git a/utils/blkmapd/device-discovery.c b/utils/blkmapd/device-discovery.c -index 2736ac8..a565fdb 100644 ---- a/utils/blkmapd/device-discovery.c -+++ b/utils/blkmapd/device-discovery.c -@@ -187,10 +187,7 @@ static void bl_add_disk(char *filepath) - } - - if (disk && diskpath) { -- if (serial) { -- free(serial->data); -- free(serial); -- } -+ bl_free_scsi_string(serial); - return; - } - -@@ -228,10 +225,7 @@ static void bl_add_disk(char *filepath) - disk->size = size; - disk->valid_path = path; - } -- if (serial) { -- free(serial->data); -- free(serial); -- } -+ bl_free_scsi_string(serial); - } - return; - -@@ -241,10 +235,7 @@ static void bl_add_disk(char *filepath) - free(path->full_path); - free(path); - } -- if (serial) { -- free(serial->data); -- free(serial); -- } -+ bl_free_scsi_string(serial); - return; - } - -@@ -462,7 +453,7 @@ static void sig_die(int signal) - unlink(PID_FILE); - } - BL_LOG_ERR("exit on signal(%d)\n", signal); -- exit(1); -+ exit(0); - } - static void usage(void) - { -@@ -507,28 +498,44 @@ int main(int argc, char **argv) - if (fg) { - openlog("blkmapd", LOG_PERROR, 0); - } else { -- if (daemon(0, 0) != 0) { -- fprintf(stderr, "Daemonize failed\n"); -+ pid_t pid = fork(); -+ if (pid < 0) { -+ BL_LOG_ERR("fork error\n"); - exit(1); -+ } else if (pid != 0) { -+ pidfd = open(PID_FILE, O_WRONLY | O_CREAT, 0644); -+ if (pidfd < 0) { -+ BL_LOG_ERR("Create pid file %s failed\n", PID_FILE); -+ exit(1); -+ } -+ -+ if (lockf(pidfd, F_TLOCK, 0) < 0) { -+ BL_LOG_ERR("Already running; Exiting!"); -+ close(pidfd); -+ exit(1); -+ } -+ if (ftruncate(pidfd, 0) < 0) -+ BL_LOG_ERR("ftruncate on %s failed: m\n", PID_FILE); -+ sprintf(pidbuf, "%d\n", pid); -+ if (write(pidfd, pidbuf, strlen(pidbuf)) != (ssize_t)strlen(pidbuf)) -+ BL_LOG_ERR("write on %s failed: m\n", PID_FILE); -+ exit(0); - } - -- openlog("blkmapd", LOG_PID, 0); -- pidfd = open(PID_FILE, O_WRONLY | O_CREAT, 0644); -- if (pidfd < 0) { -- BL_LOG_ERR("Create pid file %s failed\n", PID_FILE); -- exit(1); -+ (void)setsid(); -+ if (chdir("/")) { -+ BL_LOG_ERR("chdir error\n"); - } -+ int fd = open("/dev/null", O_RDWR, 0); -+ if (fd >= 0) { -+ (void)dup2(fd, STDIN_FILENO); -+ (void)dup2(fd, STDOUT_FILENO); -+ (void)dup2(fd, STDERR_FILENO); - -- if (lockf(pidfd, F_TLOCK, 0) < 0) { -- BL_LOG_ERR("Already running; Exiting!"); -- close(pidfd); -- exit(1); -+ (void)close(fd); - } -- if (ftruncate(pidfd, 0) < 0) -- BL_LOG_WARNING("ftruncate on %s failed: m\n", PID_FILE); -- sprintf(pidbuf, "%d\n", getpid()); -- if (write(pidfd, pidbuf, strlen(pidbuf)) != (ssize_t)strlen(pidbuf)) -- BL_LOG_WARNING("write on %s failed: m\n", PID_FILE); -+ -+ openlog("blkmapd", LOG_PID, 0); - } - - signal(SIGINT, sig_die); -diff --git a/utils/blkmapd/device-discovery.h b/utils/blkmapd/device-discovery.h -index a86eed9..462aa94 100644 ---- a/utils/blkmapd/device-discovery.h -+++ b/utils/blkmapd/device-discovery.h -@@ -151,6 +151,8 @@ uint64_t process_deviceinfo(const char *dev_addr_buf, - - extern ssize_t atomicio(ssize_t(*f) (int, void *, size_t), - int fd, void *_s, size_t n); -+extern struct bl_serial *bl_create_scsi_string(int len, const char *bytes); -+extern void bl_free_scsi_string(struct bl_serial *str); - extern struct bl_serial *bldev_read_serial(int fd, const char *filename); - extern enum bl_path_state_e bldev_read_ap_state(int fd); - extern int bl_discover_devices(void); -diff --git a/utils/blkmapd/device-inq.c b/utils/blkmapd/device-inq.c -index c7952c3..9e5749e 100644 ---- a/utils/blkmapd/device-inq.c -+++ b/utils/blkmapd/device-inq.c -@@ -53,7 +53,7 @@ - #define DEF_ALLOC_LEN 255 - #define MX_ALLOC_LEN (0xc000 + 0x80) - --static struct bl_serial *bl_create_scsi_string(int len, const char *bytes) -+struct bl_serial *bl_create_scsi_string(int len, const char *bytes) - { - struct bl_serial *s; - -@@ -66,7 +66,7 @@ static struct bl_serial *bl_create_scsi_string(int len, const char *bytes) - return s; - } - --static void bl_free_scsi_string(struct bl_serial *str) -+void bl_free_scsi_string(struct bl_serial *str) - { - if (str) - free(str); -diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c -index 6ba615d..6d79a5b 100644 ---- a/utils/exportfs/exportfs.c -+++ b/utils/exportfs/exportfs.c -@@ -69,14 +69,14 @@ static int _lockfd = -1; - * need these additional lockfile() routines. - */ - static void --grab_lockfile() -+grab_lockfile(void) - { - _lockfd = open(lockfile, O_CREAT|O_RDWR, 0666); - if (_lockfd != -1) - lockf(_lockfd, F_LOCK, 0); - } - static void --release_lockfile() -+release_lockfile(void) - { - if (_lockfd != -1) { - lockf(_lockfd, F_ULOCK, 0); -@@ -513,7 +513,7 @@ validate_export(nfs_export *exp) - */ - struct stat stb; - char *path = exportent_realpath(&exp->m_export); -- struct statfs64 stf; -+ struct statfs stf; - int fs_has_fsid = 0; - - if (stat(path, &stb) < 0) { -@@ -528,7 +528,7 @@ validate_export(nfs_export *exp) - if (!can_test()) - return; - -- if (!statfs64(path, &stf) && -+ if (!statfs(path, &stf) && - (stf.f_fsid.__val[0] || stf.f_fsid.__val[1])) - fs_has_fsid = 1; - -diff --git a/utils/idmapd/idmapd.c b/utils/idmapd/idmapd.c -index e79c124..cd9a965 100644 ---- a/utils/idmapd/idmapd.c -+++ b/utils/idmapd/idmapd.c -@@ -867,7 +867,7 @@ nfsdreopen_one(struct idmap_client *ic) - } - - static void --nfsdreopen() -+nfsdreopen(void) - { - nfsdreopen_one(&nfsd_ic[IC_NAMEID]); - nfsdreopen_one(&nfsd_ic[IC_IDNAME]); -diff --git a/utils/mount/network.c b/utils/mount/network.c -index ed2f825..01ead49 100644 ---- a/utils/mount/network.c -+++ b/utils/mount/network.c -@@ -179,7 +179,7 @@ static const unsigned long probe_mnt3_only[] = { - - static const unsigned int *nfs_default_proto(void); - #ifdef MOUNT_CONFIG --static const unsigned int *nfs_default_proto() -+static const unsigned int *nfs_default_proto(void) - { - extern unsigned long config_default_proto; - /* -diff --git a/utils/mount/parse_dev.c b/utils/mount/parse_dev.c -index 0d3bcb9..2ade5d5 100644 ---- a/utils/mount/parse_dev.c -+++ b/utils/mount/parse_dev.c -@@ -170,7 +170,8 @@ static int nfs_parse_square_bracket(const char *dev, - if (pathname) { - *pathname = strndup(cbrace, path_len); - if (*pathname == NULL) { -- free(*hostname); -+ if (hostname) -+ free(*hostname); - return nfs_pdn_nomem_err(); - } - } -diff --git a/utils/nfsd/nfsd.c b/utils/nfsd/nfsd.c -index 4016a76..249df00 100644 ---- a/utils/nfsd/nfsd.c -+++ b/utils/nfsd/nfsd.c -@@ -23,6 +23,7 @@ - #include - #include - #include -+#include - - #include "conffile.h" - #include "nfslib.h" -@@ -39,6 +40,7 @@ static void usage(const char *); - static struct option longopts[] = - { - { "host", 1, 0, 'H' }, -+ { "scope", 1, 0, 'S'}, - { "help", 0, 0, 'h' }, - { "no-nfs-version", 1, 0, 'N' }, - { "nfs-version", 1, 0, 'V' }, -@@ -69,6 +71,7 @@ main(int argc, char **argv) - int count = NFSD_NPROC, c, i, error = 0, portnum, fd, found_one; - char *p, *progname, *port, *rdma_port = NULL; - char **haddr = NULL; -+ char *scope = NULL; - int hcounter = 0; - struct conf_list *hosts; - int socket_up = 0; -@@ -168,8 +171,9 @@ main(int argc, char **argv) - hcounter++; - } - } -+ scope = conf_get_str("nfsd", "scope"); - -- while ((c = getopt_long(argc, argv, "dH:hN:V:p:P:stTuUrG:L:", longopts, NULL)) != EOF) { -+ while ((c = getopt_long(argc, argv, "dH:S:hN:V:p:P:stTuUrG:L:", longopts, NULL)) != EOF) { - switch(c) { - case 'd': - xlog_config(D_ALL, 1); -@@ -190,6 +194,9 @@ main(int argc, char **argv) - haddr[hcounter] = optarg; - hcounter++; - break; -+ case 'S': -+ scope = optarg; -+ break; - case 'P': /* XXX for nfs-server compatibility */ - case 'p': - /* only the last -p option has any effect */ -@@ -367,6 +374,14 @@ main(int argc, char **argv) - if (lease > 0) - nfssvc_set_time("lease", lease); - -+ if (scope) { -+ if (unshare(CLONE_NEWUTS) < 0 || -+ sethostname(scope, strlen(scope)) < 0) { -+ xlog(L_ERROR, "Unable to set server scope: %m"); -+ error = -1; -+ goto out; -+ } -+ } - i = 0; - do { - error = nfssvc_set_sockets(protobits, haddr[i], port); -diff --git a/utils/nfsd/nfsd.man b/utils/nfsd/nfsd.man -index 634b8a6..dc05f36 100644 ---- a/utils/nfsd/nfsd.man -+++ b/utils/nfsd/nfsd.man -@@ -35,9 +35,17 @@ Note that - .B lockd - (which performs file locking services for NFS) may still accept - request on all known network addresses. This may change in future --releases of the Linux Kernel. This option can be used multiple time -+releases of the Linux Kernel. This option can be used multiple times - to listen to more than one interface. - .TP -+.B \S " or " \-\-scope scope -+NFSv4.1 and later require the server to report a "scope" which is used -+by the clients to detect if two connections are to the same server. -+By default Linux NFSD uses the host name as the scope. -+.sp -+It is particularly important for high-availablity configurations to ensure -+that all potential server nodes report the same server scope. -+.TP - .B \-p " or " \-\-port port - specify a different port to listen on for NFS requests. By default, - .B rpc.nfsd -@@ -134,6 +142,9 @@ will listen on. Use of the - .B --host - option replaces all host names listed here. - .TP -+.B scope -+Set the server scope. -+.TP - .B grace-time - The grace time, for both NFSv4 and NLM, in seconds. - .TP -@@ -159,7 +170,9 @@ Enable or disable TCP support. - .B vers3 - .TP - .B vers4 --Enable or disable a major NFS version. 3 and 4 are normally enabled -+Enable or disable -+.B all -+NFSv4 versions. All versions are normally enabled - by default. - .TP - .B vers4.1 diff --git a/nfs-utils.2.6.3-rc8.patch b/nfs-utils.2.6.3-rc8.patch deleted file mode 100644 index 5dbbbfd..0000000 --- a/nfs-utils.2.6.3-rc8.patch +++ /dev/null @@ -1,1587 +0,0 @@ -diff --git a/.gitignore b/.gitignore -index df791a83..682153d5 100644 ---- a/.gitignore -+++ b/.gitignore -@@ -86,3 +86,5 @@ systemd/rpc-gssd.service - cscope.* - # generic editor backup et al - *~ -+# file generated by ctags -+tags -diff --git a/NEWS b/NEWS -index e70ae8ab..77872c5a 100644 ---- a/NEWS -+++ b/NEWS -@@ -1,32 +1,32 @@ - Significant changes for nfs-utils 1.1.0 - March/April 2007 - -- - rpc.lockd is gone. One 3 old kernel releases need it. -- - rpc.rquotad is gone. Use the one from the 'quota' package. -- Everone else does. -+ - rpc.lockd is gone. One 3 old kernel releases need it. -+ - rpc.rquotad is gone. Use the one from the 'quota' package. -+ Everyone else does. - - /sbin/{u,}mount.nfs{,4} are now installed so 'mount' will - use these to mount nfs filesystems instead of internal code. - + mount.nfs will check for 'statd' to be running when mounting -- a filesystem which requires it. If it is not running it will -+ a filesystem which requires it. If it is not running it will - run "/usr/sbin/start-statd" to try to start it. - If statd is not running and cannot be started, mount.nfs will - refuse to mount the filesystem and will suggest the 'nolock' - option. - - Substantial changes to statd - + The 'notify' process that must happen at boot has been split -- into a separate program "sm-notify". It ensures that it -- only runs once even if you restart statd. This is correct -+ into a separate program "sm-notify". It ensures that it -+ only runs once even if you restart statd. This is correct - behaviour. - + statd stores state in the files in /var/lib/nfs/sm/ so that - if you kill and restart it, it will restore that state and - continue working correctly. - + statd makes more use of DNS lookup and should handle -- multi-homed peers better. In particular, files in -+ multi-homed peers better. In particular, files in - /var/lib/nfs/sm/ are named with the Full Qualified Domain Name - if available. - - If you export a directory as 'crossmnt', all filesystems - mounted beneath are automatically exported with the same - options (unless explicitly exported with different options). -- - subtree_check is no-longer the default. The default is now -+ - subtree_check is no-longer the default. The default is now - no_subtree_check. - - By default the system 'rpcgen' is used while building - nfs-utils rather than the internal one. -@@ -43,14 +43,14 @@ Significant changes for nfs-utils 1.1.0 - March/April 2007 - - - A new option, -n, was added to rpc.gssd which specifies that - accesses by root should not use 'machine credentials' when -- accessing NFS file systems mounted with Kerberos. Using this -+ accessing NFS file systems mounted with Kerberos. Using this - option allows the root user to access the NFS space using any - Kerberos principal, rather than always using the machine -- credentials. However, its use also requires that root manually -+ credentials. However, its use also requires that root manually - authenticate before attempting a mount with Kerberos. - - When rpc.gssd uses machine credentials, the selection algorithm has -- been changed. Instead of simply using the first "nfs/*" key in the -+ been changed. Instead of simply using the first "nfs/*" key in the - keytab, the keytab is now searched for keys in the following - defined order: - -diff --git a/README b/README -index 5e982409..3b0e771f 100644 ---- a/README -+++ b/README -@@ -25,7 +25,7 @@ Unpack the sources and run these commands: - # ./configure - # make - --To install binaries and documenation, run this command: -+To install binaries and documentation, run this command: - - # make install - -@@ -40,7 +40,7 @@ Updating to the latest head after you've already got it. - - git pull - --Building requires that autotools be installed. To invoke them -+Building requires that autotools be installed. To invoke them - simply - - sh autogen.sh -@@ -70,7 +70,7 @@ scripts can be written to work correctly. - 3.1. SERVER STARTUP - - -- A/ mount -t nfsd /proc/fs/nfsd -+ A/ mount -t nfsd nfsd /proc/fs/nfsd - This filesystem needs to be mount before most daemons, - particularly exportfs, mountd, svcgssd, idmapd. - It could be mounted once, or the script that starts each daemon -@@ -95,27 +95,27 @@ scripts can be written to work correctly. - - D/ rpc.statd --no-notify - It is best if statd is started before nfsd though this isn't -- critical. Certainly it should be at most a few seconds after -+ critical. Certainly, it should be at most a few seconds after - nfsd. - When nfsd starts it will start lockd. If lockd then receives a -- lock request it will communicate with statd. If statd is not -+ lock request, it will communicate with statd. If statd is not - running lockd will retry, but it won't wait forever for a - reply. - Note that if statd is started before nfsd, the --no-notify -- option must be used. If notify requests are sent out before -+ option must be used. If notify requests are sent out before - nfsd start, clients may try to reclaim locks and, on finding - that lockd isn't running, they will give up and never reclaim - the lock. - rpc.statd is only needed for NFSv2 and NFSv3 support. - - E/ rpc.nfsd -- Starting nfsd will automatically start lockd. The nfs server -+ Starting nfsd will automatically start lockd. The nfs server - will now be fully active and respond to any requests from - clients. - - F/ sm-notify - This will notify any client which might have locks from before -- a reboot to try to reclaim their locks. This should start -+ a reboot to try to reclaim their locks. This should start - immediately after rpc.nfsd is started so that clients have a - chance to reclaim locks within the 90 second grace period. - sm-notify is only needed for NFSv2 and NFSv3 support. -diff --git a/configure.ac b/configure.ac -index f1c46c5c..7672a760 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -71,18 +71,6 @@ AC_ARG_WITH(systemd, - AM_CONDITIONAL(INSTALL_SYSTEMD, [test "$use_systemd" = 1]) - AC_SUBST(unitdir) - --modprobedir=/usr/lib/modprobe.d --AC_ARG_WITH(modprobedir, -- [AS_HELP_STRING([--with-modprobedir@<:@=modprobe-dir-path@:>@],[install modprobe config files @<:@Default: /usr/lib/modprobe.d@:>@])], -- if test "$withval" != "no" ; then -- modprobedir=$withval -- else -- modprobedir= -- fi -- ) -- AM_CONDITIONAL(INSTALL_MODPROBEDIR, [test -n "$modprobedir"]) -- AC_SUBST(modprobedir) -- - AC_ARG_ENABLE(nfsv4, - [AS_HELP_STRING([--disable-nfsv4],[disable support for NFSv4 @<:@default=no@:>@])], - enable_nfsv4=$enableval, -@@ -249,6 +237,16 @@ AC_ARG_ENABLE(nfsdcld, - enable_nfsdcld=$enableval, - enable_nfsdcld="yes") - -+AC_ARG_ENABLE(nfsrahead, -+ [AS_HELP_STRING([--disable-nfsrahead],[disable nfsrahead command @<:@default=no@:>@])], -+ enable_nfsrahead=$enableval, -+ enable_nfsrahead="yes") -+ AM_CONDITIONAL(CONFIG_NFSRAHEAD, [test "$enable_nfsrahead" = "yes" ]) -+ if test "$enable_nfsrahead" = yes; then -+ dnl Check for -lmount -+ PKG_CHECK_MODULES([LIBMOUNT], [mount]) -+ fi -+ - AC_ARG_ENABLE(nfsdcltrack, - [AS_HELP_STRING([--disable-nfsdcltrack],[disable NFSv4 clientid tracking programs @<:@default=no@:>@])], - enable_nfsdcltrack=$enableval, -@@ -678,12 +676,12 @@ AC_SUBST([AM_CFLAGS], ["$my_am_cflags $flg1 $flg2 $flg3 $flg4 $flg5"]) - # Make sure that $ACLOCAL_FLAGS are used during a rebuild - AC_SUBST([ACLOCAL_AMFLAGS], ["-I $ac_macro_dir \$(ACLOCAL_FLAGS)"]) - --# make _sysconfdir available for substituion in config files -+# make _sysconfdir available for substitution in config files - # 2 "evals" needed late to expand variable names. - AC_SUBST([_sysconfdir]) - AC_CONFIG_COMMANDS_PRE([eval eval _sysconfdir=$sysconfdir]) - --# make _statedir available for substituion in config files -+# make _statedir available for substitution in config files - # 2 "evals" needed late to expand variable names. - AC_SUBST([_statedir]) - AC_CONFIG_COMMANDS_PRE([eval eval _statedir=$statedir]) -@@ -695,7 +693,7 @@ else - fi - AC_SUBST(rpc_pipefsmount) - --# make _rpc_pipefsmount available for substituion in config files -+# make _rpc_pipefsmount available for substitution in config files - # 2 "evals" needed late to expand variable names. - AC_SUBST([_rpc_pipefsmount]) - AC_CONFIG_COMMANDS_PRE([eval eval _rpc_pipefsmount=$rpc_pipefsmount]) -diff --git a/support/export/auth.c b/support/export/auth.c -index 03ce4b8a..2d7960f1 100644 ---- a/support/export/auth.c -+++ b/support/export/auth.c -@@ -82,7 +82,7 @@ check_useipaddr(void) - } - - unsigned int --auth_reload() -+auth_reload(void) - { - struct stat stb; - static ino_t last_inode; -diff --git a/support/export/cache.c b/support/export/cache.c -index a5823e92..0a37703b 100644 ---- a/support/export/cache.c -+++ b/support/export/cache.c -@@ -346,27 +346,27 @@ static int uuid_by_path(char *path, int type, size_t uuidlen, char *uuid) - - /* Possible sources of uuid are - * - blkid uuid -- * - statfs64 uuid -+ * - statfs uuid - * -- * On some filesystems (e.g. vfat) the statfs64 uuid is simply an -+ * On some filesystems (e.g. vfat) the statfs uuid is simply an - * encoding of the device that the filesystem is mounted from, so - * it we be very bad to use that (as device numbers change). blkid - * must be preferred. -- * On other filesystems (e.g. btrfs) the statfs64 uuid contains -+ * On other filesystems (e.g. btrfs) the statfs uuid contains - * important info that the blkid uuid cannot contain: This happens - * when multiple subvolumes are exported (they have the same -- * blkid uuid but different statfs64 uuids). -+ * blkid uuid but different statfs uuids). - * We rely on get_uuid_blkdev *knowing* which is which and not returning -- * a uuid for filesystems where the statfs64 uuid is better. -+ * a uuid for filesystems where the statfs uuid is better. - * - */ -- struct statfs64 st; -+ struct statfs st; - char fsid_val[17]; - const char *blkid_val = NULL; - const char *val; - int rc; - -- rc = nfsd_path_statfs64(path, &st); -+ rc = nfsd_path_statfs(path, &st); - - if (type == 0 && rc == 0) { - const unsigned long *bad; -@@ -410,12 +410,16 @@ static char *next_mnt(void **v, char *p) - *v = f; - } else - f = *v; -- while ((me = getmntent(f)) != NULL && l > 1) { -+ while ((me = getmntent(f)) != NULL && l >= 1) { - char *mnt_dir = nfsd_path_strip_root(me->mnt_dir); - - if (!mnt_dir) - continue; - -+ /* Everything below "/" is a proper sub-mount */ -+ if (strcmp(p, "/") == 0) -+ return mnt_dir; -+ - if (strncmp(mnt_dir, p, l) == 0 && mnt_dir[l] == '/') - return mnt_dir; - } -@@ -932,6 +936,7 @@ static void write_fsloc(char **bp, int *blen, struct exportent *ep) - release_replicas(servers); - } - #endif -+ - static void write_secinfo(char **bp, int *blen, struct exportent *ep, int flag_mask) - { - struct sec_entry *p; -@@ -949,7 +954,20 @@ static void write_secinfo(char **bp, int *blen, struct exportent *ep, int flag_m - qword_addint(bp, blen, p->flav->fnum); - qword_addint(bp, blen, p->flags & flag_mask); - } -+} -+ -+static void write_xprtsec(char **bp, int *blen, struct exportent *ep) -+{ -+ struct xprtsec_entry *p; -+ -+ for (p = ep->e_xprtsec; p->info; p++); -+ if (p == ep->e_xprtsec) -+ return; - -+ qword_add(bp, blen, "xprtsec"); -+ qword_addint(bp, blen, p - ep->e_xprtsec); -+ for (p = ep->e_xprtsec; p->info; p++) -+ qword_addint(bp, blen, p->info->number); - } - - static int dump_to_cache(int f, char *buf, int blen, char *domain, -@@ -992,6 +1010,7 @@ static int dump_to_cache(int f, char *buf, int blen, char *domain, - qword_add(&bp, &blen, "uuid"); - qword_addhex(&bp, &blen, u, 16); - } -+ write_xprtsec(&bp, &blen, exp); - xlog(D_AUTH, "granted access to %s for %s", - path, *domain == '$' ? domain+1 : domain); - } else { -diff --git a/support/export/client.c b/support/export/client.c -index ea4f89d3..79164fef 100644 ---- a/support/export/client.c -+++ b/support/export/client.c -@@ -699,6 +699,9 @@ check_netgroup(const nfs_client *clp, const struct addrinfo *ai) - - /* check whether the IP itself is in the netgroup */ - ip = calloc(INET6_ADDRSTRLEN, 1); -+ if (ip == NULL) -+ goto out; -+ - if (inet_ntop(ai->ai_family, &(((struct sockaddr_in *)ai->ai_addr)->sin_addr), ip, INET6_ADDRSTRLEN) == ip) { - if (innetgr(netgroup, ip, NULL, NULL)) { - free(hname); -diff --git a/support/export/v4clients.c b/support/export/v4clients.c -index 5f15b614..32302512 100644 ---- a/support/export/v4clients.c -+++ b/support/export/v4clients.c -@@ -26,7 +26,7 @@ void v4clients_init(void) - { - struct stat sb; - -- if (!stat("/proc/fs/nfsd/clients", &sb) == 0 || -+ if (stat("/proc/fs/nfsd/clients", &sb) != 0 || - !S_ISDIR(sb.st_mode)) - return; - if (clients_fd >= 0) -diff --git a/support/export/v4root.c b/support/export/v4root.c -index c12a7d85..fbb0ad5f 100644 ---- a/support/export/v4root.c -+++ b/support/export/v4root.c -@@ -198,7 +198,7 @@ static int v4root_add_parents(nfs_export *exp) - * looking for components of the v4 mount. - */ - void --v4root_set() -+v4root_set(void) - { - nfs_export *exp; - int i; -diff --git a/support/export/xtab.c b/support/export/xtab.c -index c888a80a..e210ca99 100644 ---- a/support/export/xtab.c -+++ b/support/export/xtab.c -@@ -135,7 +135,7 @@ xtab_write(char *xtab, char *xtabtmp, char *lockfn, int is_export) - } - - int --xtab_export_write() -+xtab_export_write(void) - { - return xtab_write(etab.statefn, etab.tmpfn, etab.lockfn, 1); - } -diff --git a/support/include/nfs/export.h b/support/include/nfs/export.h -index 0eca828e..be5867cf 100644 ---- a/support/include/nfs/export.h -+++ b/support/include/nfs/export.h -@@ -40,4 +40,18 @@ - #define NFSEXP_OLD_SECINFO_FLAGS (NFSEXP_READONLY | NFSEXP_ROOTSQUASH \ - | NFSEXP_ALLSQUASH) - -+/* -+ * Transport layer security policies that are permitted to access -+ * an export -+ */ -+#define NFSEXP_XPRTSEC_NONE 0x0001 -+#define NFSEXP_XPRTSEC_TLS 0x0002 -+#define NFSEXP_XPRTSEC_MTLS 0x0004 -+ -+#define NFSEXP_XPRTSEC_NUM (3) -+ -+#define NFSEXP_XPRTSEC_ALL (NFSEXP_XPRTSEC_NONE | \ -+ NFSEXP_XPRTSEC_TLS | \ -+ NFSEXP_XPRTSEC_MTLS) -+ - #endif /* _NSF_EXPORT_H */ -diff --git a/support/include/nfsd_path.h b/support/include/nfsd_path.h -index 3b73aadd..aa1e1dd0 100644 ---- a/support/include/nfsd_path.h -+++ b/support/include/nfsd_path.h -@@ -7,7 +7,7 @@ - #include - - struct file_handle; --struct statfs64; -+struct statfs; - - void nfsd_path_init(void); - -@@ -18,8 +18,8 @@ char * nfsd_path_prepend_dir(const char *dir, const char *pathname); - int nfsd_path_stat(const char *pathname, struct stat *statbuf); - int nfsd_path_lstat(const char *pathname, struct stat *statbuf); - --int nfsd_path_statfs64(const char *pathname, -- struct statfs64 *statbuf); -+int nfsd_path_statfs(const char *pathname, -+ struct statfs *statbuf); - - char * nfsd_realpath(const char *path, char *resolved_path); - -diff --git a/support/include/nfslib.h b/support/include/nfslib.h -index 6faba71b..61c19933 100644 ---- a/support/include/nfslib.h -+++ b/support/include/nfslib.h -@@ -62,6 +62,18 @@ struct sec_entry { - int flags; - }; - -+#define XPRTSECMODE_COUNT 3 -+ -+struct xprtsec_info { -+ const char *name; -+ int number; -+}; -+ -+struct xprtsec_entry { -+ const struct xprtsec_info *info; -+ int flags; -+}; -+ - /* - * Data related to a single exports entry as returned by getexportent. - * FIXME: export options should probably be parsed at a later time to -@@ -83,6 +95,7 @@ struct exportent { - char * e_fslocdata; - char * e_uuid; - struct sec_entry e_secinfo[SECFLAVOR_COUNT+1]; -+ struct xprtsec_entry e_xprtsec[XPRTSECMODE_COUNT + 1]; - unsigned int e_ttl; - char * e_realpath; - }; -@@ -99,6 +112,7 @@ struct rmtabent { - void setexportent(char *fname, char *type); - struct exportent * getexportent(int,int); - void secinfo_show(FILE *fp, struct exportent *ep); -+void xprtsecinfo_show(FILE *fp, struct exportent *ep); - void putexportent(struct exportent *xep); - void endexportent(void); - struct exportent * mkexportent(char *hname, char *path, char *opts); -diff --git a/support/junction/junction.c b/support/junction/junction.c -index 41cce261..0628bb0f 100644 ---- a/support/junction/junction.c -+++ b/support/junction/junction.c -@@ -63,7 +63,7 @@ junction_open_path(const char *pathname, int *fd) - if (pathname == NULL || fd == NULL) - return FEDFS_ERR_INVAL; - -- tmp = open(pathname, O_DIRECTORY); -+ tmp = open(pathname, O_PATH|O_DIRECTORY); - if (tmp == -1) { - switch (errno) { - case EPERM: -@@ -93,7 +93,7 @@ junction_is_directory(int fd, const char *path) - { - struct stat stb; - -- if (fstat(fd, &stb) == -1) { -+ if (fstatat(fd, "", &stb, AT_NO_AUTOMOUNT|AT_EMPTY_PATH) == -1) { - xlog(D_GENERAL, "%s: failed to stat %s: %m", - __func__, path); - return FEDFS_ERR_ACCESS; -@@ -121,7 +121,7 @@ junction_is_sticky_bit_set(int fd, const char *path) - { - struct stat stb; - -- if (fstat(fd, &stb) == -1) { -+ if (fstatat(fd, "", &stb, AT_NO_AUTOMOUNT|AT_EMPTY_PATH) == -1) { - xlog(D_GENERAL, "%s: failed to stat %s: %m", - __func__, path); - return FEDFS_ERR_ACCESS; -@@ -155,7 +155,7 @@ junction_set_sticky_bit(int fd, const char *path) - { - struct stat stb; - -- if (fstat(fd, &stb) == -1) { -+ if (fstatat(fd, "", &stb, AT_NO_AUTOMOUNT|AT_EMPTY_PATH) == -1) { - xlog(D_GENERAL, "%s: failed to stat %s: %m", - __func__, path); - return FEDFS_ERR_ACCESS; -@@ -393,7 +393,7 @@ junction_get_mode(const char *pathname, mode_t *mode) - if (retval != FEDFS_OK) - return retval; - -- if (fstat(fd, &stb) == -1) { -+ if (fstatat(fd, "", &stb, AT_NO_AUTOMOUNT|AT_EMPTY_PATH) == -1) { - xlog(D_GENERAL, "%s: failed to stat %s: %m", - __func__, pathname); - (void)close(fd); -diff --git a/support/misc/nfsd_path.c b/support/misc/nfsd_path.c -index 65e53c13..c3dea4f0 100644 ---- a/support/misc/nfsd_path.c -+++ b/support/misc/nfsd_path.c -@@ -184,46 +184,46 @@ nfsd_path_lstat(const char *pathname, struct stat *statbuf) - return nfsd_run_stat(nfsd_wq, nfsd_lstatfunc, pathname, statbuf); - } - --struct nfsd_statfs64_data { -+struct nfsd_statfs_data { - const char *pathname; -- struct statfs64 *statbuf; -+ struct statfs *statbuf; - int ret; - int err; - }; - - static void --nfsd_statfs64func(void *data) -+nfsd_statfsfunc(void *data) - { -- struct nfsd_statfs64_data *d = data; -+ struct nfsd_statfs_data *d = data; - -- d->ret = statfs64(d->pathname, d->statbuf); -+ d->ret = statfs(d->pathname, d->statbuf); - if (d->ret < 0) - d->err = errno; - } - - static int --nfsd_run_statfs64(struct xthread_workqueue *wq, -+nfsd_run_statfs(struct xthread_workqueue *wq, - const char *pathname, -- struct statfs64 *statbuf) -+ struct statfs *statbuf) - { -- struct nfsd_statfs64_data data = { -+ struct nfsd_statfs_data data = { - pathname, - statbuf, - 0, - 0 - }; -- xthread_work_run_sync(wq, nfsd_statfs64func, &data); -+ xthread_work_run_sync(wq, nfsd_statfsfunc, &data); - if (data.ret < 0) - errno = data.err; - return data.ret; - } - - int --nfsd_path_statfs64(const char *pathname, struct statfs64 *statbuf) -+nfsd_path_statfs(const char *pathname, struct statfs *statbuf) - { - if (!nfsd_wq) -- return statfs64(pathname, statbuf); -- return nfsd_run_statfs64(nfsd_wq, pathname, statbuf); -+ return statfs(pathname, statbuf); -+ return nfsd_run_statfs(nfsd_wq, pathname, statbuf); - } - - struct nfsd_realpath_data { -diff --git a/support/nfs/exports.c b/support/nfs/exports.c -index 2c8f0752..da8ace3a 100644 ---- a/support/nfs/exports.c -+++ b/support/nfs/exports.c -@@ -99,6 +99,7 @@ static void init_exportent (struct exportent *ee, int fromkernel) - ee->e_fslocmethod = FSLOC_NONE; - ee->e_fslocdata = NULL; - ee->e_secinfo[0].flav = NULL; -+ ee->e_xprtsec[0].info = NULL; - ee->e_nsquids = 0; - ee->e_nsqgids = 0; - ee->e_uuid = NULL; -@@ -122,7 +123,7 @@ getexportent(int fromkernel, int fromexports) - if (first || (ok = getexport(exp, sizeof(exp))) == 0) { - has_default_opts = 0; - has_default_subtree_opts = 0; -- -+ - init_exportent(&def_ee, fromkernel); - - ok = getpath(def_ee.e_path, sizeof(def_ee.e_path)); -@@ -146,7 +147,7 @@ getexportent(int fromkernel, int fromexports) - if (exp[0] == '-' && !fromkernel) { - if (parseopts(exp + 1, &def_ee, 0, &has_default_subtree_opts) < 0) - return NULL; -- -+ - has_default_opts = 1; - - ok = getexport(exp, sizeof(exp)); -@@ -239,7 +240,6 @@ void secinfo_show(FILE *fp, struct exportent *ep) - if (ep->e_secinfo[0].flav == NULL) - secinfo_addflavor(find_flavor("sys"), ep); - for (p1=ep->e_secinfo; p1->flav; p1=p2) { -- - fprintf(fp, ",sec=%s", p1->flav->flavour); - for (p2=p1+1; (p2->flav != NULL) && (p1->flags == p2->flags); - p2++) { -@@ -249,6 +249,17 @@ void secinfo_show(FILE *fp, struct exportent *ep) - } - } - -+void xprtsecinfo_show(FILE *fp, struct exportent *ep) -+{ -+ struct xprtsec_entry *p1, *p2; -+ -+ for (p1 = ep->e_xprtsec; p1->info; p1 = p2) { -+ fprintf(fp, ",xprtsec=%s", p1->info->name); -+ for (p2 = p1 + 1; p2->info && (p1->flags == p2->flags); p2++) -+ fprintf(fp, ":%s", p2->info->name); -+ } -+} -+ - static void - fprintpath(FILE *fp, const char *path) - { -@@ -345,6 +356,7 @@ putexportent(struct exportent *ep) - } - fprintf(fp, "anonuid=%d,anongid=%d", ep->e_anonuid, ep->e_anongid); - secinfo_show(fp, ep); -+ xprtsecinfo_show(fp, ep); - fprintf(fp, ")\n"); - } - -@@ -483,6 +495,75 @@ static unsigned int parse_flavors(char *str, struct exportent *ep) - return out; - } - -+static const struct xprtsec_info xprtsec_name2info[] = { -+ { "none", NFSEXP_XPRTSEC_NONE }, -+ { "tls", NFSEXP_XPRTSEC_TLS }, -+ { "mtls", NFSEXP_XPRTSEC_MTLS }, -+ { NULL, 0 } -+}; -+ -+static const struct xprtsec_info *find_xprtsec_info(const char *name) -+{ -+ const struct xprtsec_info *info; -+ -+ for (info = xprtsec_name2info; info->name; info++) -+ if (strcmp(info->name, name) == 0) -+ return info; -+ return NULL; -+} -+ -+/* -+ * Append the given xprtsec mode to the exportent's e_xprtsec array, -+ * or do nothing if it's already there. Returns the index of flavor in -+ * the resulting array in any case. -+ */ -+static int xprtsec_addmode(const struct xprtsec_info *info, struct exportent *ep) -+{ -+ struct xprtsec_entry *p; -+ -+ for (p = ep->e_xprtsec; p->info; p++) -+ if (p->info == info || p->info->number == info->number) -+ return p - ep->e_xprtsec; -+ -+ if (p - ep->e_xprtsec >= XPRTSECMODE_COUNT) { -+ xlog(L_ERROR, "more than %d xprtsec modes on an export\n", -+ XPRTSECMODE_COUNT); -+ return -1; -+ } -+ p->info = info; -+ p->flags = ep->e_flags; -+ (p + 1)->info = NULL; -+ return p - ep->e_xprtsec; -+} -+ -+/* -+ * @str is a colon seperated list of transport layer security modes. -+ * Their order is recorded in @ep, and a bitmap corresponding to the -+ * list is returned. -+ * -+ * A zero return indicates an error. -+ */ -+static unsigned int parse_xprtsec(char *str, struct exportent *ep) -+{ -+ unsigned int out = 0; -+ char *name; -+ -+ while ((name = strsep(&str, ":"))) { -+ const struct xprtsec_info *info = find_xprtsec_info(name); -+ int bit; -+ -+ if (!info) { -+ xlog(L_ERROR, "unknown xprtsec mode %s\n", name); -+ return 0; -+ } -+ bit = xprtsec_addmode(info, ep); -+ if (bit < 0) -+ return 0; -+ out |= 1 << bit; -+ } -+ return out; -+} -+ - /* Sets the bits in @mask for the appropriate security flavor flags. */ - static void setflags(int mask, unsigned int active, struct exportent *ep) - { -@@ -621,7 +702,7 @@ parseopts(char *cp, struct exportent *ep, int warn, int *had_subtree_opt_ptr) - ep->e_anonuid = strtol(opt+8, &oe, 10); - if (opt[8]=='\0' || *oe != '\0') { - xlog(L_ERROR, "%s: %d: bad anonuid \"%s\"\n", -- flname, flline, opt); -+ flname, flline, opt); - bad_option: - free(opt); - return -1; -@@ -631,7 +712,7 @@ bad_option: - ep->e_anongid = strtol(opt+8, &oe, 10); - if (opt[8]=='\0' || *oe != '\0') { - xlog(L_ERROR, "%s: %d: bad anongid \"%s\"\n", -- flname, flline, opt); -+ flname, flline, opt); - goto bad_option; - } - } else if (strncmp(opt, "squash_uids=", 12) == 0) { -@@ -649,13 +730,13 @@ bad_option: - setflags(NFSEXP_FSID, active, ep); - } else { - ep->e_fsid = strtoul(opt+5, &oe, 0); -- if (opt[5]!='\0' && *oe == '\0') -+ if (opt[5]!='\0' && *oe == '\0') - setflags(NFSEXP_FSID, active, ep); - else if (valid_uuid(opt+5)) - ep->e_uuid = strdup(opt+5); - else { - xlog(L_ERROR, "%s: %d: bad fsid \"%s\"\n", -- flname, flline, opt); -+ flname, flline, opt); - goto bad_option; - } - } -@@ -688,6 +769,9 @@ bad_option: - active = parse_flavors(opt+4, ep); - if (!active) - goto bad_option; -+ } else if (strncmp(opt, "xprtsec=", 8) == 0) { -+ if (!parse_xprtsec(opt + 8, ep)) -+ goto bad_option; - } else { - xlog(L_ERROR, "%s:%d: unknown keyword \"%s\"\n", - flname, flline, opt); -@@ -709,7 +793,7 @@ out: - if (warn && !had_subtree_opt) - xlog(L_WARNING, "%s [%d]: Neither 'subtree_check' or 'no_subtree_check' specified for export \"%s:%s\".\n" - " Assuming default behaviour ('no_subtree_check').\n" -- " NOTE: this default has changed since nfs-utils version 1.0.x\n", -+ " NOTE: this default has changed since nfs-utils version 1.0.x\n", - - flname, flline, - ep->e_hostname, ep->e_path); -diff --git a/support/nfs/xlog.c b/support/nfs/xlog.c -index e5861b9d..fa125cef 100644 ---- a/support/nfs/xlog.c -+++ b/support/nfs/xlog.c -@@ -46,11 +46,13 @@ int export_errno = 0; - - static void xlog_toggle(int sig); - static struct xlog_debugfac debugnames[] = { -+ { "0", 0, }, - { "general", D_GENERAL, }, - { "call", D_CALL, }, - { "auth", D_AUTH, }, - { "parse", D_PARSE, }, - { "all", D_ALL, }, -+ { "1", D_ALL, }, - { NULL, 0, }, - }; - -@@ -119,13 +121,14 @@ xlog_sconfig(char *kind, int on) - { - struct xlog_debugfac *tbl = debugnames; - -- while (tbl->df_name != NULL && strcasecmp(tbl->df_name, kind)) -+ while (tbl->df_name != NULL && strcasecmp(tbl->df_name, kind)) - tbl++; - if (!tbl->df_name) { - xlog (L_WARNING, "Invalid debug facility: %s\n", kind); - return; - } -- xlog_config(tbl->df_fac, on); -+ if (tbl->df_fac) -+ xlog_config(tbl->df_fac, on); - } - - void -diff --git a/support/nfsidmap/regex.c b/support/nfsidmap/regex.c -index 958b4ac8..8424179f 100644 ---- a/support/nfsidmap/regex.c -+++ b/support/nfsidmap/regex.c -@@ -542,7 +542,7 @@ struct trans_func regex_trans = { - .gss_princ_to_grouplist = regex_gss_princ_to_grouplist, - }; - --struct trans_func *libnfsidmap_plugin_init() -+struct trans_func *libnfsidmap_plugin_init(void) - { - return (®ex_trans); - } -diff --git a/systemd/50-nfs.conf b/systemd/50-nfs.conf -deleted file mode 100644 -index 19e8ee73..00000000 ---- a/systemd/50-nfs.conf -+++ /dev/null -@@ -1,16 +0,0 @@ --# Ensure all NFS systctl settings get applied when modules load -- --# sunrpc module supports "sunrpc.*" sysctls --install sunrpc /sbin/modprobe --ignore-install sunrpc $CMDLINE_OPTS && { /sbin/sysctl -q --pattern sunrpc --system; exit 0; } -- --# rpcrdma module supports sunrpc.svc_rdma.* --install rpcrdma /sbin/modprobe --ignore-install rpcrdma $CMDLINE_OPTS && { /sbin/sysctl -q --pattern sunrpc.svc_rdma --system; exit 0; } -- --# lockd module supports "fs.nfs.nlm*" and "fs.nfs.nsm*" sysctls --install lockd /sbin/modprobe --ignore-install lockd $CMDLINE_OPTS && { /sbin/sysctl -q --pattern fs.nfs.n[sl]m --system; exit 0; } -- --# nfsv4 module supports "fs.nfs.*" sysctls (nfs_callback_tcpport and idmap_cache_timeout) --install nfsv4 /sbin/modprobe --ignore-install nfsv4 $CMDLINE_OPTS && { /sbin/sysctl -q --pattern 'fs.nfs.(nfs_callback_tcpport|idmap_cache_timeout)' --system; exit 0; } -- --# nfs module supports "fs.nfs.*" sysctls --install nfs /sbin/modprobe --ignore-install nfs $CMDLINE_OPTS && { /sbin/sysctl -q --pattern fs.nfs --system; exit 0; } -diff --git a/systemd/60-nfs.rules b/systemd/60-nfs.rules -new file mode 100644 -index 00000000..188423c1 ---- /dev/null -+++ b/systemd/60-nfs.rules -@@ -0,0 +1,21 @@ -+# Ensure all NFS systctl settings get applied when modules load -+ -+# sunrpc module supports "sunrpc.*" sysctls -+ACTION=="add", SUBSYSTEM=="module", KERNEL=="sunrpc", \ -+ RUN+="/sbin/sysctl -q --pattern ^sunrpc --system" -+ -+# rpcrdma module supports sunrpc.svc_rdma.* -+ACTION=="add", SUBSYSTEM=="module", KERNEL=="rpcrdma", \ -+ RUN+="/sbin/sysctl -q --pattern ^sunrpc.svc_rdma --system" -+ -+# lockd module supports "fs.nfs.nlm*" and "fs.nfs.nsm*" sysctls -+ACTION=="add", SUBSYSTEM=="module", KERNEL=="lockd", \ -+ RUN+="/sbin/sysctl -q --pattern ^fs.nfs.n[sl]m --system" -+ -+# nfsv4 module supports "fs.nfs.*" sysctls (nfs_callback_tcpport and idmap_cache_timeout) -+ACTION=="add", SUBSYSTEM=="module", KERNEL=="nfsv4", \ -+ RUN+="/sbin/sysctl -q --pattern ^fs.nfs.(nfs_callback_tcpport|idmap_cache_timeout) --system" -+ -+# nfs module supports "fs.nfs.*" sysctls -+ACTION=="add", SUBSYSTEM=="module", KERNEL=="nfs", \ -+ RUN+="/sbin/sysctl -q --pattern ^fs.nfs --system" -diff --git a/systemd/Makefile.am b/systemd/Makefile.am -index 7b5ab84b..577c6a22 100644 ---- a/systemd/Makefile.am -+++ b/systemd/Makefile.am -@@ -2,7 +2,8 @@ - - MAINTAINERCLEANFILES = Makefile.in - --modprobe_files = 50-nfs.conf -+udev_rulesdir = /usr/lib/udev/rules.d/ -+udev_files = 60-nfs.rules - - unit_files = \ - nfs-client.target \ -@@ -53,7 +54,7 @@ endif - - man5_MANS = nfs.conf.man - man7_MANS = nfs.systemd.man --EXTRA_DIST = $(unit_files) $(modprobe_files) $(man5_MANS) $(man7_MANS) -+EXTRA_DIST = $(unit_files) $(udev_files) $(man5_MANS) $(man7_MANS) - - generator_dir = $(unitdir)/../system-generators - -@@ -75,14 +76,10 @@ rpc_pipefs_generator_LDADD = ../support/nfs/libnfs.la - - if INSTALL_SYSTEMD - genexec_PROGRAMS = nfs-server-generator rpc-pipefs-generator --install-data-hook: $(unit_files) $(modprobe_files) -+install-data-hook: $(unit_files) $(udev_files) - mkdir -p $(DESTDIR)/$(unitdir) - cp $(unit_files) $(DESTDIR)/$(unitdir) - cp $(rpc_pipefs_mount_file) $(DESTDIR)/$(unitdir)/$(rpc_pipefsmount) --else --install-data-hook: $(modprobe_files) --endif --if INSTALL_MODPROBEDIR -- mkdir -p $(DESTDIR)$(modprobedir) -- cp $(modprobe_files) $(DESTDIR)$(modprobedir) -+ mkdir -p $(DESTDIR)/$(udev_rulesdir) -+ cp $(udev_files) $(DESTDIR)/$(udev_rulesdir) - endif -diff --git a/systemd/auth-rpcgss-module.service b/systemd/auth-rpcgss-module.service -index 45482833..4a69a7b7 100644 ---- a/systemd/auth-rpcgss-module.service -+++ b/systemd/auth-rpcgss-module.service -@@ -8,8 +8,9 @@ - Description=Kernel Module supporting RPCSEC_GSS - DefaultDependencies=no - Before=gssproxy.service rpc-svcgssd.service rpc-gssd.service --Wants=gssproxy.service rpc-svcgssd.service rpc-gssd.service -+Wants=gssproxy.service rpc-gssd.service - ConditionPathExists=/etc/krb5.keytab -+ConditionVirtualization=!container - - [Service] - Type=oneshot -diff --git a/systemd/nfs-server.service b/systemd/nfs-server.service -index b432f910..2cdd7868 100644 ---- a/systemd/nfs-server.service -+++ b/systemd/nfs-server.service -@@ -15,7 +15,7 @@ After=nfsdcld.service - Before=rpc-statd-notify.service - - # GSS services dependencies and ordering --Wants=auth-rpcgss-module.service -+Wants=auth-rpcgss-module.service rpc-svcgssd.service - After=rpc-gssd.service gssproxy.service rpc-svcgssd.service - - [Service] -diff --git a/systemd/nfs.conf.man b/systemd/nfs.conf.man -index e74083e9..bfd3380f 100644 ---- a/systemd/nfs.conf.man -+++ b/systemd/nfs.conf.man -@@ -98,6 +98,12 @@ value, which can be one or more from the list - .BR parse , - .BR all . - When a list is given, the members should be comma-separated. -+The values -+.BR 0 -+and -+.BR 1 -+are also accepted, with '0' making no changes to the debug level, and '1' equivalent to specifying 'all'. -+ - .TP - .B general - Recognized values: -@@ -166,6 +172,7 @@ for details. - Recognized values: - .BR threads , - .BR host , -+.BR scope , - .BR port , - .BR grace-time , - .BR lease-time , -diff --git a/tools/Makefile.am b/tools/Makefile.am -index 40c17c37..48fd0cdf 100644 ---- a/tools/Makefile.am -+++ b/tools/Makefile.am -@@ -12,6 +12,10 @@ if CONFIG_NFSDCLD - OPTDIRS += nfsdclddb - endif - --SUBDIRS = locktest rpcdebug nlmtest mountstats nfs-iostat rpcctl nfsdclnts nfsrahead $(OPTDIRS) -+if CONFIG_NFSRAHEAD -+OPTDIRS += nfsrahead -+endif -+ -+SUBDIRS = locktest rpcdebug nlmtest mountstats nfs-iostat rpcctl nfsdclnts $(OPTDIRS) - - MAINTAINERCLEANFILES = Makefile.in -diff --git a/tools/nfs-iostat/nfs-iostat.py b/tools/nfs-iostat/nfs-iostat.py -index 1df74ba8..85294fb9 100755 ---- a/tools/nfs-iostat/nfs-iostat.py -+++ b/tools/nfs-iostat/nfs-iostat.py -@@ -43,7 +43,7 @@ NfsEventCounters = [ - 'vfspermission', - 'vfsupdatepage', - 'vfsreadpage', -- 'vfsreadpages', -+ 'vfsreadpages', # or vfsreadahead in statvers=1.2 or above - 'vfswritepage', - 'vfswritepages', - 'vfsreaddir', -@@ -86,14 +86,14 @@ class DeviceData: - self.__nfs_data['export'] = words[1] - self.__nfs_data['mountpoint'] = words[4] - self.__nfs_data['fstype'] = words[7] -- if words[7] == 'nfs': -- self.__nfs_data['statvers'] = words[8] -+ if words[7] == 'nfs' or words[7] == 'nfs4': -+ self.__nfs_data['statvers'] = float(words[8].split('=',1)[1]) - elif 'nfs' in words or 'nfs4' in words: - self.__nfs_data['export'] = words[0] - self.__nfs_data['mountpoint'] = words[3] - self.__nfs_data['fstype'] = words[6] - if words[6] == 'nfs': -- self.__nfs_data['statvers'] = words[7] -+ self.__nfs_data['statvers'] = float(words[7].split('=',1)[1]) - elif words[0] == 'age:': - self.__nfs_data['age'] = int(words[1]) - elif words[0] == 'opts:': -@@ -294,8 +294,11 @@ class DeviceData: - print() - print('%d nfs_readpage() calls read %d pages' % \ - (vfsreadpage, vfsreadpage)) -- print('%d nfs_readpages() calls read %d pages' % \ -- (vfsreadpages, pages_read - vfsreadpage)) -+ multipageread = "readpages" -+ if self.__nfs_data['statvers'] >= 1.2: -+ multipageread = "readahead" -+ print('%d nfs_%s() calls read %d pages' % \ -+ (vfsreadpages, multipageread, pages_read - vfsreadpage)) - if vfsreadpages != 0: - print('(%.1f pages per call)' % \ - (float(pages_read - vfsreadpage) / vfsreadpages)) -diff --git a/tools/nfsrahead/Makefile.am b/tools/nfsrahead/Makefile.am -index 845ea0d5..7e08233a 100644 ---- a/tools/nfsrahead/Makefile.am -+++ b/tools/nfsrahead/Makefile.am -@@ -1,6 +1,6 @@ - libexec_PROGRAMS = nfsrahead - nfsrahead_SOURCES = main.c --nfsrahead_LDFLAGS= -lmount -+nfsrahead_LDFLAGS= $(LIBMOUNT_LIBS) - nfsrahead_LDADD = ../../support/nfs/libnfsconf.la - - man5_MANS = nfsrahead.man -diff --git a/tools/nfsrahead/main.c b/tools/nfsrahead/main.c -index c83c6f71..8a11cf1a 100644 ---- a/tools/nfsrahead/main.c -+++ b/tools/nfsrahead/main.c -@@ -167,7 +167,7 @@ int main(int argc, char **argv) - if ((ret = get_device_info(argv[optind], &device)) == 0) - break; - -- if (ret != 0) { -+ if (ret != 0 || device.fstype == NULL) { - xlog(D_GENERAL, "unable to find device %s\n", argv[optind]); - goto out; - } -diff --git a/tools/rpcdebug/rpcdebug.c b/tools/rpcdebug/rpcdebug.c -index 68206cc5..ec05179e 100644 ---- a/tools/rpcdebug/rpcdebug.c -+++ b/tools/rpcdebug/rpcdebug.c -@@ -257,7 +257,7 @@ get_flags(char *module) - perror(filename); - exit(1); - } -- if ((len = read(sysfd, buffer, sizeof(buffer))) < 0) { -+ if ((len = read(sysfd, buffer, sizeof(buffer))) <= 0) { - perror("read"); - exit(1); - } -diff --git a/utils/blkmapd/device-discovery.c b/utils/blkmapd/device-discovery.c -index 2736ac89..a565fdbd 100644 ---- a/utils/blkmapd/device-discovery.c -+++ b/utils/blkmapd/device-discovery.c -@@ -187,10 +187,7 @@ static void bl_add_disk(char *filepath) - } - - if (disk && diskpath) { -- if (serial) { -- free(serial->data); -- free(serial); -- } -+ bl_free_scsi_string(serial); - return; - } - -@@ -228,10 +225,7 @@ static void bl_add_disk(char *filepath) - disk->size = size; - disk->valid_path = path; - } -- if (serial) { -- free(serial->data); -- free(serial); -- } -+ bl_free_scsi_string(serial); - } - return; - -@@ -241,10 +235,7 @@ static void bl_add_disk(char *filepath) - free(path->full_path); - free(path); - } -- if (serial) { -- free(serial->data); -- free(serial); -- } -+ bl_free_scsi_string(serial); - return; - } - -@@ -462,7 +453,7 @@ static void sig_die(int signal) - unlink(PID_FILE); - } - BL_LOG_ERR("exit on signal(%d)\n", signal); -- exit(1); -+ exit(0); - } - static void usage(void) - { -@@ -507,28 +498,44 @@ int main(int argc, char **argv) - if (fg) { - openlog("blkmapd", LOG_PERROR, 0); - } else { -- if (daemon(0, 0) != 0) { -- fprintf(stderr, "Daemonize failed\n"); -+ pid_t pid = fork(); -+ if (pid < 0) { -+ BL_LOG_ERR("fork error\n"); - exit(1); -+ } else if (pid != 0) { -+ pidfd = open(PID_FILE, O_WRONLY | O_CREAT, 0644); -+ if (pidfd < 0) { -+ BL_LOG_ERR("Create pid file %s failed\n", PID_FILE); -+ exit(1); -+ } -+ -+ if (lockf(pidfd, F_TLOCK, 0) < 0) { -+ BL_LOG_ERR("Already running; Exiting!"); -+ close(pidfd); -+ exit(1); -+ } -+ if (ftruncate(pidfd, 0) < 0) -+ BL_LOG_ERR("ftruncate on %s failed: m\n", PID_FILE); -+ sprintf(pidbuf, "%d\n", pid); -+ if (write(pidfd, pidbuf, strlen(pidbuf)) != (ssize_t)strlen(pidbuf)) -+ BL_LOG_ERR("write on %s failed: m\n", PID_FILE); -+ exit(0); - } - -- openlog("blkmapd", LOG_PID, 0); -- pidfd = open(PID_FILE, O_WRONLY | O_CREAT, 0644); -- if (pidfd < 0) { -- BL_LOG_ERR("Create pid file %s failed\n", PID_FILE); -- exit(1); -+ (void)setsid(); -+ if (chdir("/")) { -+ BL_LOG_ERR("chdir error\n"); - } -+ int fd = open("/dev/null", O_RDWR, 0); -+ if (fd >= 0) { -+ (void)dup2(fd, STDIN_FILENO); -+ (void)dup2(fd, STDOUT_FILENO); -+ (void)dup2(fd, STDERR_FILENO); - -- if (lockf(pidfd, F_TLOCK, 0) < 0) { -- BL_LOG_ERR("Already running; Exiting!"); -- close(pidfd); -- exit(1); -+ (void)close(fd); - } -- if (ftruncate(pidfd, 0) < 0) -- BL_LOG_WARNING("ftruncate on %s failed: m\n", PID_FILE); -- sprintf(pidbuf, "%d\n", getpid()); -- if (write(pidfd, pidbuf, strlen(pidbuf)) != (ssize_t)strlen(pidbuf)) -- BL_LOG_WARNING("write on %s failed: m\n", PID_FILE); -+ -+ openlog("blkmapd", LOG_PID, 0); - } - - signal(SIGINT, sig_die); -diff --git a/utils/blkmapd/device-discovery.h b/utils/blkmapd/device-discovery.h -index a86eed99..462aa943 100644 ---- a/utils/blkmapd/device-discovery.h -+++ b/utils/blkmapd/device-discovery.h -@@ -151,6 +151,8 @@ uint64_t process_deviceinfo(const char *dev_addr_buf, - - extern ssize_t atomicio(ssize_t(*f) (int, void *, size_t), - int fd, void *_s, size_t n); -+extern struct bl_serial *bl_create_scsi_string(int len, const char *bytes); -+extern void bl_free_scsi_string(struct bl_serial *str); - extern struct bl_serial *bldev_read_serial(int fd, const char *filename); - extern enum bl_path_state_e bldev_read_ap_state(int fd); - extern int bl_discover_devices(void); -diff --git a/utils/blkmapd/device-inq.c b/utils/blkmapd/device-inq.c -index c7952c3e..9e5749ef 100644 ---- a/utils/blkmapd/device-inq.c -+++ b/utils/blkmapd/device-inq.c -@@ -53,7 +53,7 @@ - #define DEF_ALLOC_LEN 255 - #define MX_ALLOC_LEN (0xc000 + 0x80) - --static struct bl_serial *bl_create_scsi_string(int len, const char *bytes) -+struct bl_serial *bl_create_scsi_string(int len, const char *bytes) - { - struct bl_serial *s; - -@@ -66,7 +66,7 @@ static struct bl_serial *bl_create_scsi_string(int len, const char *bytes) - return s; - } - --static void bl_free_scsi_string(struct bl_serial *str) -+void bl_free_scsi_string(struct bl_serial *str) - { - if (str) - free(str); -diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c -index 6ba615d1..37b9e4b3 100644 ---- a/utils/exportfs/exportfs.c -+++ b/utils/exportfs/exportfs.c -@@ -69,14 +69,14 @@ static int _lockfd = -1; - * need these additional lockfile() routines. - */ - static void --grab_lockfile() -+grab_lockfile(void) - { - _lockfd = open(lockfile, O_CREAT|O_RDWR, 0666); - if (_lockfd != -1) - lockf(_lockfd, F_LOCK, 0); - } - static void --release_lockfile() -+release_lockfile(void) - { - if (_lockfd != -1) { - lockf(_lockfd, F_ULOCK, 0); -@@ -513,7 +513,7 @@ validate_export(nfs_export *exp) - */ - struct stat stb; - char *path = exportent_realpath(&exp->m_export); -- struct statfs64 stf; -+ struct statfs stf; - int fs_has_fsid = 0; - - if (stat(path, &stb) < 0) { -@@ -528,7 +528,7 @@ validate_export(nfs_export *exp) - if (!can_test()) - return; - -- if (!statfs64(path, &stf) && -+ if (!statfs(path, &stf) && - (stf.f_fsid.__val[0] || stf.f_fsid.__val[1])) - fs_has_fsid = 1; - -@@ -743,6 +743,7 @@ dump(int verbose, int export_format) - #endif - } - secinfo_show(stdout, ep); -+ xprtsecinfo_show(stdout, ep); - printf("%c\n", (c != '(')? ')' : ' '); - } - } -diff --git a/utils/exportfs/exports.man b/utils/exportfs/exports.man -index 54b3f877..83dd6807 100644 ---- a/utils/exportfs/exports.man -+++ b/utils/exportfs/exports.man -@@ -125,7 +125,55 @@ In that case you may include multiple sec= options, and following options - will be enforced only for access using flavors listed in the immediately - preceding sec= option. The only options that are permitted to vary in - this way are ro, rw, no_root_squash, root_squash, and all_squash. -+.SS Transport layer security -+The Linux NFS server allows the use of RPC-with-TLS (RFC 9289) to -+protect RPC traffic between itself and its clients. -+Alternately, administrators can secure NFS traffic using a VPN, -+or an ssh tunnel or similar mechanism, in a way that is transparent -+to the server. - .PP -+To enable the use of RPC-with-TLS, the server's administrator must -+install and configure -+.BR tlshd -+to handle transport layer security handshake requests from the local -+kernel. -+Clients can then choose to use RPC-with-TLS or they may continue -+operating without it. -+.PP -+Administrators may require the use of RPC-with-TLS to protect access -+to individual exports. -+This is particularly useful when using non-cryptographic security -+flavors such as -+.IR sec=sys . -+The -+.I xprtsec= -+option, followed by an unordered colon-delimited list of security policies, -+can restrict access to the export to only clients that have negotiated -+transport-layer security. -+Currently supported transport layer security policies include: -+.TP -+.IR none -+The server permits clients to access the export -+without the use of transport layer security. -+.TP -+.IR tls -+The server permits clients that have negotiated an RPC-with-TLS session -+without peer authentication (confidentiality only) to access the export. -+Clients are not required to offer an x.509 certificate -+when establishing a transport layer security session. -+.TP -+.IR mtls -+The server permits clients that have negotiated an RPC-with-TLS session -+with peer authentication to access the export. -+The server requires clients to offer an x.509 certificate -+when establishing a transport layer security session. -+.PP -+If RPC-with-TLS is configured and enabled and the -+.I xprtsec= -+option is not specified, the default setting for an export is -+.IR xprtsec=none:tls:mtls . -+With this setting, the server permits clients to use any transport -+layer security mechanism or none at all to access the export. - .SS General Options - .BR exportfs - understands the following export options: -@@ -581,7 +629,8 @@ a character class wildcard match. - .BR netgroup (5), - .BR mountd (8), - .BR nfsd (8), --.BR showmount (8). -+.BR showmount (8), -+.BR tlshd (8). - .\".SH DIAGNOSTICS - .\"An error parsing the file is reported using syslogd(8) as level NOTICE from - .\"a DAEMON whenever -diff --git a/utils/idmapd/idmapd.c b/utils/idmapd/idmapd.c -index e79c124d..cd9a965f 100644 ---- a/utils/idmapd/idmapd.c -+++ b/utils/idmapd/idmapd.c -@@ -867,7 +867,7 @@ nfsdreopen_one(struct idmap_client *ic) - } - - static void --nfsdreopen() -+nfsdreopen(void) - { - nfsdreopen_one(&nfsd_ic[IC_NAMEID]); - nfsdreopen_one(&nfsd_ic[IC_IDNAME]); -diff --git a/utils/mount/error.c b/utils/mount/error.c -index 73295bf0..9ddbcc09 100644 ---- a/utils/mount/error.c -+++ b/utils/mount/error.c -@@ -207,16 +207,17 @@ void mount_error(const char *spec, const char *mount_point, int error) - progname, spec); - break; - case EINVAL: -- nfs_error(_("%s: an incorrect mount option was specified"), progname); -+ nfs_error(_("%s: an incorrect mount option was specified for %s"), -+ progname, mount_point); - break; - case EOPNOTSUPP: -- nfs_error(_("%s: requested NFS version or transport protocol is not supported"), -- progname); -+ nfs_error(_("%s: requested NFS version or transport protocol is not supported for %s"), -+ progname, mount_point); - break; - case ENOTDIR: - if (spec) -- nfs_error(_("%s: mount spec %s or point %s is not a " -- "directory"), progname, spec, mount_point); -+ nfs_error(_("%s: mount spec %s or point %s is not a directory"), -+ progname, spec, mount_point); - else - nfs_error(_("%s: mount point %s is not a directory"), - progname, mount_point); -@@ -227,31 +228,31 @@ void mount_error(const char *spec, const char *mount_point, int error) - break; - case ENOENT: - if (spec) -- nfs_error(_("%s: mounting %s failed, " -- "reason given by server: %s"), -- progname, spec, strerror(error)); -+ nfs_error(_("%s: mounting %s failed, reason given by server: %s"), -+ progname, spec, strerror(error)); - else - nfs_error(_("%s: mount point %s does not exist"), -- progname, mount_point); -+ progname, mount_point); - break; - case ESPIPE: - rpc_mount_errors((char *)spec, 0, 0); - break; - case EIO: -- nfs_error(_("%s: mount system call failed"), progname); -+ nfs_error(_("%s: mount system call failed for %s"), -+ progname, mount_point); - break; - case EFAULT: -- nfs_error(_("%s: encountered unexpected error condition."), -- progname); -+ nfs_error(_("%s: encountered unexpected error condition for %s."), -+ progname, mount_point); - nfs_error(_("%s: please report the error to" PACKAGE_BUGREPORT), -- progname); -+ progname); - break; - case EALREADY: - /* Error message has already been provided */ - break; - default: -- nfs_error(_("%s: %s"), -- progname, strerror(error)); -+ nfs_error(_("%s: %s for %s on %s"), -+ progname, strerror(error), spec, mount_point); - } - } - -diff --git a/utils/mount/network.c b/utils/mount/network.c -index ed2f8253..01ead49f 100644 ---- a/utils/mount/network.c -+++ b/utils/mount/network.c -@@ -179,7 +179,7 @@ static const unsigned long probe_mnt3_only[] = { - - static const unsigned int *nfs_default_proto(void); - #ifdef MOUNT_CONFIG --static const unsigned int *nfs_default_proto() -+static const unsigned int *nfs_default_proto(void) - { - extern unsigned long config_default_proto; - /* -diff --git a/utils/mount/nfs.man b/utils/mount/nfs.man -index d9f34df3..7a410422 100644 ---- a/utils/mount/nfs.man -+++ b/utils/mount/nfs.man -@@ -574,7 +574,39 @@ The - .B sloppy - option is an alternative to specifying - .BR mount.nfs " -s " option. -- -+.TP 1.5i -+.BI xprtsec= policy -+Specifies the use of transport layer security to protect NFS network -+traffic on behalf of this mount point. -+.I policy -+can be one of -+.BR none , -+.BR tls , -+or -+.BR mtls . -+.IP -+If -+.B none -+is specified, -+transport layer security is forced off, even if the NFS server supports -+transport layer security. -+If -+.B tls -+is specified, the client uses RPC-with-TLS to provide in-transit -+confidentiality. -+If -+.B mtls -+is specified, the client uses RPC-with-TLS to authenticate itself and -+to provide in-transit confidentiality. -+If the server does not support RPC-with-TLS or peer authentication -+fails, the mount attempt fails. -+.IP -+If the -+.B xprtsec= -+option is not specified, -+the default behavior depends on the kernel, -+but is usually equivalent to -+.BR "xprtsec=none" . - .SS "Options for NFS versions 2 and 3 only" - Use these options, along with the options in the above subsection, - for NFS versions 2 and 3 only. -diff --git a/utils/mount/nfsmount.conf b/utils/mount/nfsmount.conf -index 342063f7..c498eb80 100644 ---- a/utils/mount/nfsmount.conf -+++ b/utils/mount/nfsmount.conf -@@ -59,13 +59,13 @@ - # acregmin=30 - # - # The Maximum time (in seconds) file attributes are cached --# acregmin=60 -+# acregmax=60 - # - # The minimum time (in seconds) directory attributes are cached --# acregmin=30 -+# acdirmin=30 - # - # The Maximum time (in seconds) directory attributes are cached --# acregmin=60 -+# acdirmax=60 - # - # Enable Access Control Lists - # Acl=False -diff --git a/utils/mount/parse_dev.c b/utils/mount/parse_dev.c -index 0d3bcb95..2ade5d5d 100644 ---- a/utils/mount/parse_dev.c -+++ b/utils/mount/parse_dev.c -@@ -170,7 +170,8 @@ static int nfs_parse_square_bracket(const char *dev, - if (pathname) { - *pathname = strndup(cbrace, path_len); - if (*pathname == NULL) { -- free(*hostname); -+ if (hostname) -+ free(*hostname); - return nfs_pdn_nomem_err(); - } - } -diff --git a/utils/nfsd/nfsd.c b/utils/nfsd/nfsd.c -index 4016a761..249df00b 100644 ---- a/utils/nfsd/nfsd.c -+++ b/utils/nfsd/nfsd.c -@@ -23,6 +23,7 @@ - #include - #include - #include -+#include - - #include "conffile.h" - #include "nfslib.h" -@@ -39,6 +40,7 @@ static void usage(const char *); - static struct option longopts[] = - { - { "host", 1, 0, 'H' }, -+ { "scope", 1, 0, 'S'}, - { "help", 0, 0, 'h' }, - { "no-nfs-version", 1, 0, 'N' }, - { "nfs-version", 1, 0, 'V' }, -@@ -69,6 +71,7 @@ main(int argc, char **argv) - int count = NFSD_NPROC, c, i, error = 0, portnum, fd, found_one; - char *p, *progname, *port, *rdma_port = NULL; - char **haddr = NULL; -+ char *scope = NULL; - int hcounter = 0; - struct conf_list *hosts; - int socket_up = 0; -@@ -168,8 +171,9 @@ main(int argc, char **argv) - hcounter++; - } - } -+ scope = conf_get_str("nfsd", "scope"); - -- while ((c = getopt_long(argc, argv, "dH:hN:V:p:P:stTuUrG:L:", longopts, NULL)) != EOF) { -+ while ((c = getopt_long(argc, argv, "dH:S:hN:V:p:P:stTuUrG:L:", longopts, NULL)) != EOF) { - switch(c) { - case 'd': - xlog_config(D_ALL, 1); -@@ -190,6 +194,9 @@ main(int argc, char **argv) - haddr[hcounter] = optarg; - hcounter++; - break; -+ case 'S': -+ scope = optarg; -+ break; - case 'P': /* XXX for nfs-server compatibility */ - case 'p': - /* only the last -p option has any effect */ -@@ -367,6 +374,14 @@ main(int argc, char **argv) - if (lease > 0) - nfssvc_set_time("lease", lease); - -+ if (scope) { -+ if (unshare(CLONE_NEWUTS) < 0 || -+ sethostname(scope, strlen(scope)) < 0) { -+ xlog(L_ERROR, "Unable to set server scope: %m"); -+ error = -1; -+ goto out; -+ } -+ } - i = 0; - do { - error = nfssvc_set_sockets(protobits, haddr[i], port); -diff --git a/utils/nfsd/nfsd.man b/utils/nfsd/nfsd.man -index 634b8a63..6f4fc1df 100644 ---- a/utils/nfsd/nfsd.man -+++ b/utils/nfsd/nfsd.man -@@ -35,9 +35,17 @@ Note that - .B lockd - (which performs file locking services for NFS) may still accept - request on all known network addresses. This may change in future --releases of the Linux Kernel. This option can be used multiple time -+releases of the Linux Kernel. This option can be used multiple times - to listen to more than one interface. - .TP -+.B \-S " or " \-\-scope scope -+NFSv4.1 and later require the server to report a "scope" which is used -+by the clients to detect if two connections are to the same server. -+By default Linux NFSD uses the host name as the scope. -+.sp -+It is particularly important for high-availablity configurations to ensure -+that all potential server nodes report the same server scope. -+.TP - .B \-p " or " \-\-port port - specify a different port to listen on for NFS requests. By default, - .B rpc.nfsd -@@ -134,6 +142,9 @@ will listen on. Use of the - .B --host - option replaces all host names listed here. - .TP -+.B scope -+Set the server scope. -+.TP - .B grace-time - The grace time, for both NFSv4 and NLM, in seconds. - .TP -@@ -159,7 +170,9 @@ Enable or disable TCP support. - .B vers3 - .TP - .B vers4 --Enable or disable a major NFS version. 3 and 4 are normally enabled -+Enable or disable -+.B all -+NFSv4 versions. All versions are normally enabled - by default. - .TP - .B vers4.1 diff --git a/nfs-utils.2.6.4-rc5.patch b/nfs-utils.2.6.4-rc5.patch deleted file mode 100644 index 3d245d5..0000000 --- a/nfs-utils.2.6.4-rc5.patch +++ /dev/null @@ -1,1519 +0,0 @@ -diff --git a/configure.ac b/configure.ac -index 4ade528..6fbcb97 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -335,42 +335,37 @@ AC_CHECK_HEADER(rpc/rpc.h, , - AC_MSG_ERROR([Header file rpc/rpc.h not found - maybe try building with --enable-tirpc])) - CPPFLAGS="${nfsutils_save_CPPFLAGS}" - -+AC_CHECK_HEADER(uuid/uuid.h, , -+ AC_MSG_ERROR([Cannot find needed header file uuid/uuid.h. Install libuuid-devel])) -+ -+dnl check for libevent libraries and headers -+AC_LIBEVENT -+ -+dnl Check for sqlite3 -+AC_SQLITE3_VERS -+ -+case $libsqlite3_cv_is_recent in -+yes) ;; -+unknown) -+ dnl do not fail when cross-compiling -+ AC_MSG_WARN([assuming sqlite is at least v3.3]) ;; -+*) -+ AC_MSG_ERROR([nfsdcld requires sqlite-devel]) ;; -+esac -+ - if test "$enable_nfsv4" = yes; then -- dnl check for libevent libraries and headers -- AC_LIBEVENT - - dnl check for the keyutils libraries and headers - AC_KEYUTILS - -- dnl Check for sqlite3 -- AC_SQLITE3_VERS -- - if test "$enable_nfsdcld" = "yes"; then - AC_CHECK_HEADERS([libgen.h sys/inotify.h], , - AC_MSG_ERROR([Cannot find header needed for nfsdcld])) -- -- case $libsqlite3_cv_is_recent in -- yes) ;; -- unknown) -- dnl do not fail when cross-compiling -- AC_MSG_WARN([assuming sqlite is at least v3.3]) ;; -- *) -- AC_MSG_ERROR([nfsdcld requires sqlite-devel]) ;; -- esac - fi - - if test "$enable_nfsdcltrack" = "yes"; then - AC_CHECK_HEADERS([libgen.h sys/inotify.h], , - AC_MSG_ERROR([Cannot find header needed for nfsdcltrack])) -- -- case $libsqlite3_cv_is_recent in -- yes) ;; -- unknown) -- dnl do not fail when cross-compiling -- AC_MSG_WARN([assuming sqlite is at least v3.3]) ;; -- *) -- AC_MSG_ERROR([nfsdcltrack requires sqlite-devel]) ;; -- esac - fi - - else -diff --git a/support/export/cache.c b/support/export/cache.c -index 19bbba5..6c0a44a 100644 ---- a/support/export/cache.c -+++ b/support/export/cache.c -@@ -1,10 +1,9 @@ -- - /* - * Handle communication with knfsd internal cache - * - * We open /proc/net/rpc/{auth.unix.ip,nfsd.export,nfsd.fh}/channel - * and listen for requests (using my_svc_run) -- * -+ * - */ - - #ifdef HAVE_CONFIG_H -@@ -16,6 +15,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -77,6 +77,7 @@ static bool path_lookup_error(int err) - case ENAMETOOLONG: - case ENOENT: - case ENOTDIR: -+ case EACCES: - return 1; - } - return 0; -@@ -758,7 +759,15 @@ static struct addrinfo *lookup_client_addr(char *dom) - return ret; - } - --static void nfsd_fh(int f) -+#define RETRY_SEC 120 -+struct delayed { -+ char *message; -+ time_t last_attempt; -+ int f; -+ struct delayed *next; -+} *delayed; -+ -+static int nfsd_handle_fh(int f, char *bp, int blen) - { - /* request are: - * domain fsidtype fsid -@@ -776,21 +785,13 @@ static void nfsd_fh(int f) - nfs_export *exp; - int i; - int dev_missing = 0; -- char buf[RPC_CHAN_BUF_SIZE], *bp; -- int blen; -+ char buf[RPC_CHAN_BUF_SIZE]; - int did_uncover = 0; -- -- blen = cache_read(f, buf, sizeof(buf)); -- if (blen <= 0 || buf[blen-1] != '\n') return; -- buf[blen-1] = 0; -- -- xlog(D_CALL, "nfsd_fh: inbuf '%s'", buf); -- -- bp = buf; -+ int ret = 0; - - dom = malloc(blen); - if (dom == NULL) -- return; -+ return ret; - if (qword_get(&bp, dom, blen) <= 0) - goto out; - if (qword_get_int(&bp, &fsidtype) != 0) -@@ -858,7 +859,8 @@ static void nfsd_fh(int f) - case 0: - continue; - case -1: -- goto out; -+ dev_missing ++; -+ continue; - } - if (is_ipaddr_client(dom) - && !ipaddr_client_matches(exp, ai)) -@@ -891,8 +893,10 @@ static void nfsd_fh(int f) - /* The missing dev could be what we want, so just be - * quiet rather than returning stale yet - */ -- if (dev_missing) -+ if (dev_missing) { -+ ret = 1; - goto out; -+ } - } else if (found->e_mountpoint && - !is_mountpoint(found->e_mountpoint[0]? - found->e_mountpoint: -@@ -902,7 +906,7 @@ static void nfsd_fh(int f) - xlog(L_WARNING, "%s not exported as %d not a mountpoint", - found->e_path, found->e_mountpoint); - */ -- /* FIXME we need to make sure we re-visit this later */ -+ ret = 1; - goto out; - } - -@@ -931,7 +935,68 @@ out: - free(found_path); - nfs_freeaddrinfo(ai); - free(dom); -- xlog(D_CALL, "nfsd_fh: found %p path %s", found, found ? found->e_path : NULL); -+ if (!ret) -+ xlog(D_CALL, "nfsd_fh: found %p path %s", -+ found, found ? found->e_path : NULL); -+ return ret; -+} -+ -+static void nfsd_fh(int f) -+{ -+ struct delayed *d, **dp; -+ char inbuf[RPC_CHAN_BUF_SIZE]; -+ int blen; -+ -+ blen = cache_read(f, inbuf, sizeof(inbuf)); -+ if (blen <= 0 || inbuf[blen-1] != '\n') return; -+ inbuf[blen-1] = 0; -+ -+ xlog(D_CALL, "nfsd_fh: inbuf '%s'", inbuf); -+ -+ if (nfsd_handle_fh(f, inbuf, blen) == 0) -+ return; -+ /* We don't have a definitive answer to give the kernel. -+ * This is because an export marked "mountpoint" isn't a -+ * mountpoint, or because a stat of a mountpoint fails with -+ * a strange error like ETIMEDOUT as is possible with an -+ * NFS mount marked "softerr" which is being re-exported. -+ * -+ * We cannot tell the kernel to retry, so we have to -+ * retry ourselves. -+ */ -+ d = malloc(sizeof(*d)); -+ -+ if (!d) -+ return; -+ d->message = strndup(inbuf, blen); -+ if (!d->message) { -+ free(d); -+ return; -+ } -+ d->f = f; -+ d->last_attempt = time(NULL); -+ d->next = NULL; -+ dp = &delayed; -+ while (*dp) -+ dp = &(*dp)->next; -+ *dp = d; -+} -+ -+static void nfsd_retry_fh(struct delayed *d) -+{ -+ struct delayed **dp; -+ -+ if (nfsd_handle_fh(d->f, d->message, strlen(d->message)+1) == 0) { -+ free(d->message); -+ free(d); -+ return; -+ } -+ d->last_attempt = time(NULL); -+ d->next = NULL; -+ dp = &delayed; -+ while (*dp) -+ dp = &(*dp)->next; -+ *dp = d; - } - - #ifdef HAVE_JUNCTION_SUPPORT -@@ -1510,7 +1575,7 @@ static void nfsd_export(int f) - * This will cause it not to appear in the V4 Pseudo-root - * and so a "mount" of this path will fail, just like with - * V3. -- * And filehandle for this mountpoint from an earlier -+ * Any filehandle for this mountpoint from an earlier - * mount will block in nfsd.fh lookup. - */ - xlog(L_WARNING, -@@ -1600,40 +1665,63 @@ int cache_process_req(fd_set *readfds) - } - - /** -- * cache_process_loop - process incoming upcalls -+ * cache_process - process incoming upcalls -+ * Returns -ve on error, or number of fds in svc_fds -+ * that might need processing. - */ --void cache_process_loop(void) -+int cache_process(fd_set *readfds) - { -- fd_set readfds; -+ fd_set fdset; - int selret; -+ struct timeval tv = { 24*3600, 0 }; - -- FD_ZERO(&readfds); -- -- for (;;) { -- -- cache_set_fds(&readfds); -- v4clients_set_fds(&readfds); -+ if (!readfds) { -+ FD_ZERO(&fdset); -+ readfds = &fdset; -+ } -+ cache_set_fds(readfds); -+ v4clients_set_fds(readfds); -+ -+ if (delayed) { -+ time_t now = time(NULL); -+ time_t delay; -+ if (delayed->last_attempt > now) -+ /* Clock updated - retry immediately */ -+ delayed->last_attempt = now - RETRY_SEC; -+ delay = delayed->last_attempt + RETRY_SEC - now; -+ if (delay < 0) -+ delay = 0; -+ tv.tv_sec = delay; -+ } -+ selret = select(FD_SETSIZE, readfds, NULL, NULL, &tv); - -- selret = select(FD_SETSIZE, &readfds, -- (void *) 0, (void *) 0, (struct timeval *) 0); -+ if (delayed) { -+ time_t now = time(NULL); -+ struct delayed *d = delayed; - -+ if (d->last_attempt + RETRY_SEC <= now) { -+ delayed = d->next; -+ d->next = NULL; -+ nfsd_retry_fh(d); -+ } -+ } - -- switch (selret) { -- case -1: -- if (errno == EINTR || errno == ECONNREFUSED -- || errno == ENETUNREACH || errno == EHOSTUNREACH) -- continue; -- xlog(L_ERROR, "my_svc_run() - select: %m"); -- return; -+ switch (selret) { -+ case -1: -+ if (errno == EINTR || errno == ECONNREFUSED -+ || errno == ENETUNREACH || errno == EHOSTUNREACH) -+ return 0; -+ return -1; - -- default: -- cache_process_req(&readfds); -- v4clients_process(&readfds); -- } -+ default: -+ selret -= cache_process_req(readfds); -+ selret -= v4clients_process(readfds); -+ if (selret < 0) -+ selret = 0; - } -+ return selret; - } - -- - /* - * Give IP->domain and domain+path->options to kernel - * % echo nfsd $IP $[now+DEFAULT_TTL] $domain > /proc/net/rpc/auth.unix.ip/channel -@@ -1773,3 +1861,74 @@ cache_get_filehandle(nfs_export *exp, int len, char *p) - fh.fh_size = qword_get(&bp, (char *)fh.fh_handle, NFS3_FHSIZE); - return &fh; - } -+ -+/* Wait for all worker child processes to exit and reap them */ -+void -+cache_wait_for_workers(char *prog) -+{ -+ int status; -+ pid_t pid; -+ -+ for (;;) { -+ -+ pid = waitpid(0, &status, 0); -+ -+ if (pid < 0) { -+ if (errno == ECHILD) -+ return; /* no more children */ -+ xlog(L_FATAL, "%s: can't wait: %s\n", prog, -+ strerror(errno)); -+ } -+ -+ /* Note: because we SIG_IGN'd SIGCHLD earlier, this -+ * does not happen on 2.6 kernels, and waitpid() blocks -+ * until all the children are dead then returns with -+ * -ECHILD. But, we don't need to do anything on the -+ * death of individual workers, so we don't care. */ -+ xlog(L_NOTICE, "%s: reaped child %d, status %d\n", -+ prog, (int)pid, status); -+ } -+} -+ -+/* Fork num_threads worker children and wait for them */ -+int -+cache_fork_workers(char *prog, int num_threads) -+{ -+ int i; -+ pid_t pid; -+ -+ if (num_threads <= 1) -+ return 1; -+ -+ xlog(L_NOTICE, "%s: starting %d threads\n", prog, num_threads); -+ -+ for (i = 0 ; i < num_threads ; i++) { -+ pid = fork(); -+ if (pid < 0) { -+ xlog(L_FATAL, "%s: cannot fork: %s\n", prog, -+ strerror(errno)); -+ } -+ if (pid == 0) { -+ /* worker child */ -+ -+ /* Re-enable the default action on SIGTERM et al -+ * so that workers die naturally when sent them. -+ * Only the parent unregisters with pmap and -+ * hence needs to do special SIGTERM handling. */ -+ struct sigaction sa; -+ sa.sa_handler = SIG_DFL; -+ sa.sa_flags = 0; -+ sigemptyset(&sa.sa_mask); -+ sigaction(SIGHUP, &sa, NULL); -+ sigaction(SIGINT, &sa, NULL); -+ sigaction(SIGTERM, &sa, NULL); -+ -+ /* fall into my_svc_run in caller */ -+ return 1; -+ } -+ } -+ -+ /* in parent */ -+ cache_wait_for_workers(prog); -+ return 0; -+} -diff --git a/support/export/export.h b/support/export/export.h -index 8d5a0d3..e2009cc 100644 ---- a/support/export/export.h -+++ b/support/export/export.h -@@ -29,6 +29,9 @@ int v4clients_process(fd_set *fdset); - struct nfs_fh_len * - cache_get_filehandle(nfs_export *exp, int len, char *p); - int cache_export(nfs_export *exp, char *path); -+int cache_fork_workers(char *prog, int num_threads); -+void cache_wait_for_workers(char *prog); -+int cache_process(fd_set *readfds); - - bool ipaddr_client_matches(nfs_export *exp, struct addrinfo *ai); - bool namelist_client_matches(nfs_export *exp, char *dom); -diff --git a/support/include/version.h b/support/include/version.h -deleted file mode 120000 -index b7db0bb..0000000 ---- a/support/include/version.h -+++ /dev/null -@@ -1 +0,0 @@ --../../utils/mount/version.h -\ No newline at end of file -diff --git a/support/include/version.h b/support/include/version.h -new file mode 100644 -index 0000000..d7cf680 ---- /dev/null -+++ b/support/include/version.h -@@ -0,0 +1,53 @@ -+/* -+ * version.h -- get running kernel version -+ * -+ * Copyright (C) 2008 Oracle. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public -+ * License as published by the Free Software Foundation; either -+ * version 2 of the License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public -+ * License along with this program; if not, write to the -+ * Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 0211-1301 USA -+ * -+ */ -+ -+#ifndef _NFS_UTILS_MOUNT_VERSION_H -+#define _NFS_UTILS_MOUNT_VERSION_H -+ -+#include -+#include -+ -+#include -+ -+static inline unsigned int MAKE_VERSION(unsigned int p, unsigned int q, -+ unsigned int r) -+{ -+ return (65536 * p) + (256 * q) + r; -+} -+ -+static inline unsigned int linux_version_code(void) -+{ -+ struct utsname my_utsname; -+ unsigned int p, q = 0, r = 0; -+ -+ /* UINT_MAX as backward compatibility code should not be run */ -+ if (uname(&my_utsname)) -+ return UINT_MAX; -+ -+ /* UINT_MAX as future versions might not start with an integer */ -+ if (sscanf(my_utsname.release, "%u.%u.%u", &p, &q, &r) < 1) -+ return UINT_MAX; -+ -+ return MAKE_VERSION(p, q, r); -+} -+ -+#endif /* _NFS_UTILS_MOUNT_VERSION_H */ -diff --git a/support/junction/junction.c b/support/junction/junction.c -index 0628bb0..c1ec8ff 100644 ---- a/support/junction/junction.c -+++ b/support/junction/junction.c -@@ -63,7 +63,7 @@ junction_open_path(const char *pathname, int *fd) - if (pathname == NULL || fd == NULL) - return FEDFS_ERR_INVAL; - -- tmp = open(pathname, O_PATH|O_DIRECTORY); -+ tmp = open(pathname, O_DIRECTORY); - if (tmp == -1) { - switch (errno) { - case EPERM: -diff --git a/support/nfsidmap/libnfsidmap.c b/support/nfsidmap/libnfsidmap.c -index 0a912e5..f8c3648 100644 ---- a/support/nfsidmap/libnfsidmap.c -+++ b/support/nfsidmap/libnfsidmap.c -@@ -219,10 +219,15 @@ static int domain_from_dns(char **domain) - - if (gethostname(hname, sizeof(hname)) == -1) - return -1; -- if ((he = gethostbyname(hname)) == NULL) -- return -1; -- if ((c = strchr(he->h_name, '.')) == NULL || *++c == '\0') -- return -1; -+ if ((he = gethostbyname(hname)) == NULL) { -+ IDMAP_LOG(1, ("libnfsidmap: DNS lookup of hostname failed. Attempting to use domain from hostname as is.")); -+ if ((c = strchr(hname, '.')) == NULL || *++c == '\0') -+ return -1; -+ } -+ else { -+ if ((c = strchr(he->h_name, '.')) == NULL || *++c == '\0') -+ return -1; -+ } - /* - * Query DNS to see if the _nfsv4idmapdomain TXT record exists - * If so use it... -@@ -387,7 +392,7 @@ int nfs4_init_name_mapping(char *conffile) - dflt = 1; - ret = domain_from_dns(&default_domain); - if (ret) { -- IDMAP_LOG(1, ("libnfsidmap: Unable to determine " -+ IDMAP_LOG(0, ("libnfsidmap: Unable to determine " - "the NFSv4 domain; Using '%s' as the NFSv4 domain " - "which means UIDs will be mapped to the 'Nobody-User' " - "user defined in %s", -diff --git a/support/reexport/fsidd.c b/support/reexport/fsidd.c -index 410b3a3..d4b245e 100644 ---- a/support/reexport/fsidd.c -+++ b/support/reexport/fsidd.c -@@ -3,7 +3,9 @@ - #endif - - #include -+#ifdef HAVE_DLFCN_H - #include -+#endif - #include - #include - #include -@@ -18,14 +20,18 @@ - - #include "conffile.h" - #include "reexport_backend.h" -+#include "reexport.h" - #include "xcommon.h" - #include "xlog.h" - --#define FSID_SOCKET_NAME "fsid.sock" -- - static struct event_base *evbase; - static struct reexpdb_backend_plugin *dbbackend = &sqlite_plug_ops; - -+/* assert_safe() always evalutes it argument, as it might have -+ * a side-effect. assert() won't if compiled with NDEBUG -+ */ -+#define assert_safe(__sideeffect) (__sideeffect ? 0 : ({assert(0) ; 0;})) -+ - static void client_cb(evutil_socket_t cl, short ev, void *d) - { - struct event *me = d; -@@ -56,12 +62,11 @@ static void client_cb(evutil_socket_t cl, short ev, void *d) - - if (dbbackend->fsidnum_by_path(req_path, &fsidnum, false, &found)) { - if (found) -- assert(asprintf(&answer, "+ %u", fsidnum) != -1); -+ assert_safe(asprintf(&answer, "+ %u", fsidnum) != -1); - else -- assert(asprintf(&answer, "+ ") != -1); -- -+ assert_safe(asprintf(&answer, "+ ") != -1); - } else { -- assert(asprintf(&answer, "- %s", "Command failed") != -1); -+ assert_safe(asprintf(&answer, "- %s", "Command failed") != -1); - } - - (void)send(cl, answer, strlen(answer), 0); -@@ -78,13 +83,13 @@ static void client_cb(evutil_socket_t cl, short ev, void *d) - - if (dbbackend->fsidnum_by_path(req_path, &fsidnum, true, &found)) { - if (found) { -- assert(asprintf(&answer, "+ %u", fsidnum) != -1); -+ assert_safe(asprintf(&answer, "+ %u", fsidnum) != -1); - } else { -- assert(asprintf(&answer, "+ ") != -1); -+ assert_safe(asprintf(&answer, "+ ") != -1); - } - - } else { -- assert(asprintf(&answer, "- %s", "Command failed") != -1); -+ assert_safe(asprintf(&answer, "- %s", "Command failed") != -1); - } - - (void)send(cl, answer, strlen(answer), 0); -@@ -106,15 +111,15 @@ static void client_cb(evutil_socket_t cl, short ev, void *d) - } - - if (bad_input) { -- assert(asprintf(&answer, "- %s", "Command failed: Bad input") != -1); -+ assert_safe(asprintf(&answer, "- %s", "Command failed: Bad input") != -1); - } else { - if (dbbackend->path_by_fsidnum(fsidnum, &path, &found)) { - if (found) -- assert(asprintf(&answer, "+ %s", path) != -1); -+ assert_safe(asprintf(&answer, "+ %s", path) != -1); - else -- assert(asprintf(&answer, "+ ") != -1); -+ assert_safe(asprintf(&answer, "+ ") != -1); - } else { -- assert(asprintf(&answer, "+ ") != -1); -+ assert_safe(asprintf(&answer, "+ ") != -1); - } - } - -@@ -129,7 +134,7 @@ static void client_cb(evutil_socket_t cl, short ev, void *d) - } else { - char *answer = NULL; - -- assert(asprintf(&answer, "- bad command") != -1); -+ assert_safe(asprintf(&answer, "- bad command") != -1); - (void)send(cl, answer, strlen(answer), 0); - - free(answer); -@@ -163,11 +168,14 @@ int main(void) - - sock_file = conf_get_str_with_def("reexport", "fsidd_socket", FSID_SOCKET_NAME); - -- unlink(sock_file); -- - memset(&addr, 0, sizeof(struct sockaddr_un)); - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, sock_file, sizeof(addr.sun_path) - 1); -+ if (addr.sun_path[0] == '@') -+ /* "abstract" socket namespace */ -+ addr.sun_path[0] = 0; -+ else -+ unlink(sock_file); - - srv = socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK, 0); - if (srv == -1) { -diff --git a/support/reexport/reexport.c b/support/reexport/reexport.c -index eddc9bf..d9a700a 100644 ---- a/support/reexport/reexport.c -+++ b/support/reexport/reexport.c -@@ -2,7 +2,9 @@ - #include - #endif - -+#ifdef HAVE_DLFCN_H - #include -+#endif - #include - #include - #include -@@ -38,6 +40,9 @@ static bool connect_fsid_service(void) - memset(&addr, 0, sizeof(struct sockaddr_un)); - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, sock_file, sizeof(addr.sun_path) - 1); -+ if (addr.sun_path[0] == '@') -+ /* "abstract" socket namespace */ -+ addr.sun_path[0] = 0; - - s = socket(AF_UNIX, SOCK_SEQPACKET, 0); - if (s == -1) { -diff --git a/support/reexport/reexport.h b/support/reexport/reexport.h -index 3bed03a..85fd59c 100644 ---- a/support/reexport/reexport.h -+++ b/support/reexport/reexport.h -@@ -1,6 +1,8 @@ - #ifndef REEXPORT_H - #define REEXPORT_H - -+#include "nfslib.h" -+ - enum { - REEXP_NONE = 0, - REEXP_AUTO_FSIDNUM, -@@ -13,6 +15,6 @@ int reexpdb_fsidnum_by_path(char *path, uint32_t *fsidnum, int may_create); - int reexpdb_apply_reexport_settings(struct exportent *ep, char *flname, int flline); - void reexpdb_uncover_subvolume(uint32_t fsidnum); - --#define FSID_SOCKET_NAME "fsid.sock" -+#define FSID_SOCKET_NAME "@/run/fsid.sock" - - #endif /* REEXPORT_H */ -diff --git a/systemd/nfs-idmapd.service b/systemd/nfs-idmapd.service -index f38fe52..198ca87 100644 ---- a/systemd/nfs-idmapd.service -+++ b/systemd/nfs-idmapd.service -@@ -2,7 +2,8 @@ - Description=NFSv4 ID-name mapping service - DefaultDependencies=no - Requires=rpc_pipefs.target --After=rpc_pipefs.target local-fs.target -+After=rpc_pipefs.target local-fs.target network-online.target -+Wants=network-online.target - - BindsTo=nfs-server.service - -diff --git a/systemd/nfs.conf.man b/systemd/nfs.conf.man -index bfd3380..866939a 100644 ---- a/systemd/nfs.conf.man -+++ b/systemd/nfs.conf.man -@@ -137,8 +137,9 @@ but on the server, this will resolve to the path - .TP - .B exportd - Recognized values: -+.BR manage-gids , - .BR threads , --.BR cache-use-upaddr , -+.BR cache-use-ipaddr , - .BR ttl , - .BR state-directory-path - -@@ -204,7 +205,7 @@ Recognized values: - .BR port , - .BR threads , - .BR reverse-lookup , --.BR cache-use-upaddr , -+.BR cache-use-ipaddr , - .BR ttl , - .BR state-directory-path , - .BR ha-callout . -diff --git a/utils/exportd/exportd.c b/utils/exportd/exportd.c -index 2dd12cb..a2e370a 100644 ---- a/utils/exportd/exportd.c -+++ b/utils/exportd/exportd.c -@@ -16,7 +16,6 @@ - #include - #include - #include --#include - - #include "nfslib.h" - #include "conffile.h" -@@ -54,90 +53,19 @@ static char shortopts[] = "d:fghs:t:liT:"; - */ - inline static void set_signals(void); - --/* Wait for all worker child processes to exit and reap them */ --static void --wait_for_workers (void) --{ -- int status; -- pid_t pid; -- -- for (;;) { -- -- pid = waitpid(0, &status, 0); -- -- if (pid < 0) { -- if (errno == ECHILD) -- return; /* no more children */ -- xlog(L_FATAL, "mountd: can't wait: %s\n", -- strerror(errno)); -- } -- -- /* Note: because we SIG_IGN'd SIGCHLD earlier, this -- * does not happen on 2.6 kernels, and waitpid() blocks -- * until all the children are dead then returns with -- * -ECHILD. But, we don't need to do anything on the -- * death of individual workers, so we don't care. */ -- xlog(L_NOTICE, "mountd: reaped child %d, status %d\n", -- (int)pid, status); -- } --} -- - inline void - cleanup_lockfiles (void) - { - unlink(etab.lockfn); - } - --/* Fork num_threads worker children and wait for them */ - static void --fork_workers(void) --{ -- int i; -- pid_t pid; -- -- xlog(L_NOTICE, "mountd: starting %d threads\n", num_threads); -- -- for (i = 0 ; i < num_threads ; i++) { -- pid = fork(); -- if (pid < 0) { -- xlog(L_FATAL, "mountd: cannot fork: %s\n", -- strerror(errno)); -- } -- if (pid == 0) { -- /* worker child */ -- -- /* Re-enable the default action on SIGTERM et al -- * so that workers die naturally when sent them. -- * Only the parent unregisters with pmap and -- * hence needs to do special SIGTERM handling. */ -- struct sigaction sa; -- sa.sa_handler = SIG_DFL; -- sa.sa_flags = 0; -- sigemptyset(&sa.sa_mask); -- sigaction(SIGHUP, &sa, NULL); -- sigaction(SIGINT, &sa, NULL); -- sigaction(SIGTERM, &sa, NULL); -- -- /* fall into my_svc_run in caller */ -- return; -- } -- } -- -- /* in parent */ -- wait_for_workers(); -- cleanup_lockfiles(); -- free_state_path_names(&etab); -- xlog(L_NOTICE, "exportd: no more workers, exiting\n"); -- exit(0); --} -- --static void - killer (int sig) - { - if (num_threads > 1) { - /* play Kronos and eat our children */ - kill(0, SIGTERM); -- wait_for_workers(); -+ cache_wait_for_workers("exportd"); - } - cleanup_lockfiles(); - free_state_path_names(&etab); -@@ -145,6 +73,7 @@ killer (int sig) - - exit(0); - } -+ - static void - sig_hup (int UNUSED(sig)) - { -@@ -152,8 +81,9 @@ sig_hup (int UNUSED(sig)) - xlog (L_NOTICE, "Received SIGHUP... Ignoring.\n"); - return; - } --inline static void --set_signals(void) -+ -+inline static void -+set_signals(void) - { - struct sigaction sa; - -@@ -289,18 +219,27 @@ main(int argc, char **argv) - else if (num_threads > MAX_THREADS) - num_threads = MAX_THREADS; - -- if (num_threads > 1) -- fork_workers(); -+ /* Open cache channel files BEFORE forking so each upcall is -+ * only handled by one thread. Kernel provides locking for both -+ * read and write. -+ */ -+ cache_open(); - -+ if (cache_fork_workers(progname, num_threads) == 0) { -+ /* We forked, waited, and now need to clean up */ -+ cleanup_lockfiles(); -+ free_state_path_names(&etab); -+ xlog(L_NOTICE, "%s: no more workers, exiting\n", progname); -+ exit(0); -+ } - -- /* Open files now to avoid sharing descriptors among forked processes */ -- cache_open(); - v4clients_init(); - - /* Process incoming upcalls */ -- cache_process_loop(); -+ while (cache_process(NULL) >= 0) -+ ; - -- xlog(L_ERROR, "%s: process loop terminated unexpectedly. Exiting...\n", -+ xlog(L_ERROR, "%s: process loop terminated unexpectedly(%m). Exiting...\n", - progname); - - free_state_path_names(&etab); -diff --git a/utils/gssd/gssd.c b/utils/gssd/gssd.c -index 833d8e0..ca9b326 100644 ---- a/utils/gssd/gssd.c -+++ b/utils/gssd/gssd.c -@@ -365,6 +365,12 @@ gssd_read_service_info(int dirfd, struct clnt_info *clp) - - fail: - printerr(0, "ERROR: failed to parse %s/info\n", clp->relpath); -+ clp->upcall_address = strdup(address); -+ clp->upcall_port = strdup(port); -+ clp->upcall_program = program; -+ clp->upcall_vers = version; -+ clp->upcall_protoname = strdup(protoname); -+ clp->upcall_service = strdup(service); - free(servername); - free(protoname); - clp->servicename = NULL; -@@ -408,6 +414,16 @@ gssd_free_client(struct clnt_info *clp) - free(clp->servicename); - free(clp->servername); - free(clp->protocol); -+ if (!clp->servername) { -+ if (clp->upcall_address) -+ free(clp->upcall_address); -+ if (clp->upcall_port) -+ free(clp->upcall_port); -+ if (clp->upcall_protoname) -+ free(clp->upcall_protoname); -+ if (clp->upcall_service) -+ free(clp->upcall_service); -+ } - free(clp); - } - -@@ -446,6 +462,31 @@ gssd_clnt_gssd_cb(int UNUSED(fd), short UNUSED(which), void *data) - { - struct clnt_info *clp = data; - -+ /* if there was a failure to translate IP to name for this server, -+ * try again -+ */ -+ if (!clp->servername) { -+ if (!gssd_addrstr_to_sockaddr((struct sockaddr *)&clp->addr, -+ clp->upcall_address, clp->upcall_port ? -+ clp->upcall_port : "")) { -+ goto do_upcall; -+ } -+ clp->servername = gssd_get_servername(clp->upcall_address, -+ (struct sockaddr *)&clp->addr, clp->upcall_address); -+ if (!clp->servername) -+ goto do_upcall; -+ -+ if (asprintf(&clp->servicename, "%s@%s", clp->upcall_service, -+ clp->servername) < 0) { -+ free(clp->servername); -+ clp->servername = NULL; -+ goto do_upcall; -+ } -+ clp->prog = clp->upcall_program; -+ clp->vers = clp->upcall_vers; -+ clp->protocol = strdup(clp->upcall_protoname); -+ } -+do_upcall: - handle_gssd_upcall(clp); - } - -diff --git a/utils/gssd/gssd.h b/utils/gssd/gssd.h -index 519dc43..4e070ed 100644 ---- a/utils/gssd/gssd.h -+++ b/utils/gssd/gssd.h -@@ -86,6 +86,12 @@ struct clnt_info { - int gssd_fd; - struct event *gssd_ev; - struct sockaddr_storage addr; -+ char *upcall_address; -+ char *upcall_port; -+ int upcall_program; -+ int upcall_vers; -+ char *upcall_protoname; -+ char *upcall_service; - }; - - struct clnt_upcall_info { -diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c -index ae568f1..a96647d 100644 ---- a/utils/gssd/gssd_proc.c -+++ b/utils/gssd/gssd_proc.c -@@ -412,13 +412,29 @@ create_auth_rpc_client(struct clnt_info *clp, - tid, tgtname); - auth = authgss_create_default(rpc_clnt, tgtname, &sec); - if (!auth) { -+ if (sec.minor_status == KRB5KRB_AP_ERR_BAD_INTEGRITY) { -+ printerr(2, "WARNING: server=%s failed context " -+ "creation with KRB5_AP_ERR_BAD_INTEGRITY\n", -+ clp->servername); -+ if (cred == GSS_C_NO_CREDENTIAL) -+ retval = gssd_refresh_krb5_machine_credential(clp->servername, -+ "*", NULL, 1); -+ else -+ retval = gssd_k5_remove_bad_service_cred(clp->servername); -+ if (!retval) { -+ auth = authgss_create_default(rpc_clnt, tgtname, -+ &sec); -+ if (auth) -+ goto success; -+ } -+ } - /* Our caller should print appropriate message */ - printerr(2, "WARNING: Failed to create krb5 context for " - "user with uid %d for server %s\n", - uid, tgtname); - goto out_fail; - } -- -+success: - /* Success !!! */ - rpc_clnt->cl_auth = auth; - *clnt_return = rpc_clnt; -@@ -571,7 +587,7 @@ krb5_use_machine_creds(struct clnt_info *clp, uid_t uid, - - do { - gssd_refresh_krb5_machine_credential(clp->servername, -- service, srchost); -+ service, srchost, 0); - /* - * Get a list of credential cache names and try each - * of them until one works or we've tried them all -diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c -index e3f270e..6f66ef4 100644 ---- a/utils/gssd/krb5_util.c -+++ b/utils/gssd/krb5_util.c -@@ -165,7 +165,7 @@ static int select_krb5_ccache(const struct dirent *d); - static int gssd_find_existing_krb5_ccache(uid_t uid, char *dirname, - const char **cctype, struct dirent **d); - static int gssd_get_single_krb5_cred(krb5_context context, -- krb5_keytab kt, struct gssd_k5_kt_princ *ple); -+ krb5_keytab kt, struct gssd_k5_kt_princ *ple, int force_renew); - static int query_krb5_ccache(const char* cred_cache, char **ret_princname, - char **ret_realm); - -@@ -391,7 +391,8 @@ gssd_check_if_cc_exists(struct gssd_k5_kt_princ *ple) - static int - gssd_get_single_krb5_cred(krb5_context context, - krb5_keytab kt, -- struct gssd_k5_kt_princ *ple) -+ struct gssd_k5_kt_princ *ple, -+ int force_renew) - { - #ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS - krb5_get_init_creds_opt *init_opts = NULL; -@@ -421,7 +422,7 @@ gssd_get_single_krb5_cred(krb5_context context, - */ - now += 300; - pthread_mutex_lock(&ple_lock); -- if (ple->ccname && ple->endtime > now && !nocache) { -+ if (ple->ccname && ple->endtime > now && !nocache && !force_renew) { - printerr(3, "%s(0x%lx): Credentials in CC '%s' are good until %s", - __func__, tid, ple->ccname, ctime((time_t *)&ple->endtime)); - code = 0; -@@ -1155,7 +1156,8 @@ err_cache: - static int - gssd_refresh_krb5_machine_credential_internal(char *hostname, - struct gssd_k5_kt_princ *ple, -- char *service, char *srchost) -+ char *service, char *srchost, -+ int force_renew) - { - krb5_error_code code = 0; - krb5_context context; -@@ -1221,7 +1223,7 @@ gssd_refresh_krb5_machine_credential_internal(char *hostname, - goto out_free_kt; - } - } -- retval = gssd_get_single_krb5_cred(context, kt, ple); -+ retval = gssd_get_single_krb5_cred(context, kt, ple, force_renew); - out_free_kt: - krb5_kt_close(context, kt); - out_free_context: -@@ -1344,7 +1346,7 @@ gssd_get_krb5_machine_cred_list(char ***list) - pthread_mutex_unlock(&ple_lock); - /* Make sure cred is up-to-date before returning it */ - retval = gssd_refresh_krb5_machine_credential_internal(NULL, ple, -- NULL, NULL); -+ NULL, NULL, 0); - pthread_mutex_lock(&ple_lock); - if (gssd_k5_kt_princ_list == NULL) { - /* Looks like we did shutdown... abort */ -@@ -1456,10 +1458,12 @@ gssd_destroy_krb5_principals(int destroy_machine_creds) - */ - int - gssd_refresh_krb5_machine_credential(char *hostname, -- char *service, char *srchost) -+ char *service, char *srchost, -+ int force_renew) - { - return gssd_refresh_krb5_machine_credential_internal(hostname, NULL, -- service, srchost); -+ service, srchost, -+ force_renew); - } - - /* -@@ -1549,6 +1553,48 @@ gssd_acquire_user_cred(gss_cred_id_t *gss_cred) - return ret; - } - -+/* Removed a service ticket for nfs/ from the ticket cache -+ */ -+int -+gssd_k5_remove_bad_service_cred(char *name) -+{ -+ krb5_creds in_creds, out_creds; -+ krb5_error_code ret; -+ krb5_context context; -+ krb5_ccache cache; -+ krb5_principal principal; -+ int retflags = KRB5_TC_MATCH_SRV_NAMEONLY; -+ char srvname[1024]; -+ -+ ret = krb5_init_context(&context); -+ if (ret) -+ goto out_cred; -+ ret = krb5_cc_default(context, &cache); -+ if (ret) -+ goto out_free_context; -+ ret = krb5_cc_get_principal(context, cache, &principal); -+ if (ret) -+ goto out_close_cache; -+ memset(&in_creds, 0, sizeof(in_creds)); -+ in_creds.client = principal; -+ sprintf(srvname, "nfs/%s", name); -+ ret = krb5_parse_name(context, srvname, &in_creds.server); -+ if (ret) -+ goto out_free_principal; -+ ret = krb5_cc_retrieve_cred(context, cache, retflags, &in_creds, &out_creds); -+ if (ret) -+ goto out_free_principal; -+ ret = krb5_cc_remove_cred(context, cache, 0, &out_creds); -+out_free_principal: -+ krb5_free_principal(context, principal); -+out_close_cache: -+ krb5_cc_close(context, cache); -+out_free_context: -+ krb5_free_context(context); -+out_cred: -+ return ret; -+} -+ - #ifdef HAVE_SET_ALLOWABLE_ENCTYPES - /* - * this routine obtains a credentials handle via gss_acquire_cred() -diff --git a/utils/gssd/krb5_util.h b/utils/gssd/krb5_util.h -index 2415205..7ef8701 100644 ---- a/utils/gssd/krb5_util.h -+++ b/utils/gssd/krb5_util.h -@@ -16,11 +16,13 @@ int gssd_get_krb5_machine_cred_list(char ***list); - void gssd_free_krb5_machine_cred_list(char **list); - void gssd_destroy_krb5_principals(int destroy_machine_creds); - int gssd_refresh_krb5_machine_credential(char *hostname, -- char *service, char *srchost); -+ char *service, char *srchost, -+ int force_renew); - char *gssd_k5_err_msg(krb5_context context, krb5_error_code code); - void gssd_k5_get_default_realm(char **def_realm); - - int gssd_acquire_user_cred(gss_cred_id_t *gss_cred); -+int gssd_k5_remove_bad_service_cred(char *srvname); - - #ifdef HAVE_SET_ALLOWABLE_ENCTYPES - extern int limit_to_legacy_enctypes; -diff --git a/utils/mount/nfs.man b/utils/mount/nfs.man -index 7a41042..c0ba4d0 100644 ---- a/utils/mount/nfs.man -+++ b/utils/mount/nfs.man -@@ -94,31 +94,38 @@ This option is an alternative to the - option. - It is included for compatibility with other operating systems - .TP 1.5i --.BR soft " / " hard -+.BR soft " / " softerr " / " hard - Determines the recovery behavior of the NFS client - after an NFS request times out. --If neither option is specified (or if the -+If no option is specified (or if the - .B hard - option is specified), NFS requests are retried indefinitely. --If the --.B soft -+If either the -+.BR soft " or " softerr - option is specified, then the NFS client fails an NFS request - after - .B retrans - retransmissions have been sent, --causing the NFS client to return an error --to the calling application. -+causing the NFS client to return either the error -+.B EIO -+(for the -+.B soft -+option) or -+.B ETIMEDOUT -+(for the -+.B softerr -+option) to the calling application. - .IP - .I NB: - A so-called "soft" timeout can cause - silent data corruption in certain cases. As such, use the --.B soft -+.BR soft " or " softerr - option only when client responsiveness - is more important than data integrity. - Using NFS over TCP or increasing the value of the - .B retrans - option may mitigate some of the risks of using the --.B soft -+.BR soft " or " softerr - option. - .TP 1.5i - .BR softreval " / " nosoftreval -@@ -416,19 +423,6 @@ Note that the - option may also be used by some pNFS drivers to decide how many - connections to set up to the data servers. - .TP 1.5i --.BR max_connect= n --While --.BR nconnect --option sets a limit on the number of connections that can be established --to a given server IP, --.BR max_connect --option allows the user to specify maximum number of connections to different --server IPs that belong to the same NFSv4.1+ server (session trunkable --connections) up to a limit of 16. When client discovers that it established --a client ID to an already existing server, instead of dropping the newly --created network transport, the client will add this new connection to the --list of available transports for that RPC client. --.TP 1.5i - .BR rdirplus " / " nordirplus - Selects whether to use NFS v3 or v4 READDIRPLUS requests. - If this option is not specified, the NFS client uses READDIRPLUS requests -@@ -590,21 +584,28 @@ If - is specified, - transport layer security is forced off, even if the NFS server supports - transport layer security. -+.IP - If - .B tls - is specified, the client uses RPC-with-TLS to provide in-transit - confidentiality. -+.IP - If - .B mtls - is specified, the client uses RPC-with-TLS to authenticate itself and - to provide in-transit confidentiality. --If the server does not support RPC-with-TLS or peer authentication --fails, the mount attempt fails. -+.IP -+If either -+.B tls -+or -+.B mtls -+is specified and the server does not support RPC-with-TLS or peer -+authentication fails, the mount attempt fails. - .IP - If the - .B xprtsec= - option is not specified, --the default behavior depends on the kernel, -+the default behavior depends on the kernel version, - but is usually equivalent to - .BR "xprtsec=none" . - .SS "Options for NFS versions 2 and 3 only" -@@ -971,6 +972,32 @@ when it identifies itself via a traditional identification string. - .IP - This mount option has no effect with NFSv4 minor versions newer than zero, - which always use TSM-compatible client identification strings. -+.TP 1.5i -+.BR max_connect= n -+While -+.BR nconnect -+option sets a limit on the number of connections that can be established -+to a given server IP, -+.BR max_connect -+option allows the user to specify maximum number of connections to different -+server IPs that belong to the same NFSv4.1+ server (session trunkable -+connections) up to a limit of 16. When client discovers that it established -+a client ID to an already existing server, instead of dropping the newly -+created network transport, the client will add this new connection to the -+list of available transports for that RPC client. -+.TP 1.5i -+.BR trunkdiscovery " / " notrunkdiscovery -+When the client discovers a new filesystem on a NFSv4.1+ server, the -+.BR trunkdiscovery -+mount option will cause it to send a GETATTR for the fs_locations attribute. -+If is receives a non-zero length reply, it will iterate through the response, -+and for each server location it will establish a connection, send an -+EXCHANGE_ID, and test for session trunking. If the trunking test succeeds, -+the connection will be added to the existing set of transports for the server, -+subject to the limit specified by the -+.BR max_connect -+option. The default is -+.BR notrunkdiscovery . - .SH nfs4 FILE SYSTEM TYPE - The - .BR nfs4 -@@ -986,7 +1013,6 @@ file. See - .BR nfsmount.conf(5) - for details. - .SH EXAMPLES --mount option. - To mount using NFS version 3, - use the - .B nfs -diff --git a/utils/mountd/mountd.c b/utils/mountd/mountd.c -index bcf749f..dbd5546 100644 ---- a/utils/mountd/mountd.c -+++ b/utils/mountd/mountd.c -@@ -21,7 +21,6 @@ - #include - #include - #include --#include - - #include "conffile.h" - #include "xmalloc.h" -@@ -119,90 +118,17 @@ cleanup_lockfiles (void) - unlink(rmtab.lockfn); - } - --/* Wait for all worker child processes to exit and reap them */ --static void --wait_for_workers (void) --{ -- int status; -- pid_t pid; -- -- for (;;) { -- -- pid = waitpid(0, &status, 0); -- -- if (pid < 0) { -- if (errno == ECHILD) -- return; /* no more children */ -- xlog(L_FATAL, "mountd: can't wait: %s\n", -- strerror(errno)); -- } -- -- /* Note: because we SIG_IGN'd SIGCHLD earlier, this -- * does not happen on 2.6 kernels, and waitpid() blocks -- * until all the children are dead then returns with -- * -ECHILD. But, we don't need to do anything on the -- * death of individual workers, so we don't care. */ -- xlog(L_NOTICE, "mountd: reaped child %d, status %d\n", -- (int)pid, status); -- } --} -- --/* Fork num_threads worker children and wait for them */ --static void --fork_workers(void) --{ -- int i; -- pid_t pid; -- -- xlog(L_NOTICE, "mountd: starting %d threads\n", num_threads); -- -- for (i = 0 ; i < num_threads ; i++) { -- pid = fork(); -- if (pid < 0) { -- xlog(L_FATAL, "mountd: cannot fork: %s\n", -- strerror(errno)); -- } -- if (pid == 0) { -- /* worker child */ -- -- /* Re-enable the default action on SIGTERM et al -- * so that workers die naturally when sent them. -- * Only the parent unregisters with pmap and -- * hence needs to do special SIGTERM handling. */ -- struct sigaction sa; -- sa.sa_handler = SIG_DFL; -- sa.sa_flags = 0; -- sigemptyset(&sa.sa_mask); -- sigaction(SIGHUP, &sa, NULL); -- sigaction(SIGINT, &sa, NULL); -- sigaction(SIGTERM, &sa, NULL); -- -- /* fall into my_svc_run in caller */ -- return; -- } -- } -- -- /* in parent */ -- wait_for_workers(); -- unregister_services(); -- cleanup_lockfiles(); -- free_state_path_names(&etab); -- free_state_path_names(&rmtab); -- xlog(L_NOTICE, "mountd: no more workers, exiting\n"); -- exit(0); --} -- - /* - * Signal handler. - */ --static void -+static void - killer (int sig) - { - unregister_services(); - if (num_threads > 1) { - /* play Kronos and eat our children */ - kill(0, SIGTERM); -- wait_for_workers(); -+ cache_wait_for_workers("mountd"); - } - cleanup_lockfiles(); - free_state_path_names(&etab); -@@ -220,7 +146,7 @@ sig_hup (int UNUSED(sig)) - } - - bool_t --mount_null_1_svc(struct svc_req *rqstp, void *UNUSED(argp), -+mount_null_1_svc(struct svc_req *rqstp, void *UNUSED(argp), - void *UNUSED(resp)) - { - struct sockaddr *sap = nfs_getrpccaller(rqstp->rq_xprt); -@@ -916,12 +842,23 @@ main(int argc, char **argv) - else if (num_threads > MAX_THREADS) - num_threads = MAX_THREADS; - -- if (num_threads > 1) -- fork_workers(); -+ /* Open cache channel files BEFORE forking so each upcall is -+ * only handled by one thread. Kernel provides locking for both -+ * read and write. -+ */ -+ cache_open(); -+ -+ if (cache_fork_workers("mountd", num_threads) == 0) { -+ /* We forked, waited, and now need to clean up */ -+ unregister_services(); -+ cleanup_lockfiles(); -+ free_state_path_names(&etab); -+ free_state_path_names(&rmtab); -+ xlog(L_NOTICE, "mountd: no more workers, exiting\n"); -+ exit(0); -+ } - - nfsd_path_init(); -- /* Open files now to avoid sharing descriptors among forked processes */ -- cache_open(); - v4clients_init(); - - xlog(L_NOTICE, "Version " VERSION " starting"); -diff --git a/utils/mountd/mountd.h b/utils/mountd/mountd.h -index d307753..bd5c957 100644 ---- a/utils/mountd/mountd.h -+++ b/utils/mountd/mountd.h -@@ -51,13 +51,4 @@ void mountlist_del(char *host, const char *path); - void mountlist_del_all(const struct sockaddr *sap); - mountlist mountlist_list(void); - --void cache_open(void); --struct nfs_fh_len * -- cache_get_filehandle(nfs_export *exp, int len, char *p); --int cache_export(nfs_export *exp, char *path); -- --bool ipaddr_client_matches(nfs_export *exp, struct addrinfo *ai); --bool namelist_client_matches(nfs_export *exp, char *dom); --bool client_matches(nfs_export *exp, char *dom, struct addrinfo *ai); -- - #endif /* MOUNTD_H */ -diff --git a/utils/mountd/svc_run.c b/utils/mountd/svc_run.c -index 167b975..2aaf375 100644 ---- a/utils/mountd/svc_run.c -+++ b/utils/mountd/svc_run.c -@@ -97,28 +97,13 @@ my_svc_run(void) - int selret; - - for (;;) { -- - readfds = svc_fdset; -- cache_set_fds(&readfds); -- v4clients_set_fds(&readfds); -- -- selret = select(FD_SETSIZE, &readfds, -- (void *) 0, (void *) 0, (struct timeval *) 0); -- -- -- switch (selret) { -- case -1: -- if (errno == EINTR || errno == ECONNREFUSED -- || errno == ENETUNREACH || errno == EHOSTUNREACH) -- continue; -+ selret = cache_process(&readfds); -+ if (selret < 0) { - xlog(L_ERROR, "my_svc_run() - select: %m"); - return; -- -- default: -- selret -= cache_process_req(&readfds); -- selret -= v4clients_process(&readfds); -- if (selret) -- svc_getreqset(&readfds); - } -+ if (selret) -+ svc_getreqset(&readfds); - } - } -diff --git a/utils/statd/start-statd b/utils/statd/start-statd -index 2baf73c..b11a7d9 100755 ---- a/utils/statd/start-statd -+++ b/utils/statd/start-statd -@@ -11,8 +11,8 @@ exec 9> /run/rpc.statd.lock - flock -e 9 - - if [ -s /run/rpc.statd.pid ] && -- [ 1`cat /run/rpc.statd.pid` -gt 1 ] && -- kill -0 `cat /run/rpc.statd.pid` > /dev/null 2>&1 -+ [ "1$(cat /run/rpc.statd.pid)" -gt 1 ] && -+ kill -0 "$(cat /run/rpc.statd.pid)" > /dev/null 2>&1 - then - # statd already running - must have been slow to respond. - exit 0 diff --git a/nfs-utils.2.6.4-rc6.patch b/nfs-utils.2.6.4-rc6.patch deleted file mode 100644 index 708b2d5..0000000 --- a/nfs-utils.2.6.4-rc6.patch +++ /dev/null @@ -1,1618 +0,0 @@ -diff --git a/Makefile.am b/Makefile.am -index 0022084..72ad4ba 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -10,6 +10,7 @@ EXTRA_DIST = \ - autogen.sh \ - \ - aclocal/bsdsignals.m4 \ -+ aclocal/getrandom.m4 \ - aclocal/nfs-utils.m4 \ - aclocal/kerberos5.m4 \ - aclocal/tcp-wrappers.m4 \ -diff --git a/aclocal/getrandom.m4 b/aclocal/getrandom.m4 -new file mode 100644 -index 0000000..bc0fe16 ---- /dev/null -+++ b/aclocal/getrandom.m4 -@@ -0,0 +1,16 @@ -+dnl Checks for getrandom support (glibc 2.25+, musl 1.1.20+) -+dnl -+AC_DEFUN([AC_GETRANDOM], [ -+ AC_MSG_CHECKING(for getrandom()) -+ AC_LINK_IFELSE( -+ [AC_LANG_PROGRAM([[ -+ #include /* for NULL */ -+ #include -+ ]], -+ [[ return getrandom(NULL, 0U, 0U); ]] )], -+ [AC_DEFINE([HAVE_GETRANDOM], [1], [Define to 1 if you have the `getrandom' function.]) -+ AC_MSG_RESULT([yes])], -+ [AC_MSG_RESULT([no])]) -+ -+ AC_SUBST(HAVE_GETRANDOM) -+]) -diff --git a/configure.ac b/configure.ac -index 4ade528..4bff679 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -277,6 +277,9 @@ AC_TCP_WRAPPERS - # Arrange for large-file support - AC_SYS_LARGEFILE - -+dnl Check for getrandom() libc support -+AC_GETRANDOM -+ - AC_CONFIG_SRCDIR([support/include/config.h.in]) - AC_CONFIG_HEADERS([support/include/config.h]) - -@@ -335,42 +338,37 @@ AC_CHECK_HEADER(rpc/rpc.h, , - AC_MSG_ERROR([Header file rpc/rpc.h not found - maybe try building with --enable-tirpc])) - CPPFLAGS="${nfsutils_save_CPPFLAGS}" - -+AC_CHECK_HEADER(uuid/uuid.h, , -+ AC_MSG_ERROR([Cannot find needed header file uuid/uuid.h. Install libuuid-devel])) -+ -+dnl check for libevent libraries and headers -+AC_LIBEVENT -+ -+dnl Check for sqlite3 -+AC_SQLITE3_VERS -+ -+case $libsqlite3_cv_is_recent in -+yes) ;; -+unknown) -+ dnl do not fail when cross-compiling -+ AC_MSG_WARN([assuming sqlite is at least v3.3]) ;; -+*) -+ AC_MSG_ERROR([nfsdcld requires sqlite-devel]) ;; -+esac -+ - if test "$enable_nfsv4" = yes; then -- dnl check for libevent libraries and headers -- AC_LIBEVENT - - dnl check for the keyutils libraries and headers - AC_KEYUTILS - -- dnl Check for sqlite3 -- AC_SQLITE3_VERS -- - if test "$enable_nfsdcld" = "yes"; then - AC_CHECK_HEADERS([libgen.h sys/inotify.h], , - AC_MSG_ERROR([Cannot find header needed for nfsdcld])) -- -- case $libsqlite3_cv_is_recent in -- yes) ;; -- unknown) -- dnl do not fail when cross-compiling -- AC_MSG_WARN([assuming sqlite is at least v3.3]) ;; -- *) -- AC_MSG_ERROR([nfsdcld requires sqlite-devel]) ;; -- esac - fi - - if test "$enable_nfsdcltrack" = "yes"; then - AC_CHECK_HEADERS([libgen.h sys/inotify.h], , - AC_MSG_ERROR([Cannot find header needed for nfsdcltrack])) -- -- case $libsqlite3_cv_is_recent in -- yes) ;; -- unknown) -- dnl do not fail when cross-compiling -- AC_MSG_WARN([assuming sqlite is at least v3.3]) ;; -- *) -- AC_MSG_ERROR([nfsdcltrack requires sqlite-devel]) ;; -- esac - fi - - else -diff --git a/support/export/cache.c b/support/export/cache.c -index 19bbba5..6c0a44a 100644 ---- a/support/export/cache.c -+++ b/support/export/cache.c -@@ -1,10 +1,9 @@ -- - /* - * Handle communication with knfsd internal cache - * - * We open /proc/net/rpc/{auth.unix.ip,nfsd.export,nfsd.fh}/channel - * and listen for requests (using my_svc_run) -- * -+ * - */ - - #ifdef HAVE_CONFIG_H -@@ -16,6 +15,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -77,6 +77,7 @@ static bool path_lookup_error(int err) - case ENAMETOOLONG: - case ENOENT: - case ENOTDIR: -+ case EACCES: - return 1; - } - return 0; -@@ -758,7 +759,15 @@ static struct addrinfo *lookup_client_addr(char *dom) - return ret; - } - --static void nfsd_fh(int f) -+#define RETRY_SEC 120 -+struct delayed { -+ char *message; -+ time_t last_attempt; -+ int f; -+ struct delayed *next; -+} *delayed; -+ -+static int nfsd_handle_fh(int f, char *bp, int blen) - { - /* request are: - * domain fsidtype fsid -@@ -776,21 +785,13 @@ static void nfsd_fh(int f) - nfs_export *exp; - int i; - int dev_missing = 0; -- char buf[RPC_CHAN_BUF_SIZE], *bp; -- int blen; -+ char buf[RPC_CHAN_BUF_SIZE]; - int did_uncover = 0; -- -- blen = cache_read(f, buf, sizeof(buf)); -- if (blen <= 0 || buf[blen-1] != '\n') return; -- buf[blen-1] = 0; -- -- xlog(D_CALL, "nfsd_fh: inbuf '%s'", buf); -- -- bp = buf; -+ int ret = 0; - - dom = malloc(blen); - if (dom == NULL) -- return; -+ return ret; - if (qword_get(&bp, dom, blen) <= 0) - goto out; - if (qword_get_int(&bp, &fsidtype) != 0) -@@ -858,7 +859,8 @@ static void nfsd_fh(int f) - case 0: - continue; - case -1: -- goto out; -+ dev_missing ++; -+ continue; - } - if (is_ipaddr_client(dom) - && !ipaddr_client_matches(exp, ai)) -@@ -891,8 +893,10 @@ static void nfsd_fh(int f) - /* The missing dev could be what we want, so just be - * quiet rather than returning stale yet - */ -- if (dev_missing) -+ if (dev_missing) { -+ ret = 1; - goto out; -+ } - } else if (found->e_mountpoint && - !is_mountpoint(found->e_mountpoint[0]? - found->e_mountpoint: -@@ -902,7 +906,7 @@ static void nfsd_fh(int f) - xlog(L_WARNING, "%s not exported as %d not a mountpoint", - found->e_path, found->e_mountpoint); - */ -- /* FIXME we need to make sure we re-visit this later */ -+ ret = 1; - goto out; - } - -@@ -931,7 +935,68 @@ out: - free(found_path); - nfs_freeaddrinfo(ai); - free(dom); -- xlog(D_CALL, "nfsd_fh: found %p path %s", found, found ? found->e_path : NULL); -+ if (!ret) -+ xlog(D_CALL, "nfsd_fh: found %p path %s", -+ found, found ? found->e_path : NULL); -+ return ret; -+} -+ -+static void nfsd_fh(int f) -+{ -+ struct delayed *d, **dp; -+ char inbuf[RPC_CHAN_BUF_SIZE]; -+ int blen; -+ -+ blen = cache_read(f, inbuf, sizeof(inbuf)); -+ if (blen <= 0 || inbuf[blen-1] != '\n') return; -+ inbuf[blen-1] = 0; -+ -+ xlog(D_CALL, "nfsd_fh: inbuf '%s'", inbuf); -+ -+ if (nfsd_handle_fh(f, inbuf, blen) == 0) -+ return; -+ /* We don't have a definitive answer to give the kernel. -+ * This is because an export marked "mountpoint" isn't a -+ * mountpoint, or because a stat of a mountpoint fails with -+ * a strange error like ETIMEDOUT as is possible with an -+ * NFS mount marked "softerr" which is being re-exported. -+ * -+ * We cannot tell the kernel to retry, so we have to -+ * retry ourselves. -+ */ -+ d = malloc(sizeof(*d)); -+ -+ if (!d) -+ return; -+ d->message = strndup(inbuf, blen); -+ if (!d->message) { -+ free(d); -+ return; -+ } -+ d->f = f; -+ d->last_attempt = time(NULL); -+ d->next = NULL; -+ dp = &delayed; -+ while (*dp) -+ dp = &(*dp)->next; -+ *dp = d; -+} -+ -+static void nfsd_retry_fh(struct delayed *d) -+{ -+ struct delayed **dp; -+ -+ if (nfsd_handle_fh(d->f, d->message, strlen(d->message)+1) == 0) { -+ free(d->message); -+ free(d); -+ return; -+ } -+ d->last_attempt = time(NULL); -+ d->next = NULL; -+ dp = &delayed; -+ while (*dp) -+ dp = &(*dp)->next; -+ *dp = d; - } - - #ifdef HAVE_JUNCTION_SUPPORT -@@ -1510,7 +1575,7 @@ static void nfsd_export(int f) - * This will cause it not to appear in the V4 Pseudo-root - * and so a "mount" of this path will fail, just like with - * V3. -- * And filehandle for this mountpoint from an earlier -+ * Any filehandle for this mountpoint from an earlier - * mount will block in nfsd.fh lookup. - */ - xlog(L_WARNING, -@@ -1600,40 +1665,63 @@ int cache_process_req(fd_set *readfds) - } - - /** -- * cache_process_loop - process incoming upcalls -+ * cache_process - process incoming upcalls -+ * Returns -ve on error, or number of fds in svc_fds -+ * that might need processing. - */ --void cache_process_loop(void) -+int cache_process(fd_set *readfds) - { -- fd_set readfds; -+ fd_set fdset; - int selret; -+ struct timeval tv = { 24*3600, 0 }; - -- FD_ZERO(&readfds); -- -- for (;;) { -- -- cache_set_fds(&readfds); -- v4clients_set_fds(&readfds); -+ if (!readfds) { -+ FD_ZERO(&fdset); -+ readfds = &fdset; -+ } -+ cache_set_fds(readfds); -+ v4clients_set_fds(readfds); -+ -+ if (delayed) { -+ time_t now = time(NULL); -+ time_t delay; -+ if (delayed->last_attempt > now) -+ /* Clock updated - retry immediately */ -+ delayed->last_attempt = now - RETRY_SEC; -+ delay = delayed->last_attempt + RETRY_SEC - now; -+ if (delay < 0) -+ delay = 0; -+ tv.tv_sec = delay; -+ } -+ selret = select(FD_SETSIZE, readfds, NULL, NULL, &tv); - -- selret = select(FD_SETSIZE, &readfds, -- (void *) 0, (void *) 0, (struct timeval *) 0); -+ if (delayed) { -+ time_t now = time(NULL); -+ struct delayed *d = delayed; - -+ if (d->last_attempt + RETRY_SEC <= now) { -+ delayed = d->next; -+ d->next = NULL; -+ nfsd_retry_fh(d); -+ } -+ } - -- switch (selret) { -- case -1: -- if (errno == EINTR || errno == ECONNREFUSED -- || errno == ENETUNREACH || errno == EHOSTUNREACH) -- continue; -- xlog(L_ERROR, "my_svc_run() - select: %m"); -- return; -+ switch (selret) { -+ case -1: -+ if (errno == EINTR || errno == ECONNREFUSED -+ || errno == ENETUNREACH || errno == EHOSTUNREACH) -+ return 0; -+ return -1; - -- default: -- cache_process_req(&readfds); -- v4clients_process(&readfds); -- } -+ default: -+ selret -= cache_process_req(readfds); -+ selret -= v4clients_process(readfds); -+ if (selret < 0) -+ selret = 0; - } -+ return selret; - } - -- - /* - * Give IP->domain and domain+path->options to kernel - * % echo nfsd $IP $[now+DEFAULT_TTL] $domain > /proc/net/rpc/auth.unix.ip/channel -@@ -1773,3 +1861,74 @@ cache_get_filehandle(nfs_export *exp, int len, char *p) - fh.fh_size = qword_get(&bp, (char *)fh.fh_handle, NFS3_FHSIZE); - return &fh; - } -+ -+/* Wait for all worker child processes to exit and reap them */ -+void -+cache_wait_for_workers(char *prog) -+{ -+ int status; -+ pid_t pid; -+ -+ for (;;) { -+ -+ pid = waitpid(0, &status, 0); -+ -+ if (pid < 0) { -+ if (errno == ECHILD) -+ return; /* no more children */ -+ xlog(L_FATAL, "%s: can't wait: %s\n", prog, -+ strerror(errno)); -+ } -+ -+ /* Note: because we SIG_IGN'd SIGCHLD earlier, this -+ * does not happen on 2.6 kernels, and waitpid() blocks -+ * until all the children are dead then returns with -+ * -ECHILD. But, we don't need to do anything on the -+ * death of individual workers, so we don't care. */ -+ xlog(L_NOTICE, "%s: reaped child %d, status %d\n", -+ prog, (int)pid, status); -+ } -+} -+ -+/* Fork num_threads worker children and wait for them */ -+int -+cache_fork_workers(char *prog, int num_threads) -+{ -+ int i; -+ pid_t pid; -+ -+ if (num_threads <= 1) -+ return 1; -+ -+ xlog(L_NOTICE, "%s: starting %d threads\n", prog, num_threads); -+ -+ for (i = 0 ; i < num_threads ; i++) { -+ pid = fork(); -+ if (pid < 0) { -+ xlog(L_FATAL, "%s: cannot fork: %s\n", prog, -+ strerror(errno)); -+ } -+ if (pid == 0) { -+ /* worker child */ -+ -+ /* Re-enable the default action on SIGTERM et al -+ * so that workers die naturally when sent them. -+ * Only the parent unregisters with pmap and -+ * hence needs to do special SIGTERM handling. */ -+ struct sigaction sa; -+ sa.sa_handler = SIG_DFL; -+ sa.sa_flags = 0; -+ sigemptyset(&sa.sa_mask); -+ sigaction(SIGHUP, &sa, NULL); -+ sigaction(SIGINT, &sa, NULL); -+ sigaction(SIGTERM, &sa, NULL); -+ -+ /* fall into my_svc_run in caller */ -+ return 1; -+ } -+ } -+ -+ /* in parent */ -+ cache_wait_for_workers(prog); -+ return 0; -+} -diff --git a/support/export/export.h b/support/export/export.h -index 8d5a0d3..e2009cc 100644 ---- a/support/export/export.h -+++ b/support/export/export.h -@@ -29,6 +29,9 @@ int v4clients_process(fd_set *fdset); - struct nfs_fh_len * - cache_get_filehandle(nfs_export *exp, int len, char *p); - int cache_export(nfs_export *exp, char *path); -+int cache_fork_workers(char *prog, int num_threads); -+void cache_wait_for_workers(char *prog); -+int cache_process(fd_set *readfds); - - bool ipaddr_client_matches(nfs_export *exp, struct addrinfo *ai); - bool namelist_client_matches(nfs_export *exp, char *dom); -diff --git a/support/include/version.h b/support/include/version.h -deleted file mode 120000 -index b7db0bb..0000000 ---- a/support/include/version.h -+++ /dev/null -@@ -1 +0,0 @@ --../../utils/mount/version.h -\ No newline at end of file -diff --git a/support/include/version.h b/support/include/version.h -new file mode 100644 -index 0000000..d7cf680 ---- /dev/null -+++ b/support/include/version.h -@@ -0,0 +1,53 @@ -+/* -+ * version.h -- get running kernel version -+ * -+ * Copyright (C) 2008 Oracle. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public -+ * License as published by the Free Software Foundation; either -+ * version 2 of the License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public -+ * License along with this program; if not, write to the -+ * Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 0211-1301 USA -+ * -+ */ -+ -+#ifndef _NFS_UTILS_MOUNT_VERSION_H -+#define _NFS_UTILS_MOUNT_VERSION_H -+ -+#include -+#include -+ -+#include -+ -+static inline unsigned int MAKE_VERSION(unsigned int p, unsigned int q, -+ unsigned int r) -+{ -+ return (65536 * p) + (256 * q) + r; -+} -+ -+static inline unsigned int linux_version_code(void) -+{ -+ struct utsname my_utsname; -+ unsigned int p, q = 0, r = 0; -+ -+ /* UINT_MAX as backward compatibility code should not be run */ -+ if (uname(&my_utsname)) -+ return UINT_MAX; -+ -+ /* UINT_MAX as future versions might not start with an integer */ -+ if (sscanf(my_utsname.release, "%u.%u.%u", &p, &q, &r) < 1) -+ return UINT_MAX; -+ -+ return MAKE_VERSION(p, q, r); -+} -+ -+#endif /* _NFS_UTILS_MOUNT_VERSION_H */ -diff --git a/support/junction/junction.c b/support/junction/junction.c -index 0628bb0..c1ec8ff 100644 ---- a/support/junction/junction.c -+++ b/support/junction/junction.c -@@ -63,7 +63,7 @@ junction_open_path(const char *pathname, int *fd) - if (pathname == NULL || fd == NULL) - return FEDFS_ERR_INVAL; - -- tmp = open(pathname, O_PATH|O_DIRECTORY); -+ tmp = open(pathname, O_DIRECTORY); - if (tmp == -1) { - switch (errno) { - case EPERM: -diff --git a/support/nfsidmap/libnfsidmap.c b/support/nfsidmap/libnfsidmap.c -index 0a912e5..f8c3648 100644 ---- a/support/nfsidmap/libnfsidmap.c -+++ b/support/nfsidmap/libnfsidmap.c -@@ -219,10 +219,15 @@ static int domain_from_dns(char **domain) - - if (gethostname(hname, sizeof(hname)) == -1) - return -1; -- if ((he = gethostbyname(hname)) == NULL) -- return -1; -- if ((c = strchr(he->h_name, '.')) == NULL || *++c == '\0') -- return -1; -+ if ((he = gethostbyname(hname)) == NULL) { -+ IDMAP_LOG(1, ("libnfsidmap: DNS lookup of hostname failed. Attempting to use domain from hostname as is.")); -+ if ((c = strchr(hname, '.')) == NULL || *++c == '\0') -+ return -1; -+ } -+ else { -+ if ((c = strchr(he->h_name, '.')) == NULL || *++c == '\0') -+ return -1; -+ } - /* - * Query DNS to see if the _nfsv4idmapdomain TXT record exists - * If so use it... -@@ -387,7 +392,7 @@ int nfs4_init_name_mapping(char *conffile) - dflt = 1; - ret = domain_from_dns(&default_domain); - if (ret) { -- IDMAP_LOG(1, ("libnfsidmap: Unable to determine " -+ IDMAP_LOG(0, ("libnfsidmap: Unable to determine " - "the NFSv4 domain; Using '%s' as the NFSv4 domain " - "which means UIDs will be mapped to the 'Nobody-User' " - "user defined in %s", -diff --git a/support/reexport/backend_sqlite.c b/support/reexport/backend_sqlite.c -index 132f30c..0eb5ea3 100644 ---- a/support/reexport/backend_sqlite.c -+++ b/support/reexport/backend_sqlite.c -@@ -7,9 +7,16 @@ - #include - #include - #include --#include - #include - -+#ifdef HAVE_GETRANDOM -+# include -+# if !defined(SYS_getrandom) && defined(__NR_getrandom) -+ /* usable kernel-headers, but old glibc-headers */ -+# define SYS_getrandom __NR_getrandom -+# endif -+#endif -+ - #include "conffile.h" - #include "reexport_backend.h" - #include "xlog.h" -@@ -20,6 +27,15 @@ - static sqlite3 *db; - static int init_done; - -+#if !defined(HAVE_GETRANDOM) && defined(SYS_getrandom) -+/* libc without function, but we have syscall */ -+static int getrandom(void *buf, size_t buflen, unsigned int flags) -+{ -+ return (syscall(SYS_getrandom, buf, buflen, flags)); -+} -+# define HAVE_GETRANDOM -+#endif -+ - static int prng_init(void) - { - int seed; -diff --git a/support/reexport/fsidd.c b/support/reexport/fsidd.c -index 410b3a3..3e62b3f 100644 ---- a/support/reexport/fsidd.c -+++ b/support/reexport/fsidd.c -@@ -3,29 +3,25 @@ - #endif - - #include -+#ifdef HAVE_DLFCN_H - #include -+#endif - #include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include - - #include "conffile.h" - #include "reexport_backend.h" -+#include "reexport.h" - #include "xcommon.h" - #include "xlog.h" - --#define FSID_SOCKET_NAME "fsid.sock" -- - static struct event_base *evbase; - static struct reexpdb_backend_plugin *dbbackend = &sqlite_plug_ops; - -+/* assert_safe() always evalutes it argument, as it might have -+ * a side-effect. assert() won't if compiled with NDEBUG -+ */ -+#define assert_safe(__sideeffect) (__sideeffect ? 0 : ({assert(0) ; 0;})) -+ - static void client_cb(evutil_socket_t cl, short ev, void *d) - { - struct event *me = d; -@@ -56,12 +52,11 @@ static void client_cb(evutil_socket_t cl, short ev, void *d) - - if (dbbackend->fsidnum_by_path(req_path, &fsidnum, false, &found)) { - if (found) -- assert(asprintf(&answer, "+ %u", fsidnum) != -1); -+ assert_safe(asprintf(&answer, "+ %u", fsidnum) != -1); - else -- assert(asprintf(&answer, "+ ") != -1); -- -+ assert_safe(asprintf(&answer, "+ ") != -1); - } else { -- assert(asprintf(&answer, "- %s", "Command failed") != -1); -+ assert_safe(asprintf(&answer, "- %s", "Command failed") != -1); - } - - (void)send(cl, answer, strlen(answer), 0); -@@ -78,13 +73,13 @@ static void client_cb(evutil_socket_t cl, short ev, void *d) - - if (dbbackend->fsidnum_by_path(req_path, &fsidnum, true, &found)) { - if (found) { -- assert(asprintf(&answer, "+ %u", fsidnum) != -1); -+ assert_safe(asprintf(&answer, "+ %u", fsidnum) != -1); - } else { -- assert(asprintf(&answer, "+ ") != -1); -+ assert_safe(asprintf(&answer, "+ ") != -1); - } - - } else { -- assert(asprintf(&answer, "- %s", "Command failed") != -1); -+ assert_safe(asprintf(&answer, "- %s", "Command failed") != -1); - } - - (void)send(cl, answer, strlen(answer), 0); -@@ -106,15 +101,15 @@ static void client_cb(evutil_socket_t cl, short ev, void *d) - } - - if (bad_input) { -- assert(asprintf(&answer, "- %s", "Command failed: Bad input") != -1); -+ assert_safe(asprintf(&answer, "- %s", "Command failed: Bad input") != -1); - } else { - if (dbbackend->path_by_fsidnum(fsidnum, &path, &found)) { - if (found) -- assert(asprintf(&answer, "+ %s", path) != -1); -+ assert_safe(asprintf(&answer, "+ %s", path) != -1); - else -- assert(asprintf(&answer, "+ ") != -1); -+ assert_safe(asprintf(&answer, "+ ") != -1); - } else { -- assert(asprintf(&answer, "+ ") != -1); -+ assert_safe(asprintf(&answer, "+ ") != -1); - } - } - -@@ -129,7 +124,7 @@ static void client_cb(evutil_socket_t cl, short ev, void *d) - } else { - char *answer = NULL; - -- assert(asprintf(&answer, "- bad command") != -1); -+ assert_safe(asprintf(&answer, "- bad command") != -1); - (void)send(cl, answer, strlen(answer), 0); - - free(answer); -@@ -163,11 +158,14 @@ int main(void) - - sock_file = conf_get_str_with_def("reexport", "fsidd_socket", FSID_SOCKET_NAME); - -- unlink(sock_file); -- - memset(&addr, 0, sizeof(struct sockaddr_un)); - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, sock_file, sizeof(addr.sun_path) - 1); -+ if (addr.sun_path[0] == '@') -+ /* "abstract" socket namespace */ -+ addr.sun_path[0] = 0; -+ else -+ unlink(sock_file); - - srv = socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK, 0); - if (srv == -1) { -diff --git a/support/reexport/reexport.c b/support/reexport/reexport.c -index eddc9bf..7851658 100644 ---- a/support/reexport/reexport.c -+++ b/support/reexport/reexport.c -@@ -2,17 +2,12 @@ - #include - #endif - -+#ifdef HAVE_DLFCN_H - #include --#include --#include --#include --#include -+#endif - #include - #include --#include - #include --#include --#include - - #include "nfsd_path.h" - #include "conffile.h" -@@ -38,6 +33,9 @@ static bool connect_fsid_service(void) - memset(&addr, 0, sizeof(struct sockaddr_un)); - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, sock_file, sizeof(addr.sun_path) - 1); -+ if (addr.sun_path[0] == '@') -+ /* "abstract" socket namespace */ -+ addr.sun_path[0] = 0; - - s = socket(AF_UNIX, SOCK_SEQPACKET, 0); - if (s == -1) { -diff --git a/support/reexport/reexport.h b/support/reexport/reexport.h -index 3bed03a..85fd59c 100644 ---- a/support/reexport/reexport.h -+++ b/support/reexport/reexport.h -@@ -1,6 +1,8 @@ - #ifndef REEXPORT_H - #define REEXPORT_H - -+#include "nfslib.h" -+ - enum { - REEXP_NONE = 0, - REEXP_AUTO_FSIDNUM, -@@ -13,6 +15,6 @@ int reexpdb_fsidnum_by_path(char *path, uint32_t *fsidnum, int may_create); - int reexpdb_apply_reexport_settings(struct exportent *ep, char *flname, int flline); - void reexpdb_uncover_subvolume(uint32_t fsidnum); - --#define FSID_SOCKET_NAME "fsid.sock" -+#define FSID_SOCKET_NAME "@/run/fsid.sock" - - #endif /* REEXPORT_H */ -diff --git a/systemd/nfs-idmapd.service b/systemd/nfs-idmapd.service -index f38fe52..198ca87 100644 ---- a/systemd/nfs-idmapd.service -+++ b/systemd/nfs-idmapd.service -@@ -2,7 +2,8 @@ - Description=NFSv4 ID-name mapping service - DefaultDependencies=no - Requires=rpc_pipefs.target --After=rpc_pipefs.target local-fs.target -+After=rpc_pipefs.target local-fs.target network-online.target -+Wants=network-online.target - - BindsTo=nfs-server.service - -diff --git a/systemd/nfs.conf.man b/systemd/nfs.conf.man -index bfd3380..866939a 100644 ---- a/systemd/nfs.conf.man -+++ b/systemd/nfs.conf.man -@@ -137,8 +137,9 @@ but on the server, this will resolve to the path - .TP - .B exportd - Recognized values: -+.BR manage-gids , - .BR threads , --.BR cache-use-upaddr , -+.BR cache-use-ipaddr , - .BR ttl , - .BR state-directory-path - -@@ -204,7 +205,7 @@ Recognized values: - .BR port , - .BR threads , - .BR reverse-lookup , --.BR cache-use-upaddr , -+.BR cache-use-ipaddr , - .BR ttl , - .BR state-directory-path , - .BR ha-callout . -diff --git a/utils/exportd/exportd.c b/utils/exportd/exportd.c -index 2dd12cb..a2e370a 100644 ---- a/utils/exportd/exportd.c -+++ b/utils/exportd/exportd.c -@@ -16,7 +16,6 @@ - #include - #include - #include --#include - - #include "nfslib.h" - #include "conffile.h" -@@ -54,90 +53,19 @@ static char shortopts[] = "d:fghs:t:liT:"; - */ - inline static void set_signals(void); - --/* Wait for all worker child processes to exit and reap them */ --static void --wait_for_workers (void) --{ -- int status; -- pid_t pid; -- -- for (;;) { -- -- pid = waitpid(0, &status, 0); -- -- if (pid < 0) { -- if (errno == ECHILD) -- return; /* no more children */ -- xlog(L_FATAL, "mountd: can't wait: %s\n", -- strerror(errno)); -- } -- -- /* Note: because we SIG_IGN'd SIGCHLD earlier, this -- * does not happen on 2.6 kernels, and waitpid() blocks -- * until all the children are dead then returns with -- * -ECHILD. But, we don't need to do anything on the -- * death of individual workers, so we don't care. */ -- xlog(L_NOTICE, "mountd: reaped child %d, status %d\n", -- (int)pid, status); -- } --} -- - inline void - cleanup_lockfiles (void) - { - unlink(etab.lockfn); - } - --/* Fork num_threads worker children and wait for them */ - static void --fork_workers(void) --{ -- int i; -- pid_t pid; -- -- xlog(L_NOTICE, "mountd: starting %d threads\n", num_threads); -- -- for (i = 0 ; i < num_threads ; i++) { -- pid = fork(); -- if (pid < 0) { -- xlog(L_FATAL, "mountd: cannot fork: %s\n", -- strerror(errno)); -- } -- if (pid == 0) { -- /* worker child */ -- -- /* Re-enable the default action on SIGTERM et al -- * so that workers die naturally when sent them. -- * Only the parent unregisters with pmap and -- * hence needs to do special SIGTERM handling. */ -- struct sigaction sa; -- sa.sa_handler = SIG_DFL; -- sa.sa_flags = 0; -- sigemptyset(&sa.sa_mask); -- sigaction(SIGHUP, &sa, NULL); -- sigaction(SIGINT, &sa, NULL); -- sigaction(SIGTERM, &sa, NULL); -- -- /* fall into my_svc_run in caller */ -- return; -- } -- } -- -- /* in parent */ -- wait_for_workers(); -- cleanup_lockfiles(); -- free_state_path_names(&etab); -- xlog(L_NOTICE, "exportd: no more workers, exiting\n"); -- exit(0); --} -- --static void - killer (int sig) - { - if (num_threads > 1) { - /* play Kronos and eat our children */ - kill(0, SIGTERM); -- wait_for_workers(); -+ cache_wait_for_workers("exportd"); - } - cleanup_lockfiles(); - free_state_path_names(&etab); -@@ -145,6 +73,7 @@ killer (int sig) - - exit(0); - } -+ - static void - sig_hup (int UNUSED(sig)) - { -@@ -152,8 +81,9 @@ sig_hup (int UNUSED(sig)) - xlog (L_NOTICE, "Received SIGHUP... Ignoring.\n"); - return; - } --inline static void --set_signals(void) -+ -+inline static void -+set_signals(void) - { - struct sigaction sa; - -@@ -289,18 +219,27 @@ main(int argc, char **argv) - else if (num_threads > MAX_THREADS) - num_threads = MAX_THREADS; - -- if (num_threads > 1) -- fork_workers(); -+ /* Open cache channel files BEFORE forking so each upcall is -+ * only handled by one thread. Kernel provides locking for both -+ * read and write. -+ */ -+ cache_open(); - -+ if (cache_fork_workers(progname, num_threads) == 0) { -+ /* We forked, waited, and now need to clean up */ -+ cleanup_lockfiles(); -+ free_state_path_names(&etab); -+ xlog(L_NOTICE, "%s: no more workers, exiting\n", progname); -+ exit(0); -+ } - -- /* Open files now to avoid sharing descriptors among forked processes */ -- cache_open(); - v4clients_init(); - - /* Process incoming upcalls */ -- cache_process_loop(); -+ while (cache_process(NULL) >= 0) -+ ; - -- xlog(L_ERROR, "%s: process loop terminated unexpectedly. Exiting...\n", -+ xlog(L_ERROR, "%s: process loop terminated unexpectedly(%m). Exiting...\n", - progname); - - free_state_path_names(&etab); -diff --git a/utils/gssd/gssd.c b/utils/gssd/gssd.c -index 833d8e0..ca9b326 100644 ---- a/utils/gssd/gssd.c -+++ b/utils/gssd/gssd.c -@@ -365,6 +365,12 @@ gssd_read_service_info(int dirfd, struct clnt_info *clp) - - fail: - printerr(0, "ERROR: failed to parse %s/info\n", clp->relpath); -+ clp->upcall_address = strdup(address); -+ clp->upcall_port = strdup(port); -+ clp->upcall_program = program; -+ clp->upcall_vers = version; -+ clp->upcall_protoname = strdup(protoname); -+ clp->upcall_service = strdup(service); - free(servername); - free(protoname); - clp->servicename = NULL; -@@ -408,6 +414,16 @@ gssd_free_client(struct clnt_info *clp) - free(clp->servicename); - free(clp->servername); - free(clp->protocol); -+ if (!clp->servername) { -+ if (clp->upcall_address) -+ free(clp->upcall_address); -+ if (clp->upcall_port) -+ free(clp->upcall_port); -+ if (clp->upcall_protoname) -+ free(clp->upcall_protoname); -+ if (clp->upcall_service) -+ free(clp->upcall_service); -+ } - free(clp); - } - -@@ -446,6 +462,31 @@ gssd_clnt_gssd_cb(int UNUSED(fd), short UNUSED(which), void *data) - { - struct clnt_info *clp = data; - -+ /* if there was a failure to translate IP to name for this server, -+ * try again -+ */ -+ if (!clp->servername) { -+ if (!gssd_addrstr_to_sockaddr((struct sockaddr *)&clp->addr, -+ clp->upcall_address, clp->upcall_port ? -+ clp->upcall_port : "")) { -+ goto do_upcall; -+ } -+ clp->servername = gssd_get_servername(clp->upcall_address, -+ (struct sockaddr *)&clp->addr, clp->upcall_address); -+ if (!clp->servername) -+ goto do_upcall; -+ -+ if (asprintf(&clp->servicename, "%s@%s", clp->upcall_service, -+ clp->servername) < 0) { -+ free(clp->servername); -+ clp->servername = NULL; -+ goto do_upcall; -+ } -+ clp->prog = clp->upcall_program; -+ clp->vers = clp->upcall_vers; -+ clp->protocol = strdup(clp->upcall_protoname); -+ } -+do_upcall: - handle_gssd_upcall(clp); - } - -diff --git a/utils/gssd/gssd.h b/utils/gssd/gssd.h -index 519dc43..4e070ed 100644 ---- a/utils/gssd/gssd.h -+++ b/utils/gssd/gssd.h -@@ -86,6 +86,12 @@ struct clnt_info { - int gssd_fd; - struct event *gssd_ev; - struct sockaddr_storage addr; -+ char *upcall_address; -+ char *upcall_port; -+ int upcall_program; -+ int upcall_vers; -+ char *upcall_protoname; -+ char *upcall_service; - }; - - struct clnt_upcall_info { -diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c -index ae568f1..a96647d 100644 ---- a/utils/gssd/gssd_proc.c -+++ b/utils/gssd/gssd_proc.c -@@ -412,13 +412,29 @@ create_auth_rpc_client(struct clnt_info *clp, - tid, tgtname); - auth = authgss_create_default(rpc_clnt, tgtname, &sec); - if (!auth) { -+ if (sec.minor_status == KRB5KRB_AP_ERR_BAD_INTEGRITY) { -+ printerr(2, "WARNING: server=%s failed context " -+ "creation with KRB5_AP_ERR_BAD_INTEGRITY\n", -+ clp->servername); -+ if (cred == GSS_C_NO_CREDENTIAL) -+ retval = gssd_refresh_krb5_machine_credential(clp->servername, -+ "*", NULL, 1); -+ else -+ retval = gssd_k5_remove_bad_service_cred(clp->servername); -+ if (!retval) { -+ auth = authgss_create_default(rpc_clnt, tgtname, -+ &sec); -+ if (auth) -+ goto success; -+ } -+ } - /* Our caller should print appropriate message */ - printerr(2, "WARNING: Failed to create krb5 context for " - "user with uid %d for server %s\n", - uid, tgtname); - goto out_fail; - } -- -+success: - /* Success !!! */ - rpc_clnt->cl_auth = auth; - *clnt_return = rpc_clnt; -@@ -571,7 +587,7 @@ krb5_use_machine_creds(struct clnt_info *clp, uid_t uid, - - do { - gssd_refresh_krb5_machine_credential(clp->servername, -- service, srchost); -+ service, srchost, 0); - /* - * Get a list of credential cache names and try each - * of them until one works or we've tried them all -diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c -index e3f270e..6f66ef4 100644 ---- a/utils/gssd/krb5_util.c -+++ b/utils/gssd/krb5_util.c -@@ -165,7 +165,7 @@ static int select_krb5_ccache(const struct dirent *d); - static int gssd_find_existing_krb5_ccache(uid_t uid, char *dirname, - const char **cctype, struct dirent **d); - static int gssd_get_single_krb5_cred(krb5_context context, -- krb5_keytab kt, struct gssd_k5_kt_princ *ple); -+ krb5_keytab kt, struct gssd_k5_kt_princ *ple, int force_renew); - static int query_krb5_ccache(const char* cred_cache, char **ret_princname, - char **ret_realm); - -@@ -391,7 +391,8 @@ gssd_check_if_cc_exists(struct gssd_k5_kt_princ *ple) - static int - gssd_get_single_krb5_cred(krb5_context context, - krb5_keytab kt, -- struct gssd_k5_kt_princ *ple) -+ struct gssd_k5_kt_princ *ple, -+ int force_renew) - { - #ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS - krb5_get_init_creds_opt *init_opts = NULL; -@@ -421,7 +422,7 @@ gssd_get_single_krb5_cred(krb5_context context, - */ - now += 300; - pthread_mutex_lock(&ple_lock); -- if (ple->ccname && ple->endtime > now && !nocache) { -+ if (ple->ccname && ple->endtime > now && !nocache && !force_renew) { - printerr(3, "%s(0x%lx): Credentials in CC '%s' are good until %s", - __func__, tid, ple->ccname, ctime((time_t *)&ple->endtime)); - code = 0; -@@ -1155,7 +1156,8 @@ err_cache: - static int - gssd_refresh_krb5_machine_credential_internal(char *hostname, - struct gssd_k5_kt_princ *ple, -- char *service, char *srchost) -+ char *service, char *srchost, -+ int force_renew) - { - krb5_error_code code = 0; - krb5_context context; -@@ -1221,7 +1223,7 @@ gssd_refresh_krb5_machine_credential_internal(char *hostname, - goto out_free_kt; - } - } -- retval = gssd_get_single_krb5_cred(context, kt, ple); -+ retval = gssd_get_single_krb5_cred(context, kt, ple, force_renew); - out_free_kt: - krb5_kt_close(context, kt); - out_free_context: -@@ -1344,7 +1346,7 @@ gssd_get_krb5_machine_cred_list(char ***list) - pthread_mutex_unlock(&ple_lock); - /* Make sure cred is up-to-date before returning it */ - retval = gssd_refresh_krb5_machine_credential_internal(NULL, ple, -- NULL, NULL); -+ NULL, NULL, 0); - pthread_mutex_lock(&ple_lock); - if (gssd_k5_kt_princ_list == NULL) { - /* Looks like we did shutdown... abort */ -@@ -1456,10 +1458,12 @@ gssd_destroy_krb5_principals(int destroy_machine_creds) - */ - int - gssd_refresh_krb5_machine_credential(char *hostname, -- char *service, char *srchost) -+ char *service, char *srchost, -+ int force_renew) - { - return gssd_refresh_krb5_machine_credential_internal(hostname, NULL, -- service, srchost); -+ service, srchost, -+ force_renew); - } - - /* -@@ -1549,6 +1553,48 @@ gssd_acquire_user_cred(gss_cred_id_t *gss_cred) - return ret; - } - -+/* Removed a service ticket for nfs/ from the ticket cache -+ */ -+int -+gssd_k5_remove_bad_service_cred(char *name) -+{ -+ krb5_creds in_creds, out_creds; -+ krb5_error_code ret; -+ krb5_context context; -+ krb5_ccache cache; -+ krb5_principal principal; -+ int retflags = KRB5_TC_MATCH_SRV_NAMEONLY; -+ char srvname[1024]; -+ -+ ret = krb5_init_context(&context); -+ if (ret) -+ goto out_cred; -+ ret = krb5_cc_default(context, &cache); -+ if (ret) -+ goto out_free_context; -+ ret = krb5_cc_get_principal(context, cache, &principal); -+ if (ret) -+ goto out_close_cache; -+ memset(&in_creds, 0, sizeof(in_creds)); -+ in_creds.client = principal; -+ sprintf(srvname, "nfs/%s", name); -+ ret = krb5_parse_name(context, srvname, &in_creds.server); -+ if (ret) -+ goto out_free_principal; -+ ret = krb5_cc_retrieve_cred(context, cache, retflags, &in_creds, &out_creds); -+ if (ret) -+ goto out_free_principal; -+ ret = krb5_cc_remove_cred(context, cache, 0, &out_creds); -+out_free_principal: -+ krb5_free_principal(context, principal); -+out_close_cache: -+ krb5_cc_close(context, cache); -+out_free_context: -+ krb5_free_context(context); -+out_cred: -+ return ret; -+} -+ - #ifdef HAVE_SET_ALLOWABLE_ENCTYPES - /* - * this routine obtains a credentials handle via gss_acquire_cred() -diff --git a/utils/gssd/krb5_util.h b/utils/gssd/krb5_util.h -index 2415205..7ef8701 100644 ---- a/utils/gssd/krb5_util.h -+++ b/utils/gssd/krb5_util.h -@@ -16,11 +16,13 @@ int gssd_get_krb5_machine_cred_list(char ***list); - void gssd_free_krb5_machine_cred_list(char **list); - void gssd_destroy_krb5_principals(int destroy_machine_creds); - int gssd_refresh_krb5_machine_credential(char *hostname, -- char *service, char *srchost); -+ char *service, char *srchost, -+ int force_renew); - char *gssd_k5_err_msg(krb5_context context, krb5_error_code code); - void gssd_k5_get_default_realm(char **def_realm); - - int gssd_acquire_user_cred(gss_cred_id_t *gss_cred); -+int gssd_k5_remove_bad_service_cred(char *srvname); - - #ifdef HAVE_SET_ALLOWABLE_ENCTYPES - extern int limit_to_legacy_enctypes; -diff --git a/utils/mount/nfs.man b/utils/mount/nfs.man -index 7a41042..c0ba4d0 100644 ---- a/utils/mount/nfs.man -+++ b/utils/mount/nfs.man -@@ -94,31 +94,38 @@ This option is an alternative to the - option. - It is included for compatibility with other operating systems - .TP 1.5i --.BR soft " / " hard -+.BR soft " / " softerr " / " hard - Determines the recovery behavior of the NFS client - after an NFS request times out. --If neither option is specified (or if the -+If no option is specified (or if the - .B hard - option is specified), NFS requests are retried indefinitely. --If the --.B soft -+If either the -+.BR soft " or " softerr - option is specified, then the NFS client fails an NFS request - after - .B retrans - retransmissions have been sent, --causing the NFS client to return an error --to the calling application. -+causing the NFS client to return either the error -+.B EIO -+(for the -+.B soft -+option) or -+.B ETIMEDOUT -+(for the -+.B softerr -+option) to the calling application. - .IP - .I NB: - A so-called "soft" timeout can cause - silent data corruption in certain cases. As such, use the --.B soft -+.BR soft " or " softerr - option only when client responsiveness - is more important than data integrity. - Using NFS over TCP or increasing the value of the - .B retrans - option may mitigate some of the risks of using the --.B soft -+.BR soft " or " softerr - option. - .TP 1.5i - .BR softreval " / " nosoftreval -@@ -416,19 +423,6 @@ Note that the - option may also be used by some pNFS drivers to decide how many - connections to set up to the data servers. - .TP 1.5i --.BR max_connect= n --While --.BR nconnect --option sets a limit on the number of connections that can be established --to a given server IP, --.BR max_connect --option allows the user to specify maximum number of connections to different --server IPs that belong to the same NFSv4.1+ server (session trunkable --connections) up to a limit of 16. When client discovers that it established --a client ID to an already existing server, instead of dropping the newly --created network transport, the client will add this new connection to the --list of available transports for that RPC client. --.TP 1.5i - .BR rdirplus " / " nordirplus - Selects whether to use NFS v3 or v4 READDIRPLUS requests. - If this option is not specified, the NFS client uses READDIRPLUS requests -@@ -590,21 +584,28 @@ If - is specified, - transport layer security is forced off, even if the NFS server supports - transport layer security. -+.IP - If - .B tls - is specified, the client uses RPC-with-TLS to provide in-transit - confidentiality. -+.IP - If - .B mtls - is specified, the client uses RPC-with-TLS to authenticate itself and - to provide in-transit confidentiality. --If the server does not support RPC-with-TLS or peer authentication --fails, the mount attempt fails. -+.IP -+If either -+.B tls -+or -+.B mtls -+is specified and the server does not support RPC-with-TLS or peer -+authentication fails, the mount attempt fails. - .IP - If the - .B xprtsec= - option is not specified, --the default behavior depends on the kernel, -+the default behavior depends on the kernel version, - but is usually equivalent to - .BR "xprtsec=none" . - .SS "Options for NFS versions 2 and 3 only" -@@ -971,6 +972,32 @@ when it identifies itself via a traditional identification string. - .IP - This mount option has no effect with NFSv4 minor versions newer than zero, - which always use TSM-compatible client identification strings. -+.TP 1.5i -+.BR max_connect= n -+While -+.BR nconnect -+option sets a limit on the number of connections that can be established -+to a given server IP, -+.BR max_connect -+option allows the user to specify maximum number of connections to different -+server IPs that belong to the same NFSv4.1+ server (session trunkable -+connections) up to a limit of 16. When client discovers that it established -+a client ID to an already existing server, instead of dropping the newly -+created network transport, the client will add this new connection to the -+list of available transports for that RPC client. -+.TP 1.5i -+.BR trunkdiscovery " / " notrunkdiscovery -+When the client discovers a new filesystem on a NFSv4.1+ server, the -+.BR trunkdiscovery -+mount option will cause it to send a GETATTR for the fs_locations attribute. -+If is receives a non-zero length reply, it will iterate through the response, -+and for each server location it will establish a connection, send an -+EXCHANGE_ID, and test for session trunking. If the trunking test succeeds, -+the connection will be added to the existing set of transports for the server, -+subject to the limit specified by the -+.BR max_connect -+option. The default is -+.BR notrunkdiscovery . - .SH nfs4 FILE SYSTEM TYPE - The - .BR nfs4 -@@ -986,7 +1013,6 @@ file. See - .BR nfsmount.conf(5) - for details. - .SH EXAMPLES --mount option. - To mount using NFS version 3, - use the - .B nfs -diff --git a/utils/mountd/mountd.c b/utils/mountd/mountd.c -index bcf749f..dbd5546 100644 ---- a/utils/mountd/mountd.c -+++ b/utils/mountd/mountd.c -@@ -21,7 +21,6 @@ - #include - #include - #include --#include - - #include "conffile.h" - #include "xmalloc.h" -@@ -119,90 +118,17 @@ cleanup_lockfiles (void) - unlink(rmtab.lockfn); - } - --/* Wait for all worker child processes to exit and reap them */ --static void --wait_for_workers (void) --{ -- int status; -- pid_t pid; -- -- for (;;) { -- -- pid = waitpid(0, &status, 0); -- -- if (pid < 0) { -- if (errno == ECHILD) -- return; /* no more children */ -- xlog(L_FATAL, "mountd: can't wait: %s\n", -- strerror(errno)); -- } -- -- /* Note: because we SIG_IGN'd SIGCHLD earlier, this -- * does not happen on 2.6 kernels, and waitpid() blocks -- * until all the children are dead then returns with -- * -ECHILD. But, we don't need to do anything on the -- * death of individual workers, so we don't care. */ -- xlog(L_NOTICE, "mountd: reaped child %d, status %d\n", -- (int)pid, status); -- } --} -- --/* Fork num_threads worker children and wait for them */ --static void --fork_workers(void) --{ -- int i; -- pid_t pid; -- -- xlog(L_NOTICE, "mountd: starting %d threads\n", num_threads); -- -- for (i = 0 ; i < num_threads ; i++) { -- pid = fork(); -- if (pid < 0) { -- xlog(L_FATAL, "mountd: cannot fork: %s\n", -- strerror(errno)); -- } -- if (pid == 0) { -- /* worker child */ -- -- /* Re-enable the default action on SIGTERM et al -- * so that workers die naturally when sent them. -- * Only the parent unregisters with pmap and -- * hence needs to do special SIGTERM handling. */ -- struct sigaction sa; -- sa.sa_handler = SIG_DFL; -- sa.sa_flags = 0; -- sigemptyset(&sa.sa_mask); -- sigaction(SIGHUP, &sa, NULL); -- sigaction(SIGINT, &sa, NULL); -- sigaction(SIGTERM, &sa, NULL); -- -- /* fall into my_svc_run in caller */ -- return; -- } -- } -- -- /* in parent */ -- wait_for_workers(); -- unregister_services(); -- cleanup_lockfiles(); -- free_state_path_names(&etab); -- free_state_path_names(&rmtab); -- xlog(L_NOTICE, "mountd: no more workers, exiting\n"); -- exit(0); --} -- - /* - * Signal handler. - */ --static void -+static void - killer (int sig) - { - unregister_services(); - if (num_threads > 1) { - /* play Kronos and eat our children */ - kill(0, SIGTERM); -- wait_for_workers(); -+ cache_wait_for_workers("mountd"); - } - cleanup_lockfiles(); - free_state_path_names(&etab); -@@ -220,7 +146,7 @@ sig_hup (int UNUSED(sig)) - } - - bool_t --mount_null_1_svc(struct svc_req *rqstp, void *UNUSED(argp), -+mount_null_1_svc(struct svc_req *rqstp, void *UNUSED(argp), - void *UNUSED(resp)) - { - struct sockaddr *sap = nfs_getrpccaller(rqstp->rq_xprt); -@@ -916,12 +842,23 @@ main(int argc, char **argv) - else if (num_threads > MAX_THREADS) - num_threads = MAX_THREADS; - -- if (num_threads > 1) -- fork_workers(); -+ /* Open cache channel files BEFORE forking so each upcall is -+ * only handled by one thread. Kernel provides locking for both -+ * read and write. -+ */ -+ cache_open(); -+ -+ if (cache_fork_workers("mountd", num_threads) == 0) { -+ /* We forked, waited, and now need to clean up */ -+ unregister_services(); -+ cleanup_lockfiles(); -+ free_state_path_names(&etab); -+ free_state_path_names(&rmtab); -+ xlog(L_NOTICE, "mountd: no more workers, exiting\n"); -+ exit(0); -+ } - - nfsd_path_init(); -- /* Open files now to avoid sharing descriptors among forked processes */ -- cache_open(); - v4clients_init(); - - xlog(L_NOTICE, "Version " VERSION " starting"); -diff --git a/utils/mountd/mountd.h b/utils/mountd/mountd.h -index d307753..bd5c957 100644 ---- a/utils/mountd/mountd.h -+++ b/utils/mountd/mountd.h -@@ -51,13 +51,4 @@ void mountlist_del(char *host, const char *path); - void mountlist_del_all(const struct sockaddr *sap); - mountlist mountlist_list(void); - --void cache_open(void); --struct nfs_fh_len * -- cache_get_filehandle(nfs_export *exp, int len, char *p); --int cache_export(nfs_export *exp, char *path); -- --bool ipaddr_client_matches(nfs_export *exp, struct addrinfo *ai); --bool namelist_client_matches(nfs_export *exp, char *dom); --bool client_matches(nfs_export *exp, char *dom, struct addrinfo *ai); -- - #endif /* MOUNTD_H */ -diff --git a/utils/mountd/svc_run.c b/utils/mountd/svc_run.c -index 167b975..2aaf375 100644 ---- a/utils/mountd/svc_run.c -+++ b/utils/mountd/svc_run.c -@@ -97,28 +97,13 @@ my_svc_run(void) - int selret; - - for (;;) { -- - readfds = svc_fdset; -- cache_set_fds(&readfds); -- v4clients_set_fds(&readfds); -- -- selret = select(FD_SETSIZE, &readfds, -- (void *) 0, (void *) 0, (struct timeval *) 0); -- -- -- switch (selret) { -- case -1: -- if (errno == EINTR || errno == ECONNREFUSED -- || errno == ENETUNREACH || errno == EHOSTUNREACH) -- continue; -+ selret = cache_process(&readfds); -+ if (selret < 0) { - xlog(L_ERROR, "my_svc_run() - select: %m"); - return; -- -- default: -- selret -= cache_process_req(&readfds); -- selret -= v4clients_process(&readfds); -- if (selret) -- svc_getreqset(&readfds); - } -+ if (selret) -+ svc_getreqset(&readfds); - } - } -diff --git a/utils/statd/start-statd b/utils/statd/start-statd -index 2baf73c..b11a7d9 100755 ---- a/utils/statd/start-statd -+++ b/utils/statd/start-statd -@@ -11,8 +11,8 @@ exec 9> /run/rpc.statd.lock - flock -e 9 - - if [ -s /run/rpc.statd.pid ] && -- [ 1`cat /run/rpc.statd.pid` -gt 1 ] && -- kill -0 `cat /run/rpc.statd.pid` > /dev/null 2>&1 -+ [ "1$(cat /run/rpc.statd.pid)" -gt 1 ] && -+ kill -0 "$(cat /run/rpc.statd.pid)" > /dev/null 2>&1 - then - # statd already running - must have been slow to respond. - exit 0 diff --git a/nfs-utils.2.7.1-rc2.patch b/nfs-utils.2.7.1-rc2.patch deleted file mode 100644 index 4169c7b..0000000 --- a/nfs-utils.2.7.1-rc2.patch +++ /dev/null @@ -1,696 +0,0 @@ -diff --git a/configure.ac b/configure.ac -index 93a1202..58d1728 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -175,14 +175,14 @@ else - fi - - AC_ARG_ENABLE(sbin-override, -- [AS_HELP_STRING([--disable-sbin-override],[Don't force nfsdcltrack and mount helpers into /sbin: always honour --sbindir])], -+ [AS_HELP_STRING([--disable-sbin-override],[Do not force nfsdcltrack and mount helpers into /sbin: always honour --sbindir])], - enable_sbin_override=$enableval, - enable_sbin_override=yes) - AM_CONDITIONAL(CONFIG_SBIN_OVERRIDE, [test "$enable_sbin_override" = "yes"]) - AC_ARG_ENABLE(junction, -- [AS_HELP_STRING([--enable-junction],[enable support for NFS junctions @<:@default=no@:>@])], -+ [AS_HELP_STRING([--enable-junction],[enable support for NFS junctions @<:@default=yes@:>@])], - enable_junction=$enableval, -- enable_junction=no) -+ enable_junction=yes) - if test "$enable_junction" = yes; then - AC_DEFINE(HAVE_JUNCTION_SUPPORT, 1, - [Define this if you want junction support compiled in]) -diff --git a/support/export/export.c b/support/export/export.c -index 3e48c42..100912c 100644 ---- a/support/export/export.c -+++ b/support/export/export.c -@@ -119,7 +119,7 @@ export_read(char *fname, int ignore_hosts) - int reexport_found = 0; - - setexportent(fname, "r"); -- while ((eep = getexportent(0,1)) != NULL) { -+ while ((eep = getexportent(0)) != NULL) { - exp = export_lookup(eep->e_hostname, eep->e_path, ignore_hosts); - if (!exp) { - if (export_create(eep, 0)) -diff --git a/support/export/xtab.c b/support/export/xtab.c -index e210ca9..282f15b 100644 ---- a/support/export/xtab.c -+++ b/support/export/xtab.c -@@ -47,7 +47,7 @@ xtab_read(char *xtab, char *lockfn, int is_export) - setexportent(xtab, "r"); - if (is_export == 1) - v4root_needed = 1; -- while ((xp = getexportent(is_export==0, 0)) != NULL) { -+ while ((xp = getexportent(is_export==0)) != NULL) { - if (!(exp = export_lookup(xp->e_hostname, xp->e_path, is_export != 1)) && - !(exp = export_create(xp, is_export!=1))) { - if(xp->e_hostname) { -diff --git a/support/include/conffile.h b/support/include/conffile.h -index c4a3ca6..c04cd1e 100644 ---- a/support/include/conffile.h -+++ b/support/include/conffile.h -@@ -62,7 +62,7 @@ extern char *conf_get_str(const char *, const char *); - extern char *conf_get_str_with_def(const char *, const char *, char *); - extern char *conf_get_section(const char *, const char *, const char *); - extern char *conf_get_entry(const char *, const char *, const char *); --extern int conf_init_file(const char *); -+extern void conf_init_file(const char *); - extern void conf_cleanup(void); - extern int conf_match_num(const char *, const char *, int); - extern int conf_remove(int, const char *, const char *); -diff --git a/support/include/nfslib.h b/support/include/nfslib.h -index bdbde78..eff2a48 100644 ---- a/support/include/nfslib.h -+++ b/support/include/nfslib.h -@@ -111,7 +111,7 @@ struct rmtabent { - * configuration file parsing - */ - void setexportent(char *fname, char *type); --struct exportent * getexportent(int,int); -+struct exportent * getexportent(int); - void secinfo_show(FILE *fp, struct exportent *ep); - void xprtsecinfo_show(FILE *fp, struct exportent *ep); - void putexportent(struct exportent *xep); -diff --git a/support/junction/junction-internal.h b/support/junction/junction-internal.h -index 3dff4cc..7abd45c 100644 ---- a/support/junction/junction-internal.h -+++ b/support/junction/junction-internal.h -@@ -28,6 +28,7 @@ - - #include - #include -+#include - - /** - ** Names of extended attributes that store junction data -diff --git a/support/junction/xml.c b/support/junction/xml.c -index 813110b..aef1cbb 100644 ---- a/support/junction/xml.c -+++ b/support/junction/xml.c -@@ -290,7 +290,7 @@ junction_parse_xml_buf(const char *pathname, const char *name, - { - xmlDocPtr tmp; - -- tmp = xmlParseMemory(buf, (int)len); -+ tmp = xmlReadMemory(buf, (int)len, NULL, NULL, 0); - if (tmp == NULL) { - xlog(D_GENERAL, "Failed to parse XML in %s(%s)\n", - pathname, name); -@@ -387,7 +387,6 @@ junction_xml_write(const char *pathname, const char *name, xmlDocPtr doc) - return retval; - - retval = FEDFS_ERR_SVRFAULT; -- xmlIndentTreeOutput = 1; - xmlDocDumpFormatMemoryEnc(doc, &buf, &len, "UTF-8", 1); - if (len < 0) - goto out; -diff --git a/support/nfs/conffile.c b/support/nfs/conffile.c -index fd4a17a..1e9c22b 100644 ---- a/support/nfs/conffile.c -+++ b/support/nfs/conffile.c -@@ -658,7 +658,7 @@ conf_load_file(const char *conf_file) - return 0; - } - --static void -+static void - conf_init_dir(const char *conf_file) - { - struct dirent **namelist = NULL; -@@ -669,14 +669,14 @@ conf_init_dir(const char *conf_file) - dname = malloc(strlen(conf_file) + 3); - if (dname == NULL) { - xlog(L_WARNING, "conf_init_dir: malloc: %s", strerror(errno)); -- return; -+ return; - } - sprintf(dname, "%s.d", conf_file); - - n = scandir(dname, &namelist, NULL, versionsort); - if (n < 0) { - if (errno != ENOENT) { -- xlog(L_WARNING, "conf_init_dir: scandir %s: %s", -+ xlog(L_WARNING, "conf_init_dir: scandir %s: %s", - dname, strerror(errno)); - } - free(dname); -@@ -691,7 +691,7 @@ conf_init_dir(const char *conf_file) - for (i = 0; i < n; i++ ) { - struct dirent *d = namelist[i]; - -- switch (d->d_type) { -+ switch (d->d_type) { - case DT_UNKNOWN: - case DT_REG: - case DT_LNK: -@@ -701,13 +701,13 @@ conf_init_dir(const char *conf_file) - } - if (*d->d_name == '.') - continue; -- -+ - fname_len = strlen(d->d_name); - path_len = (fname_len + dname_len); - if (!fname_len || path_len > PATH_MAX) { - xlog(L_WARNING, "conf_init_dir: Too long file name: %s in %s", - d->d_name, dname); -- continue; -+ continue; - } - - /* -@@ -715,7 +715,7 @@ conf_init_dir(const char *conf_file) - * that end with CONF_FILE_EXT - */ - if (fname_len <= CONF_FILE_EXT_LEN) { -- xlog(D_GENERAL, "conf_init_dir: %s: name too short", -+ xlog(D_GENERAL, "conf_init_dir: %s: name too short", - d->d_name); - continue; - } -@@ -746,41 +746,43 @@ conf_init_dir(const char *conf_file) - free(namelist[i]); - free(namelist); - free(dname); -- -+ - return; - } - --int -+void - conf_init_file(const char *conf_file) - { - unsigned int i; -- int ret; -+ int j; - - for (i = 0; i < sizeof conf_bindings / sizeof conf_bindings[0]; i++) - LIST_INIT (&conf_bindings[i]); - - TAILQ_INIT (&conf_trans_queue); - -- if (conf_file == NULL) -- conf_file=NFS_CONFFILE; -+ if (conf_file == NULL) -+ conf_file = NFS_CONFFILE; - -- /* -- * First parse the give config file -- * then parse the config.conf.d directory -- * (if it exists) -+ /* If the config file is in /etc (normal) then check -+ * /usr/etc first. Also check config.conf.d for files -+ * names *.conf. - * -+ * Content or later files always over-rides earlier -+ * files. - */ -- ret = conf_load_file(conf_file); -- -- /* -- * When the same variable is set in both files -- * the conf.d file will override the config file. -- * This allows automated admin systems to -- * have the final say. -- */ -+ if (strncmp(conf_file, "/etc/", 5) == 0) { -+ char *usrconf = NULL; -+ -+ j = asprintf(&usrconf, "/usr%s", conf_file); -+ if (usrconf && j > 0) { -+ conf_load_file(usrconf); -+ conf_init_dir(usrconf); -+ free(usrconf); -+ } -+ } -+ conf_load_file(conf_file); - conf_init_dir(conf_file); -- -- return ret; - } - - /* -diff --git a/support/nfs/exports.c b/support/nfs/exports.c -index 15dc574..a6816e6 100644 ---- a/support/nfs/exports.c -+++ b/support/nfs/exports.c -@@ -59,7 +59,7 @@ static int *squids = NULL, nsquids = 0, - - static int getexport(char *exp, int len); - static int getpath(char *path, int len); --static int parseopts(char *cp, struct exportent *ep, int warn, int *had_subtree_opt_ptr); -+static int parseopts(char *cp, struct exportent *ep, int *had_subtree_opt_ptr); - static int parsesquash(char *list, int **idp, int *lenp, char **ep); - static int parsenum(char **cpp); - static void freesquash(void); -@@ -109,7 +109,7 @@ static void init_exportent (struct exportent *ee, int fromkernel) - } - - struct exportent * --getexportent(int fromkernel, int fromexports) -+getexportent(int fromkernel) - { - static struct exportent ee, def_ee; - char exp[512], *hostname; -@@ -147,7 +147,7 @@ getexportent(int fromkernel, int fromexports) - * we're not reading from the kernel. - */ - if (exp[0] == '-' && !fromkernel) { -- if (parseopts(exp + 1, &def_ee, 0, &has_default_subtree_opts) < 0) -+ if (parseopts(exp + 1, &def_ee, &has_default_subtree_opts) < 0) - return NULL; - - has_default_opts = 1; -@@ -185,20 +185,20 @@ getexportent(int fromkernel, int fromexports) - } - ee.e_hostname = xstrdup(hostname); - -- if (parseopts(opt, &ee, fromexports && !has_default_subtree_opts, NULL) < 0) { -- if(ee.e_hostname) -- { -- xfree(ee.e_hostname); -- ee.e_hostname=NULL; -- } -- if(ee.e_uuid) -- { -- xfree(ee.e_uuid); -- ee.e_uuid=NULL; -- } -+ if (parseopts(opt, &ee, NULL) < 0) { -+ if(ee.e_hostname) -+ { -+ xfree(ee.e_hostname); -+ ee.e_hostname=NULL; -+ } -+ if(ee.e_uuid) -+ { -+ xfree(ee.e_uuid); -+ ee.e_uuid=NULL; -+ } - - return NULL; -- } -+ } - /* resolve symlinks */ - if (realpath(ee.e_path, rpath) != NULL) { - rpath[sizeof (rpath) - 1] = '\0'; -@@ -433,7 +433,7 @@ mkexportent(char *hname, char *path, char *options) - } - strncpy(ee.e_path, path, sizeof (ee.e_path)); - ee.e_path[sizeof (ee.e_path) - 1] = '\0'; -- if (parseopts(options, &ee, 0, NULL) < 0) -+ if (parseopts(options, &ee, NULL) < 0) - return NULL; - return ⅇ - } -@@ -441,7 +441,7 @@ mkexportent(char *hname, char *path, char *options) - int - updateexportent(struct exportent *eep, char *options) - { -- if (parseopts(options, eep, 0, NULL) < 0) -+ if (parseopts(options, eep, NULL) < 0) - return 0; - return 1; - } -@@ -632,7 +632,7 @@ void fix_pseudoflavor_flags(struct exportent *ep) - * Parse option string pointed to by cp and set mount options accordingly. - */ - static int --parseopts(char *cp, struct exportent *ep, int warn, int *had_subtree_opt_ptr) -+parseopts(char *cp, struct exportent *ep, int *had_subtree_opt_ptr) - { - int had_subtree_opt = 0; - char *flname = efname?efname:"command line"; -@@ -852,13 +852,6 @@ bad_option: - ep->e_nsqgids = nsqgids; - - out: -- if (warn && !had_subtree_opt) -- xlog(L_WARNING, "%s [%d]: Neither 'subtree_check' or 'no_subtree_check' specified for export \"%s:%s\".\n" -- " Assuming default behaviour ('no_subtree_check').\n" -- " NOTE: this default has changed since nfs-utils version 1.0.x\n", -- -- flname, flline, -- ep->e_hostname, ep->e_path); - if (had_subtree_opt_ptr) - *had_subtree_opt_ptr = had_subtree_opt; - -diff --git a/support/nfsidmap/idmapd.conf.5 b/support/nfsidmap/idmapd.conf.5 -index 87e39bb..58c2d97 100644 ---- a/support/nfsidmap/idmapd.conf.5 -+++ b/support/nfsidmap/idmapd.conf.5 -@@ -37,7 +37,7 @@ Configuration file for libnfsidmap. Used by idmapd and svcgssd to map NFSv4 nam - .SH DESCRIPTION - The - .B idmapd.conf --configuration file consists of several sections, initiated by strings of the -+configuration files consists of several sections, initiated by strings of the - form [General] and [Mapping]. Each section may contain lines of the form - .nf - variable = value -@@ -398,6 +398,19 @@ LDAP_base = dc=org,dc=domain - .\" Additional sections - .\" ------------------------------------------------------------------- - .\" -+.SH FILES -+.I /usr/etc/idmapd.conf -+.br -+.I /usr/etc/idmapd.conf.d/*.conf -+.br -+.I /etc/idmapd.conf -+.br -+.I /etc/idmapd.conf.d/*.conf -+.br -+.IP -+Files are read in the order listed. Later settings override earlier -+settings. -+ - .SH SEE ALSO - .BR idmapd (8) - .BR svcgssd (8) -diff --git a/support/reexport/fsidd.c b/support/reexport/fsidd.c -index 3e62b3f..8a70b78 100644 ---- a/support/reexport/fsidd.c -+++ b/support/reexport/fsidd.c -@@ -147,6 +147,7 @@ int main(void) - { - struct event *srv_ev; - struct sockaddr_un addr; -+ socklen_t addr_len; - char *sock_file; - int srv; - -@@ -161,10 +162,12 @@ int main(void) - memset(&addr, 0, sizeof(struct sockaddr_un)); - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, sock_file, sizeof(addr.sun_path) - 1); -- if (addr.sun_path[0] == '@') -+ addr_len = sizeof(struct sockaddr_un); -+ if (addr.sun_path[0] == '@') { - /* "abstract" socket namespace */ -+ addr_len = offsetof(struct sockaddr_un, sun_path) + strlen(addr.sun_path); - addr.sun_path[0] = 0; -- else -+ } else - unlink(sock_file); - - srv = socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK, 0); -@@ -173,7 +176,7 @@ int main(void) - return 1; - } - -- if (bind(srv, (const struct sockaddr *)&addr, sizeof(struct sockaddr_un)) == -1) { -+ if (bind(srv, (const struct sockaddr *)&addr, addr_len) == -1) { - xlog(L_WARNING, "Unable to bind %s: %m\n", sock_file); - return 1; - } -diff --git a/support/reexport/reexport.c b/support/reexport/reexport.c -index 7851658..0fb49a4 100644 ---- a/support/reexport/reexport.c -+++ b/support/reexport/reexport.c -@@ -21,6 +21,7 @@ static int fsidd_srv = -1; - static bool connect_fsid_service(void) - { - struct sockaddr_un addr; -+ socklen_t addr_len; - char *sock_file; - int ret; - int s; -@@ -33,9 +34,12 @@ static bool connect_fsid_service(void) - memset(&addr, 0, sizeof(struct sockaddr_un)); - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, sock_file, sizeof(addr.sun_path) - 1); -- if (addr.sun_path[0] == '@') -+ addr_len = sizeof(struct sockaddr_un); -+ if (addr.sun_path[0] == '@') { - /* "abstract" socket namespace */ -+ addr_len = offsetof(struct sockaddr_un, sun_path) + strlen(addr.sun_path); - addr.sun_path[0] = 0; -+ } - - s = socket(AF_UNIX, SOCK_SEQPACKET, 0); - if (s == -1) { -@@ -43,7 +47,7 @@ static bool connect_fsid_service(void) - return false; - } - -- ret = connect(s, (const struct sockaddr *)&addr, sizeof(struct sockaddr_un)); -+ ret = connect(s, (const struct sockaddr *)&addr, addr_len); - if (ret == -1) { - xlog(L_WARNING, "Unable to connect %s: %m, is fsidd running?\n", sock_file); - return false; -diff --git a/systemd/nfs.conf.man b/systemd/nfs.conf.man -index 866939a..d03fc88 100644 ---- a/systemd/nfs.conf.man -+++ b/systemd/nfs.conf.man -@@ -2,10 +2,13 @@ - .SH NAME - nfs.conf \- general configuration for NFS daemons and tools - .SH SYNOPSIS -+.I /usr/etc/nfs.conf -+.I /usr/etc/nfs.conf.d/ - .I /etc/nfs.conf -+.I /etc/nfs.conf.d/ - .SH DESCRIPTION - .PP --This file contains site-specific configuration for various NFS daemons -+These files contain site-specific configuration for various NFS daemons - and other processes. Most configuration can also be passed to - processes via command line arguments, but it can be more convenient to - have a central file. In particular, this encourages consistent -@@ -314,15 +317,17 @@ See - for deatils. - - .SH FILES --.TP 10n -+.I /usr/etc/nfs.conf -+.br -+.I /usr/etc/nfs.conf.d/*.conf -+.br - .I /etc/nfs.conf --Default NFS client configuration file --.TP 10n --.I /etc/nfs.conf.d --When this directory exists and files ending --with ".conf" exist, those files will be --used to set configuration variables. These --files will override variables set in /etc/nfs.conf -+.br -+.I /etc/nfs.conf.d/*.conf -+.br -+.IP -+Various configuration files read in order. Later settings override -+earlier settings. - .SH SEE ALSO - .BR nfsdcltrack (8), - .BR rpc.nfsd (8), -diff --git a/systemd/nfs.systemd.man b/systemd/nfs.systemd.man -index 46b476a..df89ddd 100644 ---- a/systemd/nfs.systemd.man -+++ b/systemd/nfs.systemd.man -@@ -27,7 +27,9 @@ any command line arguments to daemons so as to configure their - behavior. In many case such configuration can be performed by making - changes to - .I /etc/nfs.conf --or other configuration files. When that is not convenient, a -+or other configuration files (see -+.BR nfs.conf (5)). -+When that is not convenient, a - distribution might provide systemd "drop-in" files which replace the - .B ExecStart= - setting to start the program with different arguments. For example a -@@ -171,6 +173,12 @@ running, it can be masked with - /etc/nfsmount.conf - .br - /etc/idmapd.conf -+.P -+Also similar files in -+.B /usr/etc -+and in related -+.I conf.d -+drop-in directories. - .SH SEE ALSO - .BR systemd.unit (5), - .BR nfs.conf (5), -diff --git a/tools/locktest/testlk.c b/tools/locktest/testlk.c -index ea51f78..c9bd6ba 100644 ---- a/tools/locktest/testlk.c -+++ b/tools/locktest/testlk.c -@@ -81,8 +81,8 @@ main(int argc, char **argv) - if (fl.l_type == F_UNLCK) { - printf("%s: no conflicting lock\n", fname); - } else { -- printf("%s: conflicting lock by %d on (%zd;%zd)\n", -- fname, fl.l_pid, fl.l_start, fl.l_len); -+ printf("%s: conflicting lock by %d on (%lld;%lld)\n", -+ fname, fl.l_pid, (long long)fl.l_start, (long long)fl.l_len); - } - return 0; - } -diff --git a/tools/nfsconf/nfsconfcli.c b/tools/nfsconf/nfsconfcli.c -index b2ef96d..bd9d527 100644 ---- a/tools/nfsconf/nfsconfcli.c -+++ b/tools/nfsconf/nfsconfcli.c -@@ -135,19 +135,8 @@ int main(int argc, char **argv) - return 1; - } - -- if (mode != MODE_SET && mode != MODE_UNSET) { -- if (conf_init_file(confpath)) { -- /* config file was missing or had an error, warn about it */ -- if (verbose || mode != MODE_ISSET) { -- fprintf(stderr, "Error loading config file %s\n", -- confpath); -- } -- -- /* this isnt fatal for --isset */ -- if (mode != MODE_ISSET) -- return 1; -- } -- } -+ if (mode != MODE_SET && mode != MODE_UNSET) -+ conf_init_file(confpath); - - /* --dump mode, output the current configuration */ - if (mode == MODE_DUMP) { -diff --git a/utils/mount/nfsmount.conf.man b/utils/mount/nfsmount.conf.man -index 34879c8..10287cd 100644 ---- a/utils/mount/nfsmount.conf.man -+++ b/utils/mount/nfsmount.conf.man -@@ -115,16 +115,17 @@ All mounts to the '/export/home' export will be performed in - the background (i.e. done asynchronously). - .RE - .SH FILES --.TP 10n -+.I /usr/etc/nfsmount.conf -+.br -+.I /usr/etc/nfsmount.conf.d/*.conf -+.br - .I /etc/nfsmount.conf --Default NFS mount configuration file --.TP 10n --.I /etc/nfsmount.conf.d --When this directory exists and files ending --with ".conf" exist, those files will be --used to set configuration variables. These --files will override variables set --in /etc/nfsmount.conf -+.br -+.I /etc/nfsmount.conf.d/*.conf -+.br -+.IP -+Default NFS mount configuration files, variables set in the later file -+over-ride those in the earlier file. - .PD - .SH SEE ALSO - .BR nfs (5), -diff --git a/utils/nfsref/nfsref.c b/utils/nfsref/nfsref.c -index 7f97d01..aa8414b 100644 ---- a/utils/nfsref/nfsref.c -+++ b/utils/nfsref/nfsref.c -@@ -24,8 +24,6 @@ - */ - - #include --#include --#include - #include - - #include -diff --git a/utils/nfsref/nfsref.man b/utils/nfsref/nfsref.man -index 1261549..1970f9d 100644 ---- a/utils/nfsref/nfsref.man -+++ b/utils/nfsref/nfsref.man -@@ -53,33 +53,37 @@ nfsref \- manage NFS referrals - NFS version 4 introduces the concept of - .I file system referrals - to NFS. --A file system referral is like a symbolic link on a file server --to another file system share, possibly on another file server. --On an NFS client, a referral behaves like an automounted directory. --The client, under the server's direction, mounts a new NFS export --automatically when an application first accesses that directory. - .P --Referrals are typically used to construct a single file name space --across multiple file servers. --Because file servers control the shape of the name space, --no client configuration is required, --and all clients see the same referral information. -+A file system referral is like a symbolic link -+(or, -+.IR symlink ) -+to another file system share, typically on another file server. -+An NFS client, under the server's direction, -+mounts the referred-to NFS export -+automatically when an application first accesses it. - .P --The Linux NFS server supports NFS version 4 referrals. --Administrators can specify the --.B refer= --export option in --.I /etc/exports --to configure a list of exports from which the client can choose. --See --.BR exports (5) --for details. -+NFSv4 referrals can be used to transparently redirect clients -+to file systems that have been moved elsewhere, or -+to construct a single file name space across multiple file servers. -+Because file servers control the shape of the whole file name space, -+no client configuration is required. - .P - .SH DESCRIPTION -+A -+.I junction -+is a file system object on an NFS server that, -+when an NFS client encounters it, triggers a referral. -+Similar to a symlink, a junction contains one or more target locations -+that the server sends to clients in the form of an NFSv4 referral. -+.P -+On Linux, an existing directory can be converted to a junction -+and back atomically and without the loss of the directory contents. -+When a directory acts as a junction, it's local content is hidden -+from NFSv4 clients. -+.P - The - .BR nfsref (8) --command is a simple way to get started managing junction metadata. --Other administrative commands provide richer access to junction information. -+command is a simple way to get started managing junctions and their content. - .SS Subcommands - Valid - .BR nfsref (8) -@@ -135,6 +139,10 @@ For the - .B add - subcommand, the default value if this option is not specified is - .BR nfs-basic . -+The -+.B nfs-fedfs -+type is not used in this implementation. -+.IP - For the - .B remove - and -@@ -163,18 +171,12 @@ you might issue this command as root: - .sp - # mkdir /home - .br --# nfsref --type=nfs-basic add /home home.example.net / -+# nfsref add /home home.example.net / - .br - Created junction /home. - .sp - .RE --.SH FILES --.TP --.I /etc/exports --NFS server export table - .SH "SEE ALSO" --.BR exports (5) --.sp --RFC 5661 for a description of NFS version 4 referrals -+RFC 8881 for a description of the NFS version 4 referral mechanism - .SH "AUTHOR" - Chuck Lever diff --git a/nfs-utils.spec b/nfs-utils.spec index cbe9ed1..fb0d2f6 100644 --- a/nfs-utils.spec +++ b/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://linux-nfs.org/ Version: 2.7.1 -Release: 0%{?dist} +Release: 1%{?dist} Epoch: 1 # group all 32bit related archs @@ -18,8 +18,7 @@ Patch100: nfs-utils-1.2.1-statdpath-man.patch Patch102: nfs-utils-1.2.5-idmap-errmsg.patch Patch103: nfs-utils-2.3.1-systemd-gssproxy-restart.patch Patch104: nfs-utils-2.3.3-man-tcpwrappers.patch -Patch105: nfs-utils-2.3.3-nfsconf-usegssproxy.patch -Patch106: nfs-utils-2.4.2-systemd-svcgssd.patch +Patch105: nfs-utils-2.7.1-strip-svcgssd.patch Provides: exportfs = %{epoch}:%{version}-%{release} Provides: nfsstat = %{epoch}:%{version}-%{release} @@ -430,6 +429,9 @@ rm -rf /etc/systemd/system/rpc-*.requires %{_mandir}/*/nfsiostat.8.gz %changelog +* Thu Aug 22 2024 Steve Dickson 2.7.1-1 +- Disable use-gss-proxy in /etc/nfs.conf (RHEL-55766) + * Thu Aug 22 2024 Steve Dickson 2.7.1-0 - Updated to the latest upstream release: nfs-utils-2-7-1 (RHEL-55764)