From f0b81e8d48950827d09ddfa8662a11c18dae5be0 Mon Sep 17 00:00:00 2001 From: Steve Dickson Date: Aug 23 2012 18:13:49 +0000 Subject: Updated to latest upstream RC release: nfs-utils.1.2.7-rc5 (bz 833024) Signed-off-by: Steve Dickson --- diff --git a/nfs-utils-1.2.7-rc3.patch b/nfs-utils-1.2.7-rc3.patch deleted file mode 100644 index 6c3fff0..0000000 --- a/nfs-utils-1.2.7-rc3.patch +++ /dev/null @@ -1,611 +0,0 @@ -a69f6aeb19841f5a95c3eb4f4e5fe5ca0db247f4 blkmapd: remove pretty_sig() -diff --git a/utils/blkmapd/device-process.c b/utils/blkmapd/device-process.c -index 652a7a8..5fe3dff 100644 ---- a/utils/blkmapd/device-process.c -+++ b/utils/blkmapd/device-process.c -@@ -49,28 +49,6 @@ - - #include "device-discovery.h" - --static char *pretty_sig(char *sig, uint32_t siglen) --{ -- static char rs[100]; -- uint64_t sigval; -- unsigned int i; -- -- if (siglen <= sizeof(sigval)) { -- sigval = 0; -- for (i = 0; i < siglen; i++) -- sigval |= ((unsigned char *)sig)[i] << (i * 8); -- sprintf(rs, "0x%0llx", (unsigned long long) sigval); -- } else { -- if (siglen > sizeof rs - 4) { -- siglen = sizeof rs - 4; -- sprintf(&rs[siglen], "..."); -- } else -- rs[siglen] = '\0'; -- memcpy(rs, sig, siglen); -- } -- return rs; --} -- - uint32_t *blk_overflow(uint32_t * p, uint32_t * end, size_t nbytes) - { - uint32_t *q = p + ((nbytes + 3) >> 2); -@@ -109,9 +87,6 @@ static int decode_blk_signature(uint32_t **pp, uint32_t * end, - * for mapping, then thrown away. - */ - comp->bs_string = (char *)p; -- BL_LOG_INFO("%s: si_comps[%d]: bs_length %d, bs_string %s\n", -- __func__, i, siglen, -- pretty_sig(comp->bs_string, siglen)); - p += ((siglen + 3) >> 2); - } - *pp = p; -@@ -152,10 +127,6 @@ read_cmp_blk_sig(struct bl_disk *disk, int fd, struct bl_sig_comp *comp) - } - - ret = memcmp(sig, comp->bs_string, siglen); -- if (!ret) -- BL_LOG_INFO("%s: %s sig %s at %lld\n", __func__, dev_name, -- pretty_sig(sig, siglen), -- (long long)comp->bs_offset); - - out: - if (sig) -d4d392087f8ee049ed8f476e5ae780cbc0d0012a osd_login - ensure /sbin is created before installation. -diff --git a/utils/osd_login/Makefile.am b/utils/osd_login/Makefile.am -index adc493a..20c2d8c 100644 ---- a/utils/osd_login/Makefile.am -+++ b/utils/osd_login/Makefile.am -@@ -1,12 +1,9 @@ - ## Process this file with automake to produce Makefile.in - --OSD_LOGIN_FILES= osd_login -+# These binaries go in /sbin (not /usr/sbin), and that cannot be -+# overridden at config time. -+sbindir = /sbin - --EXTRA_DIST= $(OSD_LOGIN_FILES) -- --all-local: $(OSD_LOGIN_FILES) -- --install-data-hook: -- $(INSTALL) --mode 755 osd_login $(DESTDIR)/sbin/osd_login -+sbin_SCRIPTS = osd_login - - MAINTAINERCLEANFILES = Makefile.in -646be42c84305d02dea06113cc9e6c9a7ab94f8a Makefile.am: Corrected a misspelling of overridden -diff --git a/utils/mount/Makefile.am b/utils/mount/Makefile.am -index 7627854..5810936 100644 ---- a/utils/mount/Makefile.am -+++ b/utils/mount/Makefile.am -@@ -1,7 +1,7 @@ - ## Process this file with automake to produce Makefile.in - - # These binaries go in /sbin (not /usr/sbin), and that cannot be --# overriden at config time. -+# overridden at config time. - sbindir = /sbin - - man8_MANS = mount.nfs.man umount.nfs.man -7e9c0f760397d7e8fa78bdeefffc14eb8269925b autoconf: make the test for prctl have an effect -diff --git a/aclocal/libcap.m4 b/aclocal/libcap.m4 -index 68a624c..f8a0ed1 100644 ---- a/aclocal/libcap.m4 -+++ b/aclocal/libcap.m4 -@@ -3,7 +3,7 @@ dnl - AC_DEFUN([AC_LIBCAP], [ - - dnl look for prctl -- AC_CHECK_FUNC([prctl], , ) -+ AC_CHECK_FUNC([prctl], , AC_MSG_ERROR([prctl syscall is not available])) - - AC_ARG_ENABLE([caps], - [AS_HELP_STRING([--disable-caps], [Disable capabilities support])]) -ddb095f82becc94c8e3a2429cc755dee5d1808c9 build: avoid AM_CONDITIONAL in conditional execution. -diff --git a/aclocal/libsqlite3.m4 b/aclocal/libsqlite3.m4 -index 73d1e46..8c38993 100644 ---- a/aclocal/libsqlite3.m4 -+++ b/aclocal/libsqlite3.m4 -@@ -29,5 +29,4 @@ AC_DEFUN([AC_SQLITE3_VERS], [ - LIBS="$saved_LIBS"]) - - AC_MSG_RESULT($libsqlite3_cv_is_recent) -- AM_CONDITIONAL(CONFIG_SQLITE3, [test "$libsqlite3_cv_is_recent" = "yes"]) - ])dnl -diff --git a/configure.ac b/configure.ac -index 9ba53e2..b408f1b 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -278,8 +278,6 @@ if test "$enable_nfsv4" = yes; then - fi - fi - -- AM_CONDITIONAL(CONFIG_NFSDCLD, [test "$enable_nfsdcld" = "yes" ]) -- - dnl librpcsecgss already has a dependency on libgssapi, - dnl but we need to make sure we get the right version - if test "$enable_gss" = yes; then -@@ -293,6 +291,7 @@ if test "$enable_nfsv41" = yes; then - fi - - dnl enable nfsidmap when its support by libnfsidmap -+AM_CONDITIONAL(CONFIG_NFSDCLD, [test "$enable_nfsdcld" = "yes" ]) - AM_CONDITIONAL(CONFIG_NFSIDMAP, [test "$ac_cv_header_keyutils_h$ac_cv_lib_nfsidmap_nfs4_owner_to_uid" = "yesyes"]) - - -1ca82a963ace17397bd7ec09f5e0707badd7c254 statd: drop all capabilities from the bounding set as well -diff --git a/support/nsm/file.c b/support/nsm/file.c -index 5dd52c1..5476446 100644 ---- a/support/nsm/file.c -+++ b/support/nsm/file.c -@@ -338,10 +338,10 @@ nsm_is_default_parentdir(void) - * - * Returns true if successful, or false if some error occurred. - */ -+#ifdef HAVE_SYS_CAPABILITY_H - static _Bool - nsm_clear_capabilities(void) - { --#ifdef HAVE_SYS_CAPABILITY_H - cap_t caps; - - caps = cap_from_text("cap_net_bind_service=ep"); -@@ -357,10 +357,60 @@ nsm_clear_capabilities(void) - } - - (void)cap_free(caps); --#endif - return true; - } - -+#define CAP_BOUND_PROCFILE "/proc/sys/kernel/cap-bound" -+static _Bool -+prune_bounding_set(void) -+{ -+#ifdef PR_CAPBSET_DROP -+ int ret; -+ unsigned long i; -+ struct stat st; -+ -+ /* -+ * Prior to kernel 2.6.25, the capabilities bounding set was a global -+ * value. Check to see if /proc/sys/kernel/cap-bound exists and don't -+ * bother to clear the bounding set if it does. -+ */ -+ ret = stat(CAP_BOUND_PROCFILE, &st); -+ if (!ret) { -+ xlog(L_WARNING, "%s exists. Not attempting to clear " -+ "capabilities bounding set.", -+ CAP_BOUND_PROCFILE); -+ return true; -+ } else if (errno != ENOENT) { -+ /* Warn, but attempt to clear the bounding set anyway. */ -+ xlog(L_WARNING, "Unable to stat %s: %m", CAP_BOUND_PROCFILE); -+ } -+ -+ /* prune the bounding set to nothing */ -+ for (i = 0; i <= CAP_LAST_CAP; ++i) { -+ ret = prctl(PR_CAPBSET_DROP, i, 0, 0, 0); -+ if (ret) { -+ xlog(L_ERROR, "Unable to prune capability %lu from " -+ "bounding set: %m", i); -+ return false; -+ } -+ } -+#endif /* PR_CAPBSET_DROP */ -+ return true; -+} -+#else /* !HAVE_SYS_CAPABILITY_H */ -+static _Bool -+nsm_clear_capabilities(void) -+{ -+ return true; -+} -+ -+static _Bool -+prune_bounding_set(void) -+{ -+ return true; -+} -+#endif /* HAVE_SYS_CAPABILITY_H */ -+ - /** - * nsm_drop_privileges - drop root privileges - * @pidfd: file descriptor of a pid file -@@ -393,6 +443,9 @@ nsm_drop_privileges(const int pidfd) - return false; - } - -+ if (!prune_bounding_set()) -+ return false; -+ - if (st.st_uid == 0) { - xlog_warn("Running as root. " - "chown %s to choose different user", nsm_base_dirname); -43537ecbc1ab3ae7cefe5d47e7e03b14bf428197 nfsidmap: Allow verbosity level to be set in the config file -diff --git a/utils/nfsidmap/nfsidmap.c b/utils/nfsidmap/nfsidmap.c -index cf11551..b767395 100644 ---- a/utils/nfsidmap/nfsidmap.c -+++ b/utils/nfsidmap/nfsidmap.c -@@ -12,6 +12,7 @@ - - #include - #include "xlog.h" -+#include "conffile.h" - - int verbose = 0; - char *usage="Usage: %s [-v] [-c || [-u|-g|-r key] || [-t timeout] key desc]"; -@@ -26,12 +27,27 @@ char *usage="Usage: %s [-v] [-c || [-u|-g|-r key] || [-t timeout] key desc]"; - #define DEFAULT_KEYRING "id_resolver" - #endif - -+#ifndef PATH_IDMAPDCONF -+#define PATH_IDMAPDCONF "/etc/idmapd.conf" -+#endif -+ - static int keyring_clear(char *keyring); - - #define UIDKEYS 0x1 - #define GIDKEYS 0x2 - - /* -+ * Check to the config file for the verbosity level -+ */ -+int -+get_config_verbose(char *path) -+{ -+ conf_path = path; -+ conf_init(); -+ return conf_get_num("General", "Verbosity", 0); -+} -+ -+/* - * Find either a user or group id based on the name@domain string - */ - int id_lookup(char *name_at_domain, key_serial_t key, int type) -@@ -266,7 +282,9 @@ int main(int argc, char **argv) - break; - } - } -- -+ if (!verbose) { -+ verbose = get_config_verbose(PATH_IDMAPDCONF); -+ } - if (keystr) { - rc = key_revoke(keystr, keymask); - return rc; -0781cf2a60dbb0d8997c4abef103d80f819cd16f Updated the version number. -diff --git a/README b/README -index 348f5d4..e55b2dd 100644 ---- a/README -+++ b/README -@@ -1,4 +1,4 @@ --This is version 1.1.0 of nfs-utils, the Linux NFS utility package. -+This is version 1.2.6 of nfs-utils, the Linux NFS utility package. - - - 0. PROJECT RESOURCES -b66c96de551b650680a65a732a1338c3ec25b436 nsm_client: nsm_client needs to link with libtirpc -diff --git a/tests/nsm_client/Makefile.am b/tests/nsm_client/Makefile.am -index 4bf0a45..4c15346 100644 ---- a/tests/nsm_client/Makefile.am -+++ b/tests/nsm_client/Makefile.am -@@ -13,7 +13,7 @@ nsm_client_SOURCES = $(GENFILES) nsm_client.c - - BUILT_SOURCES = $(GENFILES) - nsm_client_LDADD = ../../support/nfs/libnfs.a \ -- ../../support/nsm/libnsm.a $(LIBCAP) -+ ../../support/nsm/libnsm.a $(LIBCAP) $(LIBTIRPC) - - if CONFIG_RPCGEN - RPCGEN = $(top_builddir)/tools/rpcgen/rpcgen -eae2fa997223ce0edb4218faf2ff67165535d21d mountd: Honor the no_root_squash flag on pseudo roots -diff --git a/utils/mountd/v4root.c b/utils/mountd/v4root.c -index 708eb61..726b50d 100644 ---- a/utils/mountd/v4root.c -+++ b/utils/mountd/v4root.c -@@ -62,6 +62,8 @@ void set_pseudofs_security(struct exportent *pseudo, struct exportent *source) - - if (source->e_flags & NFSEXP_INSECURE_PORT) - pseudo->e_flags |= NFSEXP_INSECURE_PORT; -+ if ((source->e_flags & NFSEXP_ROOTSQUASH) == 0) -+ pseudo->e_flags &= ~NFSEXP_ROOTSQUASH; - for (se = source->e_secinfo; se->flav; se++) { - struct sec_entry *new; - -@@ -92,7 +94,8 @@ v4root_create(char *path, nfs_export *export) - exp = export_create(&eep, 0); - if (exp == NULL) - return NULL; -- xlog(D_CALL, "v4root_create: path '%s'", exp->m_export.e_path); -+ xlog(D_CALL, "v4root_create: path '%s' flags 0x%x", -+ exp->m_export.e_path, exp->m_export.e_flags); - return &exp->m_export; - } - -55b1769e63cdffa07b597fa6132c9902cec25265 rpcdebug: Add new "state" flag for the nfs module -diff --git a/support/include/nfs/debug.h b/support/include/nfs/debug.h -index dbec5ba..80a1b1d 100644 ---- a/support/include/nfs/debug.h -+++ b/support/include/nfs/debug.h -@@ -79,6 +79,7 @@ enum { - #define NFSDBG_FSCACHE 0x0800 - #define NFSDBG_PNFS 0x1000 - #define NFSDBG_PNFS_LD 0x2000 -+#define NFSDBG_STATE 0x4000 - #define NFSDBG_ALL 0xFFFF - - #endif /* _NFS_DEBUG_H */ -diff --git a/tools/rpcdebug/rpcdebug.c b/tools/rpcdebug/rpcdebug.c -index 444616d..d6e10d3 100644 ---- a/tools/rpcdebug/rpcdebug.c -+++ b/tools/rpcdebug/rpcdebug.c -@@ -170,6 +170,7 @@ static struct flagmap { - FLAG(NFS, FSCACHE), - FLAG(NFS, PNFS), - FLAG(NFS, PNFS_LD), -+ FLAG(NFS, STATE), - FLAG(NFS, ALL), - - /* nfsd */ -d18b89cd7352783580f3d3dde26f8617e36459b9 nfsdcld: Before clearing the capability bounding set, check if we have the cap -diff --git a/support/nsm/file.c b/support/nsm/file.c -index 5476446..4711c2c 100644 ---- a/support/nsm/file.c -+++ b/support/nsm/file.c -@@ -386,7 +386,7 @@ prune_bounding_set(void) - } - - /* prune the bounding set to nothing */ -- for (i = 0; i <= CAP_LAST_CAP; ++i) { -+ for (i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) >=0 ; ++i) { - ret = prctl(PR_CAPBSET_DROP, i, 0, 0, 0); - if (ret) { - xlog(L_ERROR, "Unable to prune capability %lu from " -diff --git a/utils/nfsdcld/nfsdcld.c b/utils/nfsdcld/nfsdcld.c -index e7af4e3..473d069 100644 ---- a/utils/nfsdcld/nfsdcld.c -+++ b/utils/nfsdcld/nfsdcld.c -@@ -102,8 +102,8 @@ cld_set_caps(void) - } - - /* prune the bounding set to nothing */ -- for (i = 0; i <= CAP_LAST_CAP; ++i) { -- ret = prctl(PR_CAPBSET_DROP, i); -+ for (i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) >= 0 ; ++i) { -+ ret = prctl(PR_CAPBSET_DROP, i, 0, 0, 0); - if (ret) { - xlog(L_ERROR, "Unable to prune capability %lu from " - "bounding set: %m", i); -78ee5f378f295e7bff24a7be41b9361f406d4f8b mount.nfs: try the next address after mount fails with ETIMEDOUT -diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c -index e09aa7c..0aa9a75 100644 ---- a/utils/mount/stropts.c -+++ b/utils/mount/stropts.c -@@ -665,6 +665,7 @@ static int nfs_try_mount_v3v2(struct nfsmount_info *mi) - case ECONNREFUSED: - case EOPNOTSUPP: - case EHOSTUNREACH: -+ case ETIMEDOUT: - continue; - default: - goto out; -@@ -752,6 +753,7 @@ static int nfs_try_mount_v4(struct nfsmount_info *mi) - switch (errno) { - case ECONNREFUSED: - case EHOSTUNREACH: -+ case ETIMEDOUT: - continue; - default: - goto out; -8c3d608410c2c8f405fc74d47aa3bcab1933f974 exportfs: Update exportfs flush option list in usage message. -diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c -index a3323d7..9f79541 100644 ---- a/utils/exportfs/exportfs.c -+++ b/utils/exportfs/exportfs.c -@@ -40,7 +40,7 @@ static void unexportfs(char *arg, int verbose); - static void exports_update(int verbose); - static void dump(int verbose); - static void error(nfs_export *exp, int err); --static void usage(const char *progname); -+static void usage(const char *progname, int n); - static void validate_export(nfs_export *exp); - static int matchhostname(const char *hostname1, const char *hostname2); - static void export_d_read(const char *dname); -@@ -105,11 +105,17 @@ main(int argc, char **argv) - - export_errno = 0; - -- while ((c = getopt(argc, argv, "aio:ruvf")) != EOF) { -+ while ((c = getopt(argc, argv, "afhio:ruv")) != EOF) { - switch(c) { - case 'a': - f_all = 1; - break; -+ case 'f': -+ force_flush = 1; -+ break; -+ case 'h': -+ usage(progname, 0); -+ break; - case 'i': - f_ignore = 1; - break; -@@ -126,11 +132,8 @@ main(int argc, char **argv) - case 'v': - f_verbose = 1; - break; -- case 'f': -- force_flush = 1; -- break; - default: -- usage(progname); -+ usage(progname, 1); - break; - } - } -@@ -723,8 +726,8 @@ error(nfs_export *exp, int err) - } - - static void --usage(const char *progname) -+usage(const char *progname, int n) - { -- fprintf(stderr, "usage: %s [-aruv] [host:/path]\n", progname); -- exit(1); -+ fprintf(stderr, "usage: %s [-afhioruv] [host:/path]\n", progname); -+ exit(n); - } -fd27c638898010438d404cd17120729ef1d680e2 nfsidmap: Default domain not being set. -diff --git a/utils/nfsidmap/nfsidmap.c b/utils/nfsidmap/nfsidmap.c -index b767395..e14543c 100644 ---- a/utils/nfsidmap/nfsidmap.c -+++ b/utils/nfsidmap/nfsidmap.c -@@ -37,17 +37,6 @@ static int keyring_clear(char *keyring); - #define GIDKEYS 0x2 - - /* -- * Check to the config file for the verbosity level -- */ --int --get_config_verbose(char *path) --{ -- conf_path = path; -- conf_init(); -- return conf_get_num("General", "Verbosity", 0); --} -- --/* - * Find either a user or group id based on the name@domain string - */ - int id_lookup(char *name_at_domain, key_serial_t key, int type) -@@ -282,9 +271,14 @@ int main(int argc, char **argv) - break; - } - } -- if (!verbose) { -- verbose = get_config_verbose(PATH_IDMAPDCONF); -+ -+ if (nfs4_init_name_mapping(PATH_IDMAPDCONF)) { -+ xlog_err("Unable to create name to user id mappings."); -+ return 1; - } -+ if (!verbose) -+ verbose = conf_get_num("General", "Verbosity", 0); -+ - if (keystr) { - rc = key_revoke(keystr, keymask); - return rc; -76908c3f14a12e865054ea5d6e4cad201c28839a mount.nfs: restore correct error status when umount fails -diff --git a/utils/mount/mount_libmount.c b/utils/mount/mount_libmount.c -index e8f17a9..5c1116a 100644 ---- a/utils/mount/mount_libmount.c -+++ b/utils/mount/mount_libmount.c -@@ -173,6 +173,7 @@ static int umount_main(struct libmnt_context *cxt, int argc, char **argv) - { - int rc, c; - char *spec = NULL, *opts = NULL; -+ int ret = EX_FAIL; - - static const struct option longopts[] = { - { "force", 0, 0, 'f' }, -@@ -243,7 +244,7 @@ static int umount_main(struct libmnt_context *cxt, int argc, char **argv) - /* strange, no entry in mtab or /proc not mounted */ - nfs_umount23(spec, "tcp,v3"); - } -- -+ ret = EX_FILEIO; - rc = mnt_context_do_umount(cxt); /* call umount(2) syscall */ - mnt_context_finalize_mount(cxt); /* mtab update */ - -@@ -252,12 +253,10 @@ static int umount_main(struct libmnt_context *cxt, int argc, char **argv) - umount_error(rc, spec); - goto err; - } -- -- free(opts); -- return EX_SUCCESS; -+ ret = EX_SUCCESS; - err: - free(opts); -- return EX_FAIL; -+ return ret; - } - - static int mount_main(struct libmnt_context *cxt, int argc, char **argv) -4dac21d1e8ff31c3b01f7f29e7cf877e89f09eaa rpc.gssd: close upcall pipe on POLLHUP -diff --git a/utils/gssd/gssd.h b/utils/gssd/gssd.h -index 28a8206..71a140b 100644 ---- a/utils/gssd/gssd.h -+++ b/utils/gssd/gssd.h -@@ -81,8 +81,10 @@ struct clnt_info { - char *protocol; - int krb5_fd; - int krb5_poll_index; -+ int krb5_close_me; - int gssd_fd; - int gssd_poll_index; -+ int gssd_close_me; - struct sockaddr_storage addr; - }; - -diff --git a/utils/gssd/gssd_main_loop.c b/utils/gssd/gssd_main_loop.c -index cec09ea..c18e12c 100644 ---- a/utils/gssd/gssd_main_loop.c -+++ b/utils/gssd/gssd_main_loop.c -@@ -78,8 +78,10 @@ scan_poll_results(int ret) - { - i = clp->gssd_poll_index; - if (i >= 0 && pollarray[i].revents) { -- if (pollarray[i].revents & POLLHUP) -+ if (pollarray[i].revents & POLLHUP) { -+ clp->gssd_close_me = 1; - dir_changed = 1; -+ } - if (pollarray[i].revents & POLLIN) - handle_gssd_upcall(clp); - pollarray[clp->gssd_poll_index].revents = 0; -@@ -89,8 +91,10 @@ scan_poll_results(int ret) - } - i = clp->krb5_poll_index; - if (i >= 0 && pollarray[i].revents) { -- if (pollarray[i].revents & POLLHUP) -+ if (pollarray[i].revents & POLLHUP) { -+ clp->krb5_close_me = 1; - dir_changed = 1; -+ } - if (pollarray[i].revents & POLLIN) - handle_krb5_upcall(clp); - pollarray[clp->krb5_poll_index].revents = 0; -diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c -index aa39435..2861d06 100644 ---- a/utils/gssd/gssd_proc.c -+++ b/utils/gssd/gssd_proc.c -@@ -340,6 +340,25 @@ process_clnt_dir_files(struct clnt_info * clp) - char gname[PATH_MAX]; - char info_file_name[PATH_MAX]; - -+ if (clp->gssd_close_me) { -+ printerr(2, "Closing 'gssd' pipe for %s\n", clp->dirname); -+ close(clp->gssd_fd); -+ memset(&pollarray[clp->gssd_poll_index], 0, -+ sizeof(struct pollfd)); -+ clp->gssd_fd = -1; -+ clp->gssd_poll_index = -1; -+ clp->gssd_close_me = 0; -+ } -+ if (clp->krb5_close_me) { -+ printerr(2, "Closing 'krb5' pipe for %s\n", clp->dirname); -+ close(clp->krb5_fd); -+ memset(&pollarray[clp->krb5_poll_index], 0, -+ sizeof(struct pollfd)); -+ clp->krb5_fd = -1; -+ clp->krb5_poll_index = -1; -+ clp->krb5_close_me = 0; -+ } -+ - if (clp->gssd_fd == -1) { - snprintf(gname, sizeof(gname), "%s/gssd", clp->dirname); - clp->gssd_fd = open(gname, O_RDWR); diff --git a/nfs-utils-1.2.7-rc5.patch b/nfs-utils-1.2.7-rc5.patch new file mode 100644 index 0000000..d7ba4b0 --- /dev/null +++ b/nfs-utils-1.2.7-rc5.patch @@ -0,0 +1,1200 @@ +diff --git a/README b/README +index 348f5d4..e55b2dd 100644 +--- a/README ++++ b/README +@@ -1,4 +1,4 @@ +-This is version 1.1.0 of nfs-utils, the Linux NFS utility package. ++This is version 1.2.6 of nfs-utils, the Linux NFS utility package. + + + 0. PROJECT RESOURCES +diff --git a/aclocal/libcap.m4 b/aclocal/libcap.m4 +index 68a624c..f8a0ed1 100644 +--- a/aclocal/libcap.m4 ++++ b/aclocal/libcap.m4 +@@ -3,7 +3,7 @@ dnl + AC_DEFUN([AC_LIBCAP], [ + + dnl look for prctl +- AC_CHECK_FUNC([prctl], , ) ++ AC_CHECK_FUNC([prctl], , AC_MSG_ERROR([prctl syscall is not available])) + + AC_ARG_ENABLE([caps], + [AS_HELP_STRING([--disable-caps], [Disable capabilities support])]) +diff --git a/aclocal/libsqlite3.m4 b/aclocal/libsqlite3.m4 +index 73d1e46..8c38993 100644 +--- a/aclocal/libsqlite3.m4 ++++ b/aclocal/libsqlite3.m4 +@@ -29,5 +29,4 @@ AC_DEFUN([AC_SQLITE3_VERS], [ + LIBS="$saved_LIBS"]) + + AC_MSG_RESULT($libsqlite3_cv_is_recent) +- AM_CONDITIONAL(CONFIG_SQLITE3, [test "$libsqlite3_cv_is_recent" = "yes"]) + ])dnl +diff --git a/configure.ac b/configure.ac +index 9ba53e2..a174bf4 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -278,8 +278,6 @@ if test "$enable_nfsv4" = yes; then + fi + fi + +- AM_CONDITIONAL(CONFIG_NFSDCLD, [test "$enable_nfsdcld" = "yes" ]) +- + dnl librpcsecgss already has a dependency on libgssapi, + dnl but we need to make sure we get the right version + if test "$enable_gss" = yes; then +@@ -290,9 +288,11 @@ fi + if test "$enable_nfsv41" = yes; then + AC_CHECK_LIB([devmapper], [dm_task_create], [LIBDEVMAPPER="-ldevmapper"], AC_MSG_ERROR([libdevmapper needed])) + AC_CHECK_HEADER(libdevmapper.h, , AC_MSG_ERROR([Cannot find devmapper header file libdevmapper.h])) ++ AC_CHECK_HEADER(sys/inotify.h, , AC_MSG_ERROR([Cannot find header file sys/inotify.h])) + fi + + dnl enable nfsidmap when its support by libnfsidmap ++AM_CONDITIONAL(CONFIG_NFSDCLD, [test "$enable_nfsdcld" = "yes" ]) + AM_CONDITIONAL(CONFIG_NFSIDMAP, [test "$ac_cv_header_keyutils_h$ac_cv_lib_nfsidmap_nfs4_owner_to_uid" = "yesyes"]) + + +@@ -393,7 +393,7 @@ AC_CHECK_FUNCS([alarm atexit dup2 fdatasync ftruncate getcwd \ + gethostbyaddr gethostbyname gethostname getmntent \ + getnameinfo getrpcbyname getifaddrs \ + gettimeofday hasmntopt inet_ntoa innetgr memset mkdir pathconf \ +- realpath rmdir select socket strcasecmp strchr strdup \ ++ ppoll realpath rmdir select socket strcasecmp strchr strdup \ + strerror strrchr strtol strtoul sigprocmask]) + + +diff --git a/support/include/nfs/debug.h b/support/include/nfs/debug.h +index dbec5ba..80a1b1d 100644 +--- a/support/include/nfs/debug.h ++++ b/support/include/nfs/debug.h +@@ -79,6 +79,7 @@ enum { + #define NFSDBG_FSCACHE 0x0800 + #define NFSDBG_PNFS 0x1000 + #define NFSDBG_PNFS_LD 0x2000 ++#define NFSDBG_STATE 0x4000 + #define NFSDBG_ALL 0xFFFF + + #endif /* _NFS_DEBUG_H */ +diff --git a/support/nsm/file.c b/support/nsm/file.c +index 5dd52c1..4711c2c 100644 +--- a/support/nsm/file.c ++++ b/support/nsm/file.c +@@ -338,10 +338,10 @@ nsm_is_default_parentdir(void) + * + * Returns true if successful, or false if some error occurred. + */ ++#ifdef HAVE_SYS_CAPABILITY_H + static _Bool + nsm_clear_capabilities(void) + { +-#ifdef HAVE_SYS_CAPABILITY_H + cap_t caps; + + caps = cap_from_text("cap_net_bind_service=ep"); +@@ -357,10 +357,60 @@ nsm_clear_capabilities(void) + } + + (void)cap_free(caps); +-#endif + return true; + } + ++#define CAP_BOUND_PROCFILE "/proc/sys/kernel/cap-bound" ++static _Bool ++prune_bounding_set(void) ++{ ++#ifdef PR_CAPBSET_DROP ++ int ret; ++ unsigned long i; ++ struct stat st; ++ ++ /* ++ * Prior to kernel 2.6.25, the capabilities bounding set was a global ++ * value. Check to see if /proc/sys/kernel/cap-bound exists and don't ++ * bother to clear the bounding set if it does. ++ */ ++ ret = stat(CAP_BOUND_PROCFILE, &st); ++ if (!ret) { ++ xlog(L_WARNING, "%s exists. Not attempting to clear " ++ "capabilities bounding set.", ++ CAP_BOUND_PROCFILE); ++ return true; ++ } else if (errno != ENOENT) { ++ /* Warn, but attempt to clear the bounding set anyway. */ ++ xlog(L_WARNING, "Unable to stat %s: %m", CAP_BOUND_PROCFILE); ++ } ++ ++ /* prune the bounding set to nothing */ ++ for (i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) >=0 ; ++i) { ++ ret = prctl(PR_CAPBSET_DROP, i, 0, 0, 0); ++ if (ret) { ++ xlog(L_ERROR, "Unable to prune capability %lu from " ++ "bounding set: %m", i); ++ return false; ++ } ++ } ++#endif /* PR_CAPBSET_DROP */ ++ return true; ++} ++#else /* !HAVE_SYS_CAPABILITY_H */ ++static _Bool ++nsm_clear_capabilities(void) ++{ ++ return true; ++} ++ ++static _Bool ++prune_bounding_set(void) ++{ ++ return true; ++} ++#endif /* HAVE_SYS_CAPABILITY_H */ ++ + /** + * nsm_drop_privileges - drop root privileges + * @pidfd: file descriptor of a pid file +@@ -393,6 +443,9 @@ nsm_drop_privileges(const int pidfd) + return false; + } + ++ if (!prune_bounding_set()) ++ return false; ++ + if (st.st_uid == 0) { + xlog_warn("Running as root. " + "chown %s to choose different user", nsm_base_dirname); +diff --git a/tests/nsm_client/Makefile.am b/tests/nsm_client/Makefile.am +index 4bf0a45..4c15346 100644 +--- a/tests/nsm_client/Makefile.am ++++ b/tests/nsm_client/Makefile.am +@@ -13,7 +13,7 @@ nsm_client_SOURCES = $(GENFILES) nsm_client.c + + BUILT_SOURCES = $(GENFILES) + nsm_client_LDADD = ../../support/nfs/libnfs.a \ +- ../../support/nsm/libnsm.a $(LIBCAP) ++ ../../support/nsm/libnsm.a $(LIBCAP) $(LIBTIRPC) + + if CONFIG_RPCGEN + RPCGEN = $(top_builddir)/tools/rpcgen/rpcgen +diff --git a/tools/rpcdebug/rpcdebug.c b/tools/rpcdebug/rpcdebug.c +index 444616d..d6e10d3 100644 +--- a/tools/rpcdebug/rpcdebug.c ++++ b/tools/rpcdebug/rpcdebug.c +@@ -170,6 +170,7 @@ static struct flagmap { + FLAG(NFS, FSCACHE), + FLAG(NFS, PNFS), + FLAG(NFS, PNFS_LD), ++ FLAG(NFS, STATE), + FLAG(NFS, ALL), + + /* nfsd */ +diff --git a/utils/blkmapd/device-discovery.c b/utils/blkmapd/device-discovery.c +index c21de3e..df4627e 100644 +--- a/utils/blkmapd/device-discovery.c ++++ b/utils/blkmapd/device-discovery.c +@@ -31,10 +31,12 @@ + #include + #include + #include ++#include + #include + #include + #include + #include ++#include + + #include + #include +@@ -50,10 +52,17 @@ + + #include "device-discovery.h" + ++#define EVENT_SIZE (sizeof(struct inotify_event)) ++#define EVENT_BUFSIZE (1024 * EVENT_SIZE) ++ + #define BL_PIPE_FILE "/var/lib/nfs/rpc_pipefs/nfs/blocklayout" ++#define NFSPIPE_DIR "/var/lib/nfs/rpc_pipefs/nfs" ++#define RPCPIPE_DIR "/var/lib/nfs/rpc_pipefs" + #define PID_FILE "/var/run/blkmapd.pid" + + struct bl_disk *visible_disk_list; ++int bl_watch_fd, bl_pipe_fd, nfs_pipedir_wfd, rpc_pipedir_wfd; ++int pidfd = -1; + + struct bl_disk_path *bl_get_path(const char *filepath, + struct bl_disk_path *paths) +@@ -262,7 +271,7 @@ int bl_discover_devices(void) + * return 1: request processed, and more requests waiting; + * return < 0: error + */ +-int bl_disk_inquiry_process(int fd) ++static int bl_disk_inquiry_process(int fd) + { + int ret = 0; + struct bl_pipemsg_hdr head; +@@ -338,23 +347,70 @@ int bl_disk_inquiry_process(int fd) + return ret; + } + +-/* TODO: set bl_process_stop to 1 in command */ +-unsigned int bl_process_stop; ++static void bl_watch_dir(const char* dir, int *wd) ++{ ++ *wd = inotify_add_watch(bl_watch_fd, dir, IN_CREATE|IN_DELETE); ++ if (*wd < 0) ++ BL_LOG_ERR("failed to watch %s: %s\n", dir, strerror(errno)); ++} + +-int bl_run_disk_inquiry_process(int fd) ++static void bl_rpcpipe_cb(void) + { +- fd_set rset; +- int ret; ++ int rc, curr_byte = 0; ++ char eventArr[EVENT_BUFSIZE]; ++ struct inotify_event *event; ++ ++ rc = read(bl_watch_fd, &eventArr, EVENT_BUFSIZE); ++ if (rc < 0) ++ BL_LOG_ERR("read event fail: %s", strerror(errno)); ++ ++ while (rc > curr_byte) { ++ event = (struct inotify_event *)&eventArr[curr_byte]; ++ curr_byte += EVENT_SIZE + event->len; ++ if (event->wd == rpc_pipedir_wfd) { ++ if (strncmp(event->name, "nfs", 3)) ++ continue; ++ if (event->mask & IN_CREATE) { ++ BL_LOG_WARNING("nfs pipe dir created\n"); ++ bl_watch_dir(NFSPIPE_DIR, &nfs_pipedir_wfd); ++ bl_pipe_fd = open(BL_PIPE_FILE, O_RDWR); ++ } else if (event->mask & IN_DELETE) { ++ BL_LOG_WARNING("nfs pipe dir deleted\n"); ++ inotify_rm_watch(bl_watch_fd, nfs_pipedir_wfd); ++ close(bl_pipe_fd); ++ nfs_pipedir_wfd = -1; ++ bl_pipe_fd = -1; ++ } ++ } else if (event->wd == nfs_pipedir_wfd) { ++ if (strncmp(event->name, "blocklayout", 11)) ++ continue; ++ if (event->mask & IN_CREATE) { ++ BL_LOG_WARNING("blocklayout pipe file created\n"); ++ bl_pipe_fd = open(BL_PIPE_FILE, O_RDWR); ++ if (bl_pipe_fd < 0) ++ BL_LOG_ERR("open %s failed: %s\n", ++ event->name, strerror(errno)); ++ } else if (event->mask & IN_DELETE) { ++ BL_LOG_WARNING("blocklayout pipe file deleted\n"); ++ close(bl_pipe_fd); ++ bl_pipe_fd = -1; ++ } ++ } ++ } ++} + +- bl_process_stop = 0; ++static int bl_event_helper(void) ++{ ++ fd_set rset; ++ int ret = 0, maxfd; + + for (;;) { +- if (bl_process_stop) +- return 1; + FD_ZERO(&rset); +- FD_SET(fd, &rset); +- ret = 0; +- switch (select(fd + 1, &rset, NULL, NULL, NULL)) { ++ FD_SET(bl_watch_fd, &rset); ++ if (bl_pipe_fd > 0) ++ FD_SET(bl_pipe_fd, &rset); ++ maxfd = (bl_watch_fd>bl_pipe_fd)?bl_watch_fd:bl_pipe_fd; ++ switch (select(maxfd + 1, &rset, NULL, NULL, NULL)) { + case -1: + if (errno == EINTR) + continue; +@@ -365,18 +421,32 @@ int bl_run_disk_inquiry_process(int fd) + case 0: + goto out; + default: +- if (FD_ISSET(fd, &rset)) +- ret = bl_disk_inquiry_process(fd); ++ if (FD_ISSET(bl_watch_fd, &rset)) ++ bl_rpcpipe_cb(); ++ else if (bl_pipe_fd > 0 && FD_ISSET(bl_pipe_fd, &rset)) ++ ret = bl_disk_inquiry_process(bl_pipe_fd); ++ if (ret) ++ goto out; + } + } + out: + return ret; + } + ++void sig_die(int signal) ++{ ++ if (pidfd >= 0) { ++ close(pidfd); ++ unlink(PID_FILE); ++ } ++ BL_LOG_ERR("exit on signal(%d)\n", signal); ++ exit(1); ++} ++ + /* Daemon */ + int main(int argc, char **argv) + { +- int fd, pidfd = -1, opt, dflag = 0, fg = 0, ret = 1; ++ int opt, dflag = 0, fg = 0, ret = 1; + struct stat statbuf; + char pidbuf[64]; + +@@ -421,23 +491,33 @@ int main(int argc, char **argv) + write(pidfd, pidbuf, strlen(pidbuf)); + } + ++ signal(SIGINT, sig_die); ++ signal(SIGTERM, sig_die); ++ signal(SIGHUP, SIG_IGN); ++ + if (dflag) { + bl_discover_devices(); + exit(0); + } + +- /* open pipe file */ +- fd = open(BL_PIPE_FILE, O_RDWR); +- if (fd < 0) { +- BL_LOG_ERR("open pipe file %s error\n", BL_PIPE_FILE); ++ if ((bl_watch_fd = inotify_init()) < 0) { ++ BL_LOG_ERR("init inotify failed %s\n", strerror(errno)); + exit(1); + } + ++ /* open pipe file */ ++ bl_watch_dir(RPCPIPE_DIR, &rpc_pipedir_wfd); ++ bl_watch_dir(NFSPIPE_DIR, &nfs_pipedir_wfd); ++ ++ bl_pipe_fd = open(BL_PIPE_FILE, O_RDWR); ++ if (bl_pipe_fd < 0) ++ BL_LOG_ERR("open pipe file %s failed: %s\n", BL_PIPE_FILE, strerror(errno)); ++ + while (1) { + /* discover device when needed */ + bl_discover_devices(); + +- ret = bl_run_disk_inquiry_process(fd); ++ ret = bl_event_helper(); + if (ret < 0) { + /* what should we do with process error? */ + BL_LOG_ERR("inquiry process return %d\n", ret); +diff --git a/utils/blkmapd/device-process.c b/utils/blkmapd/device-process.c +index 652a7a8..5fe3dff 100644 +--- a/utils/blkmapd/device-process.c ++++ b/utils/blkmapd/device-process.c +@@ -49,28 +49,6 @@ + + #include "device-discovery.h" + +-static char *pretty_sig(char *sig, uint32_t siglen) +-{ +- static char rs[100]; +- uint64_t sigval; +- unsigned int i; +- +- if (siglen <= sizeof(sigval)) { +- sigval = 0; +- for (i = 0; i < siglen; i++) +- sigval |= ((unsigned char *)sig)[i] << (i * 8); +- sprintf(rs, "0x%0llx", (unsigned long long) sigval); +- } else { +- if (siglen > sizeof rs - 4) { +- siglen = sizeof rs - 4; +- sprintf(&rs[siglen], "..."); +- } else +- rs[siglen] = '\0'; +- memcpy(rs, sig, siglen); +- } +- return rs; +-} +- + uint32_t *blk_overflow(uint32_t * p, uint32_t * end, size_t nbytes) + { + uint32_t *q = p + ((nbytes + 3) >> 2); +@@ -109,9 +87,6 @@ static int decode_blk_signature(uint32_t **pp, uint32_t * end, + * for mapping, then thrown away. + */ + comp->bs_string = (char *)p; +- BL_LOG_INFO("%s: si_comps[%d]: bs_length %d, bs_string %s\n", +- __func__, i, siglen, +- pretty_sig(comp->bs_string, siglen)); + p += ((siglen + 3) >> 2); + } + *pp = p; +@@ -152,10 +127,6 @@ read_cmp_blk_sig(struct bl_disk *disk, int fd, struct bl_sig_comp *comp) + } + + ret = memcmp(sig, comp->bs_string, siglen); +- if (!ret) +- BL_LOG_INFO("%s: %s sig %s at %lld\n", __func__, dev_name, +- pretty_sig(sig, siglen), +- (long long)comp->bs_offset); + + out: + if (sig) +diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c +index a3323d7..9f79541 100644 +--- a/utils/exportfs/exportfs.c ++++ b/utils/exportfs/exportfs.c +@@ -40,7 +40,7 @@ static void unexportfs(char *arg, int verbose); + static void exports_update(int verbose); + static void dump(int verbose); + static void error(nfs_export *exp, int err); +-static void usage(const char *progname); ++static void usage(const char *progname, int n); + static void validate_export(nfs_export *exp); + static int matchhostname(const char *hostname1, const char *hostname2); + static void export_d_read(const char *dname); +@@ -105,11 +105,17 @@ main(int argc, char **argv) + + export_errno = 0; + +- while ((c = getopt(argc, argv, "aio:ruvf")) != EOF) { ++ while ((c = getopt(argc, argv, "afhio:ruv")) != EOF) { + switch(c) { + case 'a': + f_all = 1; + break; ++ case 'f': ++ force_flush = 1; ++ break; ++ case 'h': ++ usage(progname, 0); ++ break; + case 'i': + f_ignore = 1; + break; +@@ -126,11 +132,8 @@ main(int argc, char **argv) + case 'v': + f_verbose = 1; + break; +- case 'f': +- force_flush = 1; +- break; + default: +- usage(progname); ++ usage(progname, 1); + break; + } + } +@@ -723,8 +726,8 @@ error(nfs_export *exp, int err) + } + + static void +-usage(const char *progname) ++usage(const char *progname, int n) + { +- fprintf(stderr, "usage: %s [-aruv] [host:/path]\n", progname); +- exit(1); ++ fprintf(stderr, "usage: %s [-afhioruv] [host:/path]\n", progname); ++ exit(n); + } +diff --git a/utils/gssd/gssd.h b/utils/gssd/gssd.h +index 28a8206..86472a1 100644 +--- a/utils/gssd/gssd.h ++++ b/utils/gssd/gssd.h +@@ -45,8 +45,8 @@ + #define DNOTIFY_SIGNAL (SIGRTMIN + 3) + + #define GSSD_DEFAULT_CRED_DIR "/tmp" +-#define GSSD_USER_CRED_DIR "/run/user" +-#define GSSD_DEFAULT_CRED_PREFIX "krb5cc_" ++#define GSSD_USER_CRED_DIR "/run/user/%U" ++#define GSSD_DEFAULT_CRED_PREFIX "krb5cc" + #define GSSD_DEFAULT_MACHINE_CRED_SUFFIX "machine" + #define GSSD_DEFAULT_KEYTAB_FILE "/etc/krb5.keytab" + #define GSSD_SERVICE_NAME "nfs" +@@ -81,8 +81,10 @@ struct clnt_info { + char *protocol; + int krb5_fd; + int krb5_poll_index; ++ int krb5_close_me; + int gssd_fd; + int gssd_poll_index; ++ int gssd_close_me; + struct sockaddr_storage addr; + }; + +diff --git a/utils/gssd/gssd.man b/utils/gssd/gssd.man +index d8138fa..c74b7e8 100644 +--- a/utils/gssd/gssd.man ++++ b/utils/gssd/gssd.man +@@ -103,9 +103,12 @@ where to look for the rpc_pipefs filesystem. The default value is + .B -d directory + Tells + .B rpc.gssd +-where to look for Kerberos credential files. The default value is "/tmp". +-This can also be a colon separated list of directories to be searched +-for Kerberos credential files. Note that if machine credentials are being ++where to look for Kerberos credential files. The default value is ++"/tmp:/run/user/%U". ++This can also be a colon separated list of directories to be searched for ++Kerberos credential files. The sequence "%U", if used, is replaced with ++the UID of the user for whom credentials are being searched. ++Note that if machine credentials are being + stored in files, then the first directory on this list is where the + machine credentials are stored. + .TP +diff --git a/utils/gssd/gssd_main_loop.c b/utils/gssd/gssd_main_loop.c +index cec09ea..ccf7fe5 100644 +--- a/utils/gssd/gssd_main_loop.c ++++ b/utils/gssd/gssd_main_loop.c +@@ -55,16 +55,14 @@ + #include "err_util.h" + + extern struct pollfd *pollarray; +-extern int pollsize; ++extern unsigned long pollsize; + + #define POLL_MILLISECS 500 + + static volatile int dir_changed = 1; + +-static void dir_notify_handler(int sig, siginfo_t *si, void *data) ++static void dir_notify_handler(__attribute__((unused))int sig) + { +- printerr(2, "dir_notify_handler: sig %d si %p data %p\n", sig, si, data); +- + dir_changed = 1; + } + +@@ -78,8 +76,10 @@ scan_poll_results(int ret) + { + i = clp->gssd_poll_index; + if (i >= 0 && pollarray[i].revents) { +- if (pollarray[i].revents & POLLHUP) ++ if (pollarray[i].revents & POLLHUP) { ++ clp->gssd_close_me = 1; + dir_changed = 1; ++ } + if (pollarray[i].revents & POLLIN) + handle_gssd_upcall(clp); + pollarray[clp->gssd_poll_index].revents = 0; +@@ -89,8 +89,10 @@ scan_poll_results(int ret) + } + i = clp->krb5_poll_index; + if (i >= 0 && pollarray[i].revents) { +- if (pollarray[i].revents & POLLHUP) ++ if (pollarray[i].revents & POLLHUP) { ++ clp->krb5_close_me = 1; + dir_changed = 1; ++ } + if (pollarray[i].revents & POLLIN) + handle_krb5_upcall(clp); + pollarray[clp->krb5_poll_index].revents = 0; +@@ -99,7 +101,7 @@ scan_poll_results(int ret) + break; + } + } +-}; ++} + + static int + topdirs_add_entry(struct dirent *dent) +@@ -119,11 +121,13 @@ topdirs_add_entry(struct dirent *dent) + } + snprintf(tdi->dirname, PATH_MAX, "%s/%s", pipefs_dir, dent->d_name); + tdi->fd = open(tdi->dirname, O_RDONLY); +- if (tdi->fd != -1) { +- fcntl(tdi->fd, F_SETSIG, DNOTIFY_SIGNAL); +- fcntl(tdi->fd, F_NOTIFY, +- DN_CREATE|DN_DELETE|DN_MODIFY|DN_MULTISHOT); ++ if (tdi->fd == -1) { ++ printerr(0, "ERROR: failed to open %s\n", tdi->dirname); ++ free(tdi); ++ return -1; + } ++ fcntl(tdi->fd, F_SETSIG, DNOTIFY_SIGNAL); ++ fcntl(tdi->fd, F_NOTIFY, DN_CREATE|DN_DELETE|DN_MODIFY|DN_MULTISHOT); + + TAILQ_INSERT_HEAD(&topdirs_list, tdi, list); + return 0; +@@ -175,17 +179,52 @@ out_err: + return -1; + } + ++#ifdef HAVE_PPOLL ++static void gssd_poll(struct pollfd *fds, unsigned long nfds) ++{ ++ sigset_t emptyset; ++ int ret; ++ ++ sigemptyset(&emptyset); ++ ret = ppoll(fds, nfds, NULL, &emptyset); ++ if (ret < 0) { ++ if (errno != EINTR) ++ printerr(0, "WARNING: error return from poll\n"); ++ } else if (ret == 0) { ++ printerr(0, "WARNING: unexpected timeout\n"); ++ } else { ++ scan_poll_results(ret); ++ } ++} ++#else /* !HAVE_PPOLL */ ++static void gssd_poll(struct pollfd *fds, unsigned long nfds) ++{ ++ int ret; ++ ++ /* race condition here: dir_changed could be set before we ++ * enter the poll, and we'd never notice if it weren't for the ++ * timeout. */ ++ ret = poll(fds, nfds, POLL_MILLISECS); ++ if (ret < 0) { ++ if (errno != EINTR) ++ printerr(0, "WARNING: error return from poll\n"); ++ } else if (ret == 0) { ++ /* timeout */ ++ } else { /* ret > 0 */ ++ scan_poll_results(ret); ++ } ++} ++#endif /* !HAVE_PPOLL */ ++ + void + gssd_run() + { +- int ret; +- struct sigaction dn_act; ++ struct sigaction dn_act = { ++ .sa_handler = dir_notify_handler ++ }; + sigset_t set; + +- /* Taken from linux/Documentation/dnotify.txt: */ +- dn_act.sa_sigaction = dir_notify_handler; + sigemptyset(&dn_act.sa_mask); +- dn_act.sa_flags = SA_SIGINFO; + sigaction(DNOTIFY_SIGNAL, &dn_act, NULL); + + /* just in case the signal is blocked... */ +@@ -207,19 +246,7 @@ gssd_run() + exit(1); + } + } +- /* race condition here: dir_changed could be set before we +- * enter the poll, and we'd never notice if it weren't for the +- * timeout. */ +- ret = poll(pollarray, pollsize, POLL_MILLISECS); +- if (ret < 0) { +- if (errno != EINTR) +- printerr(0, +- "WARNING: error return from poll\n"); +- } else if (ret == 0) { +- /* timeout */ +- } else { /* ret > 0 */ +- scan_poll_results(ret); +- } ++ gssd_poll(pollarray, pollsize); + } + topdirs_free_list(); + +diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c +index aa39435..336f3e9 100644 +--- a/utils/gssd/gssd_proc.c ++++ b/utils/gssd/gssd_proc.c +@@ -104,7 +104,7 @@ + + struct pollfd * pollarray; + +-int pollsize; /* the size of pollaray (in pollfd's) */ ++unsigned long pollsize; /* the size of pollaray (in pollfd's) */ + + /* + * convert a presentation address string to a sockaddr_storage struct. Returns +@@ -340,6 +340,25 @@ process_clnt_dir_files(struct clnt_info * clp) + char gname[PATH_MAX]; + char info_file_name[PATH_MAX]; + ++ if (clp->gssd_close_me) { ++ printerr(2, "Closing 'gssd' pipe for %s\n", clp->dirname); ++ close(clp->gssd_fd); ++ memset(&pollarray[clp->gssd_poll_index], 0, ++ sizeof(struct pollfd)); ++ clp->gssd_fd = -1; ++ clp->gssd_poll_index = -1; ++ clp->gssd_close_me = 0; ++ } ++ if (clp->krb5_close_me) { ++ printerr(2, "Closing 'krb5' pipe for %s\n", clp->dirname); ++ close(clp->krb5_fd); ++ memset(&pollarray[clp->krb5_poll_index], 0, ++ sizeof(struct pollfd)); ++ clp->krb5_fd = -1; ++ clp->krb5_poll_index = -1; ++ clp->krb5_close_me = 0; ++ } ++ + if (clp->gssd_fd == -1) { + snprintf(gname, sizeof(gname), "%s/gssd", clp->dirname); + clp->gssd_fd = open(gname, O_RDWR); +@@ -918,23 +937,6 @@ int create_auth_rpc_client(struct clnt_info *clp, + goto out; + } + +-static char * +-user_cachedir(char *dirname, uid_t uid) +-{ +- struct passwd *pw; +- char *ptr; +- +- if ((pw = getpwuid(uid)) == NULL) { +- printerr(0, "user_cachedir: Failed to find '%d' uid" +- " for cache directory\n"); +- return NULL; +- } +- ptr = malloc(strlen(dirname)+strlen(pw->pw_name)+2); +- if (ptr) +- sprintf(ptr, "%s/%s", dirname, pw->pw_name); +- +- return ptr; +-} + /* + * this code uses the userland rpcsec gss library to create a krb5 + * context on behalf of the kernel +@@ -949,7 +951,7 @@ process_krb5_upcall(struct clnt_info *clp, uid_t uid, int fd, char *tgtname, + gss_buffer_desc token; + char **credlist = NULL; + char **ccname; +- char **dirname, *dir, *userdir; ++ char **dirname; + int create_resp = -1; + int err, downcall_err = -EACCES; + +@@ -992,22 +994,7 @@ process_krb5_upcall(struct clnt_info *clp, uid_t uid, int fd, char *tgtname, + service == NULL)) { + /* Tell krb5 gss which credentials cache to use */ + for (dirname = ccachesearch; *dirname != NULL; dirname++) { +- /* See if the user name is needed */ +- if (strncmp(*dirname, GSSD_USER_CRED_DIR, +- strlen(GSSD_USER_CRED_DIR)) == 0) { +- userdir = user_cachedir(*dirname, uid); +- if (userdir == NULL) +- continue; +- dir = userdir; +- } else +- dir = *dirname; +- +- err = gssd_setup_krb5_user_gss_ccache(uid, clp->servername, dir); +- +- if (userdir) { +- free(userdir); +- userdir = NULL; +- } ++ err = gssd_setup_krb5_user_gss_ccache(uid, clp->servername, *dirname); + if (err == -EKEYEXPIRED) + downcall_err = -EKEYEXPIRED; + else if (!err) +diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c +index 887d118..60ba594 100644 +--- a/utils/gssd/krb5_util.c ++++ b/utils/gssd/krb5_util.c +@@ -139,7 +139,7 @@ int limit_to_legacy_enctypes = 0; + + static int select_krb5_ccache(const struct dirent *d); + static int gssd_find_existing_krb5_ccache(uid_t uid, char *dirname, +- struct dirent **d); ++ 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, int nocache); + static int query_krb5_ccache(const char* cred_cache, char **ret_princname, +@@ -178,7 +178,8 @@ select_krb5_ccache(const struct dirent *d) + * code otherwise. + */ + static int +-gssd_find_existing_krb5_ccache(uid_t uid, char *dirname, struct dirent **d) ++gssd_find_existing_krb5_ccache(uid_t uid, char *dirname, ++ const char **cctype, struct dirent **d) + { + struct dirent **namelist; + int n; +@@ -192,6 +193,7 @@ gssd_find_existing_krb5_ccache(uid_t uid, char *dirname, struct dirent **d) + int score, best_match_score = 0, err = -EACCES; + + memset(&best_match_stat, 0, sizeof(best_match_stat)); ++ *cctype = NULL; + *d = NULL; + n = scandir(dirname, &namelist, select_krb5_ccache, 0); + if (n < 0) { +@@ -203,41 +205,51 @@ gssd_find_existing_krb5_ccache(uid_t uid, char *dirname, struct dirent **d) + for (i = 0; i < n; i++) { + snprintf(statname, sizeof(statname), + "%s/%s", dirname, namelist[i]->d_name); +- printerr(3, "CC file '%s' being considered, " ++ printerr(3, "CC '%s' being considered, " + "with preferred realm '%s'\n", + statname, preferred_realm ? + preferred_realm : ""); +- snprintf(buf, sizeof(buf), "FILE:%s/%s", dirname, +- namelist[i]->d_name); + if (lstat(statname, &tmp_stat)) { +- printerr(0, "Error doing stat on file '%s'\n", ++ printerr(0, "Error doing stat on '%s'\n", + statname); + free(namelist[i]); + continue; + } + /* Only pick caches owned by the user (uid) */ + if (tmp_stat.st_uid != uid) { +- printerr(3, "CC file '%s' owned by %u, not %u\n", ++ printerr(3, "CC '%s' owned by %u, not %u\n", + statname, tmp_stat.st_uid, uid); + free(namelist[i]); + continue; + } +- if (!S_ISREG(tmp_stat.st_mode)) { +- printerr(3, "CC file '%s' is not a regular file\n", ++ if (!S_ISREG(tmp_stat.st_mode) && ++ !S_ISDIR(tmp_stat.st_mode)) { ++ printerr(3, "CC '%s' is not a regular " ++ "file or directory\n", + statname); + free(namelist[i]); + continue; + } + if (uid == 0 && !root_uses_machine_creds && + strstr(namelist[i]->d_name, "_machine_")) { +- printerr(3, "CC file '%s' not available to root\n", ++ printerr(3, "CC '%s' not available to root\n", + statname); + free(namelist[i]); + continue; + } ++ if (S_ISDIR(tmp_stat.st_mode)) { ++ *cctype = "DIR"; ++ } else ++ if (S_ISREG(tmp_stat.st_mode)) { ++ *cctype = "FILE"; ++ } else { ++ continue; ++ } ++ snprintf(buf, sizeof(buf), "%s:%s/%s", *cctype, ++ dirname, namelist[i]->d_name); + if (!query_krb5_ccache(buf, &princname, &realm)) { +- printerr(3, "CC file '%s' is expired or corrupt\n", +- statname); ++ printerr(3, "CC '%s' is expired or corrupt\n", ++ buf); + free(namelist[i]); + err = -EKEYEXPIRED; + continue; +@@ -248,9 +260,9 @@ gssd_find_existing_krb5_ccache(uid_t uid, char *dirname, struct dirent **d) + strcmp(realm, preferred_realm) == 0) + score++; + +- printerr(3, "CC file '%s'(%s@%s) passed all checks and" ++ printerr(3, "CC '%s'(%s@%s) passed all checks and" + " has mtime of %u\n", +- statname, princname, realm, ++ buf, princname, realm, + tmp_stat.st_mtime); + /* + * if more than one match is found, return the most +@@ -284,10 +296,11 @@ gssd_find_existing_krb5_ccache(uid_t uid, char *dirname, struct dirent **d) + else { + free(namelist[i]); + } +- printerr(3, "CC file '%s/%s' is our " ++ printerr(3, "CC '%s:%s/%s' is our " + "current best match " + "with mtime of %u\n", +- dirname, best_match_dir->d_name, ++ cctype, dirname, ++ best_match_dir->d_name, + best_match_stat.st_mtime); + } + free(princname); +@@ -1023,20 +1036,43 @@ err_cache: + * Returns 0 if a ccache was found, and a non-zero error code otherwise. + */ + int +-gssd_setup_krb5_user_gss_ccache(uid_t uid, char *servername, char *dirname) ++gssd_setup_krb5_user_gss_ccache(uid_t uid, char *servername, char *dirpattern) + { +- char buf[MAX_NETOBJ_SZ]; ++ char buf[MAX_NETOBJ_SZ], dirname[PATH_MAX]; ++ const char *cctype; + struct dirent *d; +- int err; ++ int err, i, j; + + printerr(2, "getting credentials for client with uid %u for " + "server %s\n", uid, servername); +- memset(buf, 0, sizeof(buf)); +- err = gssd_find_existing_krb5_ccache(uid, dirname, &d); ++ ++ for (i = 0, j = 0; dirpattern[i] != '\0'; i++) { ++ switch (dirpattern[i]) { ++ case '%': ++ switch (dirpattern[i + 1]) { ++ case '%': ++ dirname[j++] = dirpattern[i]; ++ i++; ++ break; ++ case 'U': ++ j += sprintf(dirname + j, "%lu", ++ (unsigned long) uid); ++ i++; ++ break; ++ } ++ break; ++ default: ++ dirname[j++] = dirpattern[i]; ++ break; ++ } ++ } ++ dirname[j] = '\0'; ++ ++ err = gssd_find_existing_krb5_ccache(uid, dirname, &cctype, &d); + if (err) + return err; + +- snprintf(buf, sizeof(buf), "FILE:%s/%s", dirname, d->d_name); ++ snprintf(buf, sizeof(buf), "%s:%s/%s", cctype, dirname, d->d_name); + free(d); + + printerr(2, "using %s as credentials cache for client with " +diff --git a/utils/mount/Makefile.am b/utils/mount/Makefile.am +index 7627854..5810936 100644 +--- a/utils/mount/Makefile.am ++++ b/utils/mount/Makefile.am +@@ -1,7 +1,7 @@ + ## Process this file with automake to produce Makefile.in + + # These binaries go in /sbin (not /usr/sbin), and that cannot be +-# overriden at config time. ++# overridden at config time. + sbindir = /sbin + + man8_MANS = mount.nfs.man umount.nfs.man +diff --git a/utils/mount/mount_libmount.c b/utils/mount/mount_libmount.c +index e8f17a9..701d41e 100644 +--- a/utils/mount/mount_libmount.c ++++ b/utils/mount/mount_libmount.c +@@ -140,14 +140,14 @@ static int try_mount(struct libmnt_context *cxt, int bg) + return ret; + } + +-/* returns: error = -1, success = 0 , unknown = 1 */ ++/* returns: error = -1, success = 1 , not vers4 == 0 */ + static int is_vers4(struct libmnt_context *cxt) + { + struct libmnt_fs *fs = mnt_context_get_fs(cxt); + struct libmnt_table *tb = NULL; + const char *src = mnt_context_get_source(cxt), + *tgt = mnt_context_get_target(cxt); +- int rc = 1; ++ int rc = 0; + + if (!src || !tgt) + return -1; +@@ -163,7 +163,7 @@ static int is_vers4(struct libmnt_context *cxt) + if (fs) { + const char *type = mnt_fs_get_fstype(fs); + if (type && strcmp(type, "nfs4") == 0) +- rc = 0; ++ rc = 1; + } + mnt_free_table(tb); + return rc; +@@ -173,6 +173,7 @@ static int umount_main(struct libmnt_context *cxt, int argc, char **argv) + { + int rc, c; + char *spec = NULL, *opts = NULL; ++ int ret = EX_FAIL; + + static const struct option longopts[] = { + { "force", 0, 0, 'f' }, +@@ -209,8 +210,6 @@ static int umount_main(struct libmnt_context *cxt, int argc, char **argv) + + if (mnt_context_set_target(cxt, spec)) + goto err; +- if (mnt_context_set_fstype_pattern(cxt, "nfs,nfs4")) /* restrict filesystems */ +- goto err; + + /* read mtab/fstab, evaluate permissions, etc. */ + rc = mnt_context_prepare_umount(cxt); +@@ -220,6 +219,14 @@ static int umount_main(struct libmnt_context *cxt, int argc, char **argv) + goto err; + } + ++ if (mnt_context_get_fstype(cxt) && ++ !mnt_match_fstype(mnt_context_get_fstype(cxt), "nfs,nfs4")) { ++ ++ nfs_error(_("%s: %s: is not an NFS filesystem"), progname, spec); ++ ret = EX_USAGE; ++ goto err; ++ } ++ + opts = retrieve_mount_options(mnt_context_get_fs(cxt)); + + if (!mnt_context_is_lazy(cxt)) { +@@ -244,6 +251,7 @@ static int umount_main(struct libmnt_context *cxt, int argc, char **argv) + nfs_umount23(spec, "tcp,v3"); + } + ++ ret = EX_FILEIO; + rc = mnt_context_do_umount(cxt); /* call umount(2) syscall */ + mnt_context_finalize_mount(cxt); /* mtab update */ + +@@ -252,12 +260,10 @@ static int umount_main(struct libmnt_context *cxt, int argc, char **argv) + umount_error(rc, spec); + goto err; + } +- +- free(opts); +- return EX_SUCCESS; ++ ret = EX_SUCCESS; + err: + free(opts); +- return EX_FAIL; ++ return ret; + } + + static int mount_main(struct libmnt_context *cxt, int argc, char **argv) +diff --git a/utils/mount/nfs.man b/utils/mount/nfs.man +index 87e27e1..da6d6d3 100644 +--- a/utils/mount/nfs.man ++++ b/utils/mount/nfs.man +@@ -460,6 +460,13 @@ by other clients, but can impact application and server performance. + .IP + The DATA AND METADATA COHERENCE section contains a + detailed discussion of these trade-offs. ++.TP 1.5i ++.BR fsc " / " nofsc ++Enable/Disables the cache of (read-only) data pages to the local disk ++using the FS-Cache facility. See cachefilesd(8) ++and /Documentation/filesystems/caching ++for detail on how to configure the FS-Cache facility. ++Default value is nofsc. + .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/stropts.c b/utils/mount/stropts.c +index e09aa7c..0aa9a75 100644 +--- a/utils/mount/stropts.c ++++ b/utils/mount/stropts.c +@@ -665,6 +665,7 @@ static int nfs_try_mount_v3v2(struct nfsmount_info *mi) + case ECONNREFUSED: + case EOPNOTSUPP: + case EHOSTUNREACH: ++ case ETIMEDOUT: + continue; + default: + goto out; +@@ -752,6 +753,7 @@ static int nfs_try_mount_v4(struct nfsmount_info *mi) + switch (errno) { + case ECONNREFUSED: + case EHOSTUNREACH: ++ case ETIMEDOUT: + continue; + default: + goto out; +diff --git a/utils/mountd/v4root.c b/utils/mountd/v4root.c +index 708eb61..726b50d 100644 +--- a/utils/mountd/v4root.c ++++ b/utils/mountd/v4root.c +@@ -62,6 +62,8 @@ void set_pseudofs_security(struct exportent *pseudo, struct exportent *source) + + if (source->e_flags & NFSEXP_INSECURE_PORT) + pseudo->e_flags |= NFSEXP_INSECURE_PORT; ++ if ((source->e_flags & NFSEXP_ROOTSQUASH) == 0) ++ pseudo->e_flags &= ~NFSEXP_ROOTSQUASH; + for (se = source->e_secinfo; se->flav; se++) { + struct sec_entry *new; + +@@ -92,7 +94,8 @@ v4root_create(char *path, nfs_export *export) + exp = export_create(&eep, 0); + if (exp == NULL) + return NULL; +- xlog(D_CALL, "v4root_create: path '%s'", exp->m_export.e_path); ++ xlog(D_CALL, "v4root_create: path '%s' flags 0x%x", ++ exp->m_export.e_path, exp->m_export.e_flags); + return &exp->m_export; + } + +diff --git a/utils/nfsdcld/nfsdcld.c b/utils/nfsdcld/nfsdcld.c +index e7af4e3..473d069 100644 +--- a/utils/nfsdcld/nfsdcld.c ++++ b/utils/nfsdcld/nfsdcld.c +@@ -102,8 +102,8 @@ cld_set_caps(void) + } + + /* prune the bounding set to nothing */ +- for (i = 0; i <= CAP_LAST_CAP; ++i) { +- ret = prctl(PR_CAPBSET_DROP, i); ++ for (i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) >= 0 ; ++i) { ++ ret = prctl(PR_CAPBSET_DROP, i, 0, 0, 0); + if (ret) { + xlog(L_ERROR, "Unable to prune capability %lu from " + "bounding set: %m", i); +diff --git a/utils/nfsidmap/nfsidmap.c b/utils/nfsidmap/nfsidmap.c +index cf11551..e14543c 100644 +--- a/utils/nfsidmap/nfsidmap.c ++++ b/utils/nfsidmap/nfsidmap.c +@@ -12,6 +12,7 @@ + + #include + #include "xlog.h" ++#include "conffile.h" + + int verbose = 0; + char *usage="Usage: %s [-v] [-c || [-u|-g|-r key] || [-t timeout] key desc]"; +@@ -26,6 +27,10 @@ char *usage="Usage: %s [-v] [-c || [-u|-g|-r key] || [-t timeout] key desc]"; + #define DEFAULT_KEYRING "id_resolver" + #endif + ++#ifndef PATH_IDMAPDCONF ++#define PATH_IDMAPDCONF "/etc/idmapd.conf" ++#endif ++ + static int keyring_clear(char *keyring); + + #define UIDKEYS 0x1 +@@ -267,6 +272,13 @@ int main(int argc, char **argv) + } + } + ++ if (nfs4_init_name_mapping(PATH_IDMAPDCONF)) { ++ xlog_err("Unable to create name to user id mappings."); ++ return 1; ++ } ++ if (!verbose) ++ verbose = conf_get_num("General", "Verbosity", 0); ++ + if (keystr) { + rc = key_revoke(keystr, keymask); + return rc; +diff --git a/utils/osd_login/Makefile.am b/utils/osd_login/Makefile.am +index adc493a..20c2d8c 100644 +--- a/utils/osd_login/Makefile.am ++++ b/utils/osd_login/Makefile.am +@@ -1,12 +1,9 @@ + ## Process this file with automake to produce Makefile.in + +-OSD_LOGIN_FILES= osd_login ++# These binaries go in /sbin (not /usr/sbin), and that cannot be ++# overridden at config time. ++sbindir = /sbin + +-EXTRA_DIST= $(OSD_LOGIN_FILES) +- +-all-local: $(OSD_LOGIN_FILES) +- +-install-data-hook: +- $(INSTALL) --mode 755 osd_login $(DESTDIR)/sbin/osd_login ++sbin_SCRIPTS = osd_login + + MAINTAINERCLEANFILES = Makefile.in diff --git a/nfs-utils.spec b/nfs-utils.spec index 1eb7eb3..c5daf5b 100644 --- a/nfs-utils.spec +++ b/nfs-utils.spec @@ -36,7 +36,7 @@ Source51: nfs-server.preconfig Source52: nfs-server.postconfig %define nfs_configs %{SOURCE50} %{SOURCE51} %{SOURCE52} -Patch001: nfs-utils-1.2.7-rc4.patch +Patch001: nfs-utils-1.2.7-rc5.patch Patch100: nfs-utils-1.2.1-statdpath-man.patch Patch101: nfs-utils-1.2.1-exp-subtree-warn-off.patch @@ -304,6 +304,7 @@ fi * Thu Aug 23 2012 Steve Dickson 1.2.6-12 - Added FedFS support by added a BuildRequires for fedfs-utils-devel - Introduce new systemd-rpm macros (bz 850227) +- Updated to latest upstream RC release: nfs-utils.1.2.7-rc5 (bz 833024) * Mon Aug 6 2012 Steve Dickson 1.2.6-11 - Updated to latest upstream RC release: nfs-utils.1.2.7-rc4