diff --git a/am-utils-6.2-32-bit-fixes.patch b/am-utils-6.2-32-bit-fixes.patch new file mode 100644 index 0000000..ac6cf1a --- /dev/null +++ b/am-utils-6.2-32-bit-fixes.patch @@ -0,0 +1,145 @@ +commit a6bbb7d9b098dacd2636925c232c630452e4b46e +Author: Christos Zoulas +Date: Sun Jan 18 18:03:37 2015 -0500 + + 32 bit fixes + +diff --git a/amd/amq_subr.c b/amd/amq_subr.c +index 8783611..86f0351 100644 +--- a/amd/amq_subr.c ++++ b/amd/amq_subr.c +@@ -528,6 +528,7 @@ xdr_amq_map_info_qelem(XDR *xdrs, qelem *qhead) + u_int len = 0; + int x; + char *n; ++ long modify; + + /* + * Compute length of list +@@ -552,7 +553,8 @@ xdr_amq_map_info_qelem(XDR *xdrs, qelem *qhead) + return (FALSE); + } + +- if (!xdr_long(xdrs, &m->modify)) { ++ modify = (long)m->modify; ++ if (!xdr_long(xdrs, &modify)) { + return (FALSE); + } + +diff --git a/amd/nfs_subr.c b/amd/nfs_subr.c +index e463ff7..7192a6a 100644 +--- a/amd/nfs_subr.c ++++ b/amd/nfs_subr.c +@@ -1104,9 +1104,9 @@ am_nfs3_getattr_3_svc(am_GETATTR3args *argp, struct svc_req *rqstp) + result.status = AM_NFS3_OK; + + if (amuDebug(D_TRACE)) +- plog(XLOG_DEBUG, "\tstat(%s), size = %lu, mtime=%d.%d", ++ plog(XLOG_DEBUG, "\tstat(%s), size = %llu, mtime=%d.%d", + mp->am_path, +- (am_size3) fattr3->size, ++ (unsigned long long)fattr3->size, + (u_int) fattr3->mtime.seconds, + (u_int) fattr3->mtime.nseconds); + +diff --git a/amd/readdir.c b/amd/readdir.c +index 4b5e61b..57773a5 100644 +--- a/amd/readdir.c ++++ b/amd/readdir.c +@@ -635,7 +635,7 @@ static size_t needroom3(void) + + /* This one is called only if map is browsable */ + static int +-amfs_readdir3_browsable(am_node *mp, am_cookie3 cookie, ++amfs_readdir3_browsable(am_node *mp, voidp cookie, + am_dirlist3 *dp, am_entry3 *ep, u_int count, + int fully_browsable) + { +@@ -647,7 +647,8 @@ amfs_readdir3_browsable(am_node *mp, am_cookie3 cookie, + dp->eof = FALSE; /* assume readdir not done */ + + if (amuDebug(D_READDIR)) +- plog(XLOG_DEBUG, "amfs_readdir3_browsable gen=%lu, count=%d", gen, count); ++ plog(XLOG_DEBUG, "%s: gen=%llu, count=%d", __func__, ++ (unsigned long long)gen, count); + + if (gen == 0) { + size_t needed = needroom3(); +@@ -732,8 +733,9 @@ amfs_readdir3_browsable(am_node *mp, am_cookie3 cookie, + for (j = 0, ne = te; ne; ne = ne->ne_nextentry) + plog(XLOG_DEBUG, "gen2 key %4d \"%s\"", j++, ne->name); + for (j = 0, ne = ep; ne; ne = ne->ne_nextentry) { +- plog(XLOG_DEBUG, "gen2+ key %4d \"%s\" fi=%lu ck=%lu", +- j++, ne->name, ne->fileid, ne->cookie); ++ plog(XLOG_DEBUG, "gen2+ key %4d \"%s\" fi=%llu ck=%llu", ++ j++, ne->name, (unsigned long long)ne->fileid, ++ (unsigned long long)ne->cookie); + } + plog(XLOG_DEBUG, "EOF is %d", dp->eof); + } +@@ -793,14 +795,15 @@ amfs_readdir3_browsable(am_node *mp, am_cookie3 cookie, + } + + static int +-amfs_readdir3(am_node *mp, am_cookie3 cookie, ++amfs_readdir3(am_node *mp, voidp cookie, + am_dirlist3 *dp, am_entry3 *ep, u_int count) + { + uint64 gen = *(uint64 *) cookie; + am_node *xp; + + if (amuDebug(D_READDIR)) +- plog(XLOG_DEBUG, "amfs_readdir3 gen=%lu, count=%d", gen, count); ++ plog(XLOG_DEBUG, "%s: gen=%llu, count=%d", __func__, ++ (unsigned long long)gen, count); + + dp->eof = FALSE; /* assume readdir not done */ + +@@ -847,8 +850,9 @@ amfs_readdir3(am_node *mp, am_cookie3 cookie, + am_entry3 *ne; + int j; + for (j = 0, ne = ep; ne; ne = ne->nextentry) { +- plog(XLOG_DEBUG, "gen1 key %4d \"%s\" fi=%lu ck=%lu", +- j++, ne->name, ne->fileid, ne->cookie); ++ plog(XLOG_DEBUG, "gen1 key %4d \"%s\" fi=%llu ck=%llu", ++ j++, ne->name, (unsigned long long)ne->fileid, ++ (unsigned long long)ne->cookie); + } + } + return 0; +@@ -907,8 +911,9 @@ amfs_readdir3(am_node *mp, am_cookie3 cookie, + am_entry3 *ne; + int j; + for (j = 0, ne = ep; ne; ne = ne->nextentry) { +- plog(XLOG_DEBUG, "gen2 key %4d \"%s\" fi=%lu ck=%lu", +- j++, ne->name, ne->fileid, ne->cookie); ++ plog(XLOG_DEBUG, "gen2 key %4d \"%s\" fi=%llu ck=%llu", ++ j++, ne->name, (unsigned long long)ne->fileid, ++ (unsigned long long)ne->cookie); + } + } + return 0; +@@ -944,8 +949,8 @@ amfs_generic_readdir(am_node *mp, voidp cookie, voidp dp, voidp ep, u_int count) + return amfs_readdir(mp, cookie, dp, ep, count); + } else { + if (browsable) +- return amfs_readdir3_browsable(mp, (am_cookie3) cookie, dp, ep, count, full); ++ return amfs_readdir3_browsable(mp, cookie, dp, ep, count, full); + else +- return amfs_readdir3(mp, (am_cookie3) cookie, dp, ep, count); ++ return amfs_readdir3(mp, cookie, dp, ep, count); + } + } +diff --git a/amq/amq.c b/amq/amq.c +index 5d4ed7a..dc5fe02 100644 +--- a/amq/amq.c ++++ b/amq/amq.c +@@ -79,7 +79,7 @@ enum show_opt { + static void + time_print(time_type tt) + { +- time_t t = (time_t)tt; ++ time_t t = (time_t)*tt; + struct tm *tp = localtime(&t); + printf("%02d/%02d/%04d %02d:%02d:%02d", + tp->tm_mon + 1, tp->tm_mday, diff --git a/am-utils-6.2-Add-the-sys-alias-for-unix-as-well-as-none-and-null.patch b/am-utils-6.2-Add-the-sys-alias-for-unix-as-well-as-none-and-null.patch new file mode 100644 index 0000000..0762139 --- /dev/null +++ b/am-utils-6.2-Add-the-sys-alias-for-unix-as-well-as-none-and-null.patch @@ -0,0 +1,64 @@ +commit cb493f02ca3b8fbf0dba18d5a733345f54513300 +Author: zoulasc +Date: Mon Mar 7 18:03:19 2016 -0500 + + 1. Add the "sys" alias for "unix", as well as "none", and "null" + 2. Properly handle multiple flavors, although the linux kernel does not (yet?) + 3. Don't add the "sec=" field, because it is already there. + +diff --git a/libamu/mount_fs.c b/libamu/mount_fs.c +index 87f64c3..366eb8b 100644 +--- a/libamu/mount_fs.c ++++ b/libamu/mount_fs.c +@@ -1076,7 +1076,10 @@ struct { + const char *name; + int num; + } flavours[] = { ++ { "none", AUTH_NONE }, ++ { "null", AUTH_NULL }, + { "unix", AUTH_UNIX }, ++ { "sys", AUTH_SYS }, + { "krb5", RPC_AUTH_GSS_KRB5 }, + { "krb5i", RPC_AUTH_GSS_KRB5I }, + { "krb5p", RPC_AUTH_GSS_KRB5P }, +@@ -1104,12 +1107,13 @@ set_nfs4_security(nfs4_args_t *nap, mntent_t *mntp) + nap->auth_flavours = xmalloc(l * sizeof(*nap->auth_flavours)); + + s = ss = xstrdup(o); ++ l = 0; + for (;;) { + q = strchr(s, ','); + if (q) + *q = '\0'; + +- for (l = 0, i = 0; i < sizeof(flavours) / sizeof(flavours[0]); i++) ++ for (i = 0; i < sizeof(flavours) / sizeof(flavours[0]); i++) + if (strcmp(flavours[i].name, s) == 0) { + nap->auth_flavours[l++] = flavours[i].num; + break; +@@ -1125,6 +1129,9 @@ set_nfs4_security(nfs4_args_t *nap, mntent_t *mntp) + s = ++q; + } + ++ if (l == 0) { ++ nap->auth_flavours[l++] = AUTH_UNIX; ++ } + nap->auth_flavourlen = l; + return ss; + } +@@ -1172,12 +1179,15 @@ add_nfs4_mntopts(const nfs4_args_t *nap, mntent_t *mntp, char *sec) + opts = xrealloc(mntp->mnt_opts, len); + xstrlcat(opts, buf, len); + ++#ifdef notdef ++ /* Already in the options */ + if (sec) { + xstrlcat(opts, ",", len); + xstrlcat(opts, MNTTAB_OPT_SEC, len); + xstrlcat(opts, "=", len); + xstrlcat(opts, sec, len); + } ++#endif + + mntp->mnt_opts = opts; + } diff --git a/am-utils-6.2-Default-to-string-mount-options-for-NFSv4.patch b/am-utils-6.2-Default-to-string-mount-options-for-NFSv4.patch new file mode 100644 index 0000000..3057d22 --- /dev/null +++ b/am-utils-6.2-Default-to-string-mount-options-for-NFSv4.patch @@ -0,0 +1,58 @@ +commit 3369871a5e68484e231705bb0a893b4c6da85d17 +Author: zoulasc +Date: Mon Mar 7 18:05:07 2016 -0500 + + Default to "string" mount options for NFSv4 because the kernel does not + properly handle the auth_flavours[] field. Tested with nfs-utils-1.3.3 and + it always defaults to krb5i if string options are not used. Please note + that the "rw" option is not recognized by the linux kernel. + +diff --git a/conf/mount/mount_linux.c b/conf/mount/mount_linux.c +index d3841ce..de7708d 100644 +--- a/conf/mount/mount_linux.c ++++ b/conf/mount/mount_linux.c +@@ -450,7 +450,7 @@ do_mount_linux(MTYPE_TYPE type, mntent_t *mnt, int flags, caddr_t data) + return mount(mnt->mnt_fsname, + mnt->mnt_dir, + type, +- MS_MGC_VAL | flags, ++ flags, + data); + } + +@@ -566,9 +566,9 @@ mount_linux_nfs(MTYPE_TYPE type, mntent_t *mnt, int flags, caddr_t data) + plog(XLOG_DEBUG, "%s: port %d\n", __func__, + htons(mnt_data->addr.sin_port)); + } ++ flags |= MS_MGC_VAL; + if (amuDebug(D_TRACE)) { +- plog(XLOG_DEBUG, "%s: Generic mount flags 0x%x", __func__, +- MS_MGC_VAL | flags); ++ plog(XLOG_DEBUG, "%s: Generic mount flags 0x%x", __func__, flags); + plog(XLOG_DEBUG, "%s: updated nfs_args...", __func__); + print_nfs_args(mnt_data, 0); + } +@@ -610,14 +610,21 @@ mount_linux_nfs4(MTYPE_TYPE type, mntent_t *mnt, int flags, caddr_t data) + plog(XLOG_DEBUG, "%s: type %s\n", __func__, type); + plog(XLOG_DEBUG, "%s: version %d\n", __func__, mnt_data->version); + } ++#if 0 ++ flags |= MS_MGC_VAL; ++#endif + if (amuDebug(D_TRACE)) { +- plog(XLOG_DEBUG, "%s: Generic mount flags 0x%x", __func__, +- MS_MGC_VAL | flags); ++ plog(XLOG_DEBUG, "%s: Generic mount flags 0x%x", __func__, flags); + plog(XLOG_DEBUG, "%s: updated nfs_args...", __func__); + print_nfs_args(mnt_data, NFS_VERSION4); + } + ++#if 0 + errorcode = do_mount_linux(type, mnt, flags, data); ++#else ++ errorcode = do_mount_linux(type, mnt, flags, mnt->mnt_opts); ++#endif ++ + + return errorcode; + } diff --git a/am-utils-6.2-Fix-SEGV-on-amq-entries-that-print-times.patch b/am-utils-6.2-Fix-SEGV-on-amq-entries-that-print-times.patch new file mode 100644 index 0000000..ed7b9f3 --- /dev/null +++ b/am-utils-6.2-Fix-SEGV-on-amq-entries-that-print-times.patch @@ -0,0 +1,19 @@ +commit 6a12fc0acb3afb654ba5e6efdeb28b943e2efd3e +Author: zoulasc +Date: Thu Mar 31 14:56:53 2016 -0400 + + Fix SEGV on amq entries that print times. + +diff --git a/amq/amq.c b/amq/amq.c +index dc5fe02..04f9e4d 100644 +--- a/amq/amq.c ++++ b/amq/amq.c +@@ -79,7 +79,7 @@ enum show_opt { + static void + time_print(time_type tt) + { +- time_t t = (time_t)*tt; ++ time_t t = (time_t)(intptr_t)tt; + struct tm *tp = localtime(&t); + printf("%02d/%02d/%04d %02d:%02d:%02d", + tp->tm_mon + 1, tp->tm_mday, diff --git a/am-utils-6.2-Fix-nfs-args-setting-code.patch b/am-utils-6.2-Fix-nfs-args-setting-code.patch new file mode 100644 index 0000000..96d0425 --- /dev/null +++ b/am-utils-6.2-Fix-nfs-args-setting-code.patch @@ -0,0 +1,71 @@ +commit 1c4c00a489d7aef115020b903dcd10201eb56ac0 +Author: zoulasc +Date: Thu Apr 30 14:24:39 2015 -0400 + + Fix nfs args setting code (raven at the maw dot net) + +diff --git a/ChangeLog b/ChangeLog +index fd05087..64be682 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,8 @@ ++2015-04-30 Christos Zoulas ++ ++ * fix compilation error in nfs args set code. ++ (raven at themaw.net) ++ + 2015-01-17 Christos Zoulas + + * Move libtool macro functions from m4/macros to m4 and delete +diff --git a/libamu/mount_fs.c b/libamu/mount_fs.c +index b577bab..87f64c3 100644 +--- a/libamu/mount_fs.c ++++ b/libamu/mount_fs.c +@@ -1001,12 +1001,12 @@ compute_nfs23_args(nfs_args_t *nap, + + #ifdef MNTTAB_OPT_SYMTTL /* symlink cache time-to-live */ + if ((nap->symttl = hasmntval(mntp, MNTTAB_OPT_SYMTTL))) +- nap->args.flags |= MNT2_NFS_OPT_SYMTTL; ++ nap->flags |= MNT2_NFS_OPT_SYMTTL; + #endif /* MNTTAB_OPT_SYMTTL */ + + #ifdef MNT2_NFS_OPT_PGTHRESH /* paging threshold */ + if ((nap->pg_thresh = hasmntval(mntp, MNTTAB_OPT_PGTHRESH))) +- nap->args.flags |= MNT2_NFS_OPT_PGTHRESH; ++ nap->flags |= MNT2_NFS_OPT_PGTHRESH; + #endif /* MNT2_NFS_OPT_PGTHRESH */ + + #if defined(MNT2_NFS_OPT_POSIX) && defined(MNTTAB_OPT_POSIX) +@@ -1029,12 +1029,12 @@ compute_nfs23_args(nfs_args_t *nap, + return; + } + /* update the flags field for knconf */ +- nap->args.flags |= MNT2_NFS_OPT_KNCONF; ++ nap->flags |= MNT2_NFS_OPT_KNCONF; + #endif /* HAVE_TRANSPORT_TYPE_TLI */ + + #ifdef MNT2_NFS_OPT_FSNAME + nap->fsname = fs_name; +- nap->args.flags |= MNT2_NFS_OPT_FSNAME; ++ nap->flags |= MNT2_NFS_OPT_FSNAME; + #endif /* MNT2_NFS_OPT_FSNAME */ + + +@@ -1323,7 +1323,7 @@ compute_nfs4_args(nfs4_args_t *nap, + + #if defined(MNT2_NFS_OPT_POSIX) && defined(MNTTAB_OPT_POSIX) + if (amu_hasmntopt(mntp, MNTTAB_OPT_POSIX) != NULL) { +- nap->args.flags |= MNT2_NFS_OPT_POSIX; ++ nap->flags |= MNT2_NFS_OPT_POSIX; + # ifdef HAVE_NFS_ARGS_T_PATHCONF + nap->pathconf = NULL; + # endif /* HAVE_NFS_ARGS_T_PATHCONF */ +@@ -1333,7 +1333,7 @@ compute_nfs4_args(nfs4_args_t *nap, + #if defined(MNT2_NFS_OPT_MAXGRPS) && defined(MNTTAB_OPT_MAXGROUPS) + nap->maxgrouplist = hasmntval(mntp, MNTTAB_OPT_MAXGROUPS); + if (nap->maxgrouplist != 0) +- nap->args.flags |= MNT2_NFS_OPT_MAXGRPS; ++ nap->flags |= MNT2_NFS_OPT_MAXGRPS; + #endif /* defined(MNT2_NFS_OPT_MAXGRPS) && defined(MNTTAB_OPT_MAXGROUPS) */ + + #ifdef HAVE_NFS_ARGS_T_OPTSTR diff --git a/am-utils-6.2-Improve-debugging-for-unmounting.patch b/am-utils-6.2-Improve-debugging-for-unmounting.patch new file mode 100644 index 0000000..564daa5 --- /dev/null +++ b/am-utils-6.2-Improve-debugging-for-unmounting.patch @@ -0,0 +1,36 @@ +commit 227ce116a307a7f38967639c94ad74970ee83700 +Author: zoulasc +Date: Tue Mar 8 23:30:38 2016 -0500 + + Improve debugging for unmounting. + +diff --git a/amd/map.c b/amd/map.c +index bcb2156..a6df44b 100644 +--- a/amd/map.c ++++ b/amd/map.c +@@ -904,10 +904,8 @@ unmount_mp(am_node *mp) + int was_backgrounded = 0; + mntfs *mf = mp->am_al->al_mnt; + +-#ifdef notdef + plog(XLOG_INFO, "\"%s\" on %s timed out (flags 0x%x)", +- mp->am_path, mf->mf_mount, (int) mf->mf_flags); +-#endif /* notdef */ ++ mp->am_path, mf->mf_mount, (int) mf->mf_flags); + + #ifndef MNT2_NFS_OPT_SYMTTL + /* +@@ -938,11 +936,12 @@ unmount_mp(am_node *mp) + plog(XLOG_STATS, "file server %s is down - timeout of \"%s\" ignored", mf->mf_server->fs_host, mp->am_path); + mf->mf_flags |= MFF_LOGDOWN; + } ++ dlog("\"%s\" on %s server is down, deferred", mp->am_path, mf->mf_mount); + notify_child(mp, AMQ_UMNT_SERVER, 0, 0); + return 0; + } + +- dlog("\"%s\" on %s timed out", mp->am_path, mf->mf_mount); ++ dlog("\"%s\" on %s timed out, unmounting", mp->am_path, mf->mf_mount); + mf->mf_flags |= MFF_UNMOUNTING; + + #ifdef HAVE_FS_AUTOFS diff --git a/am-utils-6.2-Make-hasmntval-return-an-0-on-error-1-on-success.patch b/am-utils-6.2-Make-hasmntval-return-an-0-on-error-1-on-success.patch new file mode 100644 index 0000000..7c39f97 --- /dev/null +++ b/am-utils-6.2-Make-hasmntval-return-an-0-on-error-1-on-success.patch @@ -0,0 +1,530 @@ +commit 1c9cd2d03ab1561b7eee831af381eff781fcf41e +Author: zoulasc +Date: Fri Apr 8 15:29:33 2016 -0400 + + * Make hasmntval() return an 0 on error, 1 on success and + place the value in an argument. Update all users and + check properly for errors. Get rid of hasmntvalerr(). + * Add hasmntvaldelim() which takes a string delimiter. This + is now used to chop vers=4.1 to 4, so that we can parse the + version correctly (we don't care about the .1 part yet) + +--- + amd/autil.c | 10 ++---- + amd/ops_cdfs.c | 7 ++++ + amd/ops_nfs.c | 3 -- + amd/ops_pcfs.c | 10 ++++-- + amd/ops_ufs.c | 6 +++- + amd/srvr_nfs.c | 24 ++++++++++------ + hlfsd/hlfsd.c | 3 -- + include/am_utils.h | 4 +- + libamu/mount_fs.c | 79 ++++++++++++++++++++++++++++++++++++++--------------- + libamu/mtab.c | 41 ++++++++------------------- + 10 files changed, 109 insertions(+), 78 deletions(-) + +--- am-utils-6.2.orig/amd/autil.c ++++ am-utils-6.2/amd/autil.c +@@ -279,7 +279,7 @@ am_mounted(am_node *mp) + if (amu_hasmntopt(&mnt, "nounmount") || amu_hasmntopt(&mnt, "noumount")) + notimeout = 1; + /* utimeout=N option: user wants to unmount this option AND set timeout */ +- if ((mp->am_timeo = hasmntval(&mnt, "utimeout")) == 0) ++ if (!hasmntval(&mnt, "utimeout", &mp->am_timeo)) + mp->am_timeo = gopt.am_timeo; /* otherwise use default timeout */ + else + notimeout = 0; +@@ -480,8 +480,7 @@ amfs_mount(am_node *mp, mntfs *mf, char + mnt.mnt_type = HIDE_MOUNT_TYPE; + } + +- retry = hasmntval(&mnt, MNTTAB_OPT_RETRY); +- if (retry <= 0) ++ if (!hasmntval(&mnt, MNTTAB_OPT_RETRY, &retry) || retry <= 0) + retry = 2; /* XXX: default to 2 retries */ + + /* +@@ -526,7 +525,7 @@ again: + nfs_args_t nfs_args; + am_nfs_handle_t *fhp, anh; + #ifndef HAVE_TRANSPORT_TYPE_TLI +- u_short port; ++ int port; + struct sockaddr_in sin; + #endif /* not HAVE_TRANSPORT_TYPE_TLI */ + +@@ -547,8 +546,7 @@ again: + /* as per POSIX, sin_len need not be set (used internally by kernel) */ + sin.sin_family = AF_INET; + sin.sin_addr = myipaddr; +- port = hasmntval(&mnt, MNTTAB_OPT_PORT); +- if (port) { ++ if (hasmntval(&mnt, MNTTAB_OPT_PORT, &port) && port > 0 && port < 65536) { + sin.sin_port = htons(port); + } else { + plog(XLOG_ERROR, "no port number specified for %s", dir); +--- am-utils-6.2.orig/amd/ops_cdfs.c ++++ am-utils-6.2/amd/ops_cdfs.c +@@ -190,7 +190,12 @@ mount_cdfs(char *mntdir, char *fs_name, + #endif /* HAVE_CDFS_ARGS_T_ISO_FLAGS */ + + #ifdef HAVE_CDFS_ARGS_T_ISO_PGTHRESH +- cdfs_args.iso_pgthresh = hasmntval(&mnt, MNTTAB_OPT_PGTHRESH); ++ { ++ int thresh; ++ if (!hasmntval(&mnt, MNTTAB_OPT_PGTHRESH, &thresh) || thresh < 0) ++ thresh = 0; ++ cdfs_args.iso_pgthresh = thresh; ++ } + #endif /* HAVE_CDFS_ARGS_T_ISO_PGTHRESH */ + + #ifdef HAVE_CDFS_ARGS_T_NORRIP +--- am-utils-6.2.orig/amd/ops_nfs.c ++++ am-utils-6.2/amd/ops_nfs.c +@@ -888,8 +888,7 @@ mount_nfs_fh(am_nfs_handle_t *fhp, char + plog(XLOG_INFO, "mount_nfs_fh: NFS version %d", (int) nfs_version); + plog(XLOG_INFO, "mount_nfs_fh: using NFS transport %s", nfs_proto); + +- retry = hasmntval(&mnt, MNTTAB_OPT_RETRY); +- if (retry <= 0) ++ if (!hasmntval(&mnt, MNTTAB_OPT_RETRY, &retry) || retry <= 0) + retry = 1; /* XXX */ + + genflags = compute_mount_flags(&mnt); +--- am-utils-6.2.orig/amd/ops_pcfs.c ++++ am-utils-6.2/amd/ops_pcfs.c +@@ -139,17 +139,19 @@ mount_pcfs(char *mntdir, char *fs_name, + #endif /* HAVE_PCFS_ARGS_T_FSPEC */ + + #ifdef HAVE_PCFS_ARGS_T_MASK +- pcfs_args.mask = 0777; /* this may be the msdos file modes */ +- if ((mask = hasmntval(&mnt, MNTTAB_OPT_MASK)) > 0) ++ if (hasmntval(&mnt, MNTTAB_OPT_MASK, &mask) && mask > 0) + pcfs_args.mask = mask; ++ else ++ pcfs_args.mask = 0777; /* this may be the msdos file modes */ + if (amuDebug(D_TRACE)) + plog(XLOG_DEBUG, "mount_pcfs: mask=%o (octal)", (u_int) pcfs_args.mask); + #endif /* HAVE_PCFS_ARGS_T_MASK */ + + #ifdef HAVE_PCFS_ARGS_T_DIRMASK +- pcfs_args.dirmask = 0777; /* this may be the msdos dir modes */ +- if ((mask = hasmntval(&mnt, MNTTAB_OPT_DIRMASK)) > 0) ++ if (hasmntval(&mnt, MNTTAB_OPT_DIRMASK, &mask) && mask > 0) + pcfs_args.dirmask = mask; ++ else ++ pcfs_args.dirmask = 0777; /* this may be the msdos dir modes */ + if (amuDebug(D_TRACE)) + plog(XLOG_DEBUG, "mount_pcfs: dirmask=%o (octal)", (u_int) pcfs_args.dirmask); + #endif /* HAVE_PCFS_ARGS_T_DIRMASK */ +--- am-utils-6.2.orig/amd/ops_ufs.c ++++ am-utils-6.2/amd/ops_ufs.c +@@ -144,7 +144,11 @@ mount_ufs(char *mntdir, char *fs_name, c + #endif /* HAVE_UFS_ARGS_T_FSPEC */ + + #ifdef HAVE_UFS_ARGS_T_UFS_PGTHRESH +- ufs_args.ufs_pgthresh = hasmntval(&mnt, MNTTAB_OPT_PGTHRESH); ++ { ++ int thresh; ++ if (!hasmntval(&mnt, MNTTAB_OPT_PGTHRESH, &thresh) || thresh < 0) ++ thresh = 0; ++ ufs_args.ufs_pgthresh = thresh; + #endif /* HAVE_UFS_ARGS_T_UFS_PGTHRESH */ + + /* +--- am-utils-6.2.orig/amd/srvr_nfs.c ++++ am-utils-6.2/amd/srvr_nfs.c +@@ -704,10 +704,10 @@ find_nfs_srvr(mntfs *mf) + struct hostent *hp = NULL; + struct sockaddr_in *ip = NULL; + u_long nfs_version = 0; /* default is no version specified */ ++ int val; + u_long best_nfs_version = 0; + char *nfs_proto = NULL; /* no IP protocol either */ +- int nfs_port = 0; +- int nfs_port_opt = 0; ++ int nfs_port; + int fserver_is_down = 0; + + if (mf->mf_fo == NULL) { +@@ -721,7 +721,8 @@ find_nfs_srvr(mntfs *mf) + * are required or not. < 0 = no pings. + */ + mnt.mnt_opts = mf->mf_mopts; +- pingval = hasmntval(&mnt, "ping"); ++ if (!hasmntval(&mnt, "ping", &pingval) || pingval < 0) ++ pingval = 0; + + if (mf->mf_flags & MFF_NFS_SCALEDOWN) { + /* +@@ -739,7 +740,10 @@ find_nfs_srvr(mntfs *mf) + * to decide the highest NFS version to try. + */ + #ifdef MNTTAB_OPT_VERS +- nfs_version = hasmntval(&mnt, MNTTAB_OPT_VERS); ++ if (!hasmntvaldelim(&mnt, MNTTAB_OPT_VERS, ",.", &val) || val < 0) ++ nfs_version = 0; ++ else ++ nfs_version = val; + #endif /* MNTTAB_OPT_VERS */ + + #ifdef MNTTAB_OPT_PROTO +@@ -934,11 +938,11 @@ find_nfs_srvr(mntfs *mf) + * If the port has been determined from the portmapper, use that. + * Default to NFS_PORT otherwise (cf. RFC 2054, 3). + */ +- nfs_port_opt = hasmntval(&mnt, MNTTAB_OPT_PORT); +- if (nfs_port_opt > 0) +- nfs_port = htons(nfs_port_opt); +- if (!nfs_port) ++ if (!hasmntval(&mnt, MNTTAB_OPT_PORT, &nfs_port) ++ || nfs_port > 65535 || nfs_port <= 0) + nfs_port = htons(NFS_PORT); ++ else ++ nfs_port = htons(nfs_port); + + dlog("%s: using port %d for nfs on %s", __func__, + (int) ntohs(nfs_port), host); +@@ -1050,7 +1054,9 @@ no_dns: + fs->fs_flags |= FSF_PING_UNINIT; /* pinger hasn't been initialized */ + np = ALLOC(struct nfs_private); + memset((voidp) np, 0, sizeof(*np)); +- np->np_mountd = htons(hasmntval(&mnt, "mountport")); ++ if (!hasmntval(&mnt, "mountport", &val) || val < 0) ++ val = 0; ++ np->np_mountd = htons(val); + if (np->np_mountd == 0) { + np->np_mountd_inval = 'Y'; + np->np_xid = XID_ALLOC(); +--- am-utils-6.2.orig/hlfsd/hlfsd.c ++++ am-utils-6.2/hlfsd/hlfsd.c +@@ -530,8 +530,7 @@ main(int argc, char *argv[]) + + genflags = compute_mount_flags(&mnt); + +- retry = hasmntval(&mnt, MNTTAB_OPT_RETRY); +- if (retry <= 0) ++ if (!hasmntval(&mnt, MNTTAB_OPT_RETRY, &retry) || retry <= 0) + retry = 1; /* XXX */ + + memmove(&anh.v2, root_fhp, sizeof(*root_fhp)); +--- am-utils-6.2.orig/include/am_utils.h ++++ am-utils-6.2/include/am_utils.h +@@ -290,8 +290,8 @@ extern int compute_mount_flags(mntent_t + extern void discard_nfs_args(void *, u_long); + extern u_long get_amd_program_number(void); + extern int getcreds(struct svc_req *, uid_t *, gid_t *, SVCXPRT *); +-extern int hasmntval(mntent_t *, char *); +-extern unsigned int hasmntvalerr(mntent_t *, char *, int *); ++extern int hasmntval(mntent_t *, char *, int *); ++extern int hasmntvaldelim(mntent_t *, char *, const char *, int *); + extern char *hasmntstr(mntent_t *, char *); + extern char *hasmnteq(mntent_t *, char *); + extern char *haseq(char *); +--- am-utils-6.2.orig/libamu/mount_fs.c ++++ am-utils-6.2/libamu/mount_fs.c +@@ -188,8 +188,10 @@ static void + addvers(char *zopts, size_t l, mntent_t *mnt, u_long have_vers, + u_long want_vers) + { +- if (have_vers == want_vers && +- hasmntval(mnt, MNTTAB_OPT_VERS) != want_vers) { ++ int val; ++ if (have_vers == want_vers ++ && hasmntvaldelim(mnt, MNTTAB_OPT_VERS, ".,", &val) ++ && (u_long)val != want_vers) { + char optsbuf[48]; + xsnprintf(optsbuf, sizeof(optsbuf), + "%s=%d", MNTTAB_OPT_VERS, want_vers); +@@ -391,7 +393,7 @@ compute_nfs_attrcache_flags(struct nfs_c + * on the values of the attribute caches. + */ + #ifdef MNTTAB_OPT_ACTIMEO +- err_acval = hasmntvalerr(mntp, MNTTAB_OPT_ACTIMEO, &acval); /* attr cache timeout (sec) */ ++ err_acval = !hasmntval(mntp, MNTTAB_OPT_ACTIMEO, &acval); /* attr cache timeout (sec) */ + #endif /* MNTTAB_OPT_ACTIMEO */ + + /*** acregmin ***/ +@@ -402,7 +404,7 @@ compute_nfs_attrcache_flags(struct nfs_c + } else { + # ifdef MNTTAB_OPT_ACREGMIN + int tmp; +- err_acrdmm = hasmntvalerr(mntp, MNTTAB_OPT_ACREGMIN, &tmp); ++ err_acrdmm = !hasmntval(mntp, MNTTAB_OPT_ACREGMIN, &tmp); + nap->acregmin = tmp; + # else /* not MNTTAB_OPT_ACREGMIN */ + nap->acregmin = 0; +@@ -423,7 +425,7 @@ compute_nfs_attrcache_flags(struct nfs_c + } else { + # ifdef MNTTAB_OPT_ACREGMAX + int tmp; +- err_acrdmm = hasmntvalerr(mntp, MNTTAB_OPT_ACREGMAX, &tmp); ++ err_acrdmm = !hasmntval(mntp, MNTTAB_OPT_ACREGMAX, &tmp); + nap->acregmax = tmp; + # else /* not MNTTAB_OPT_ACREGMAX */ + nap->acregmax = 0; +@@ -444,7 +446,7 @@ compute_nfs_attrcache_flags(struct nfs_c + } else { + # ifdef MNTTAB_OPT_ACDIRMIN + int tmp; +- err_acrdmm = hasmntvalerr(mntp, MNTTAB_OPT_ACDIRMIN, &tmp); ++ err_acrdmm = !hasmntval(mntp, MNTTAB_OPT_ACDIRMIN, &tmp); + nap->acdirmin = tmp; + # else /* not MNTTAB_OPT_ACDIRMIN */ + nap->acdirmin = 0; +@@ -465,7 +467,7 @@ compute_nfs_attrcache_flags(struct nfs_c + } else { + # ifdef MNTTAB_OPT_ACDIRMAX + int tmp; +- err_acrdmm = hasmntvalerr(mntp, MNTTAB_OPT_ACDIRMAX, &tmp); ++ err_acrdmm = !hasmntval(mntp, MNTTAB_OPT_ACDIRMAX, &tmp); + nap->acdirmax = tmp; + # else /* not MNTTAB_OPT_ACDIRMAX */ + nap->acdirmax = 0; +@@ -492,6 +494,7 @@ static void + compute_nfs_common_args(struct nfs_common_args *nap, mntent_t *mntp, + const char *nfs_proto, u_long nfs_version) + { ++ int val; + #ifdef MNT2_NFS_OPT_TCP + if (nfs_proto && STREQ(nfs_proto, "tcp")) + nap->flags |= MNT2_NFS_OPT_TCP; +@@ -536,7 +539,10 @@ compute_nfs_common_args(struct nfs_commo + # endif /* not MNTTAB_OPT_RESVPORT */ + #endif /* MNT2_NFS_OPT_RESVPORT */ + +- nap->rsize = hasmntval(mntp, MNTTAB_OPT_RSIZE); ++ if (!hasmntval(mntp, MNTTAB_OPT_RSIZE, &val) || val <= 0) ++ nap->rsize = 0; ++ else ++ nap->rsize = val; + #ifdef MNT2_NFS_OPT_RSIZE + if (nap->rsize) + nap->flags |= MNT2_NFS_OPT_RSIZE; +@@ -544,7 +550,10 @@ compute_nfs_common_args(struct nfs_commo + if (nfs_version == NFS_VERSION && nap->rsize > 8192) + nap->rsize = 8192; + +- nap->wsize = hasmntval(mntp, MNTTAB_OPT_WSIZE); ++ if (!hasmntval(mntp, MNTTAB_OPT_WSIZE, &val) || val <= 0) ++ nap->wsize = 0; ++ else ++ nap->wsize = val; + #ifdef MNT2_NFS_OPT_WSIZE + if (nap->wsize) + nap->flags |= MNT2_NFS_OPT_WSIZE; +@@ -552,13 +561,19 @@ compute_nfs_common_args(struct nfs_commo + if (nfs_version == NFS_VERSION && nap->wsize > 8192) + nap->wsize = 8192; + +- nap->timeo = hasmntval(mntp, MNTTAB_OPT_TIMEO); ++ if (!hasmntval(mntp, MNTTAB_OPT_TIMEO, &val) || val <= 0) ++ nap->timeo = 0; ++ else ++ nap->timeo = val; + #ifdef MNT2_NFS_OPT_TIMEO + if (nap->timeo) + nap->flags |= MNT2_NFS_OPT_TIMEO; + #endif /* MNT2_NFS_OPT_TIMEO */ + +- nap->retrans = hasmntval(mntp, MNTTAB_OPT_RETRANS); ++ if (!hasmntval(mntp, MNTTAB_OPT_RETRANS, &val) || val <= 0) ++ nap->retrans = 0; ++ else ++ nap->retrans = val; + #ifdef MNT2_NFS_OPT_RETRANS + if (nap->retrans) + nap->flags |= MNT2_NFS_OPT_RETRANS; +@@ -861,6 +876,7 @@ compute_nfs23_args(nfs_args_t *nap, + char *host_name, + char *fs_name) + { ++ int val; + struct nfs_common_args a; + /* initialize just in case */ + memset((voidp) nap, 0, sizeof(nfs_args_t)); +@@ -995,18 +1011,30 @@ compute_nfs23_args(nfs_args_t *nap, + /************************************************************************/ + + #ifdef MNT2_NFS_OPT_BIODS +- if ((nap->biods = hasmntval(mntp, MNTTAB_OPT_BIODS))) ++ if (!hasmntval(mntp, MNTTAB_OPT_BIODS, &val) || val <= 0) ++ nap->biods = 0; ++ else { ++ nap->biods = val; + nap->flags |= MNT2_NFS_OPT_BIODS; ++ } + #endif /* MNT2_NFS_OPT_BIODS */ + + #ifdef MNTTAB_OPT_SYMTTL /* symlink cache time-to-live */ +- if ((nap->symttl = hasmntval(mntp, MNTTAB_OPT_SYMTTL))) ++ if (!hasmntval(mntp, MNTTAB_OPT_SYMTTL, &val) || val <= 0) ++ nap->symttl = 0; ++ else { ++ nap->symttl = val; + nap->flags |= MNT2_NFS_OPT_SYMTTL; ++ } + #endif /* MNTTAB_OPT_SYMTTL */ + + #ifdef MNT2_NFS_OPT_PGTHRESH /* paging threshold */ +- if ((nap->pg_thresh = hasmntval(mntp, MNTTAB_OPT_PGTHRESH))) ++ if (!hasmntval(mntp, MNTTAB_OPT_PGTHRESH, &val) || val <= 0) ++ nap->pg_thresh = 0; ++ else { ++ nap->pg_thresh = val; + nap->flags |= MNT2_NFS_OPT_PGTHRESH; ++ } + #endif /* MNT2_NFS_OPT_PGTHRESH */ + + #if defined(MNT2_NFS_OPT_POSIX) && defined(MNTTAB_OPT_POSIX) +@@ -1020,7 +1048,7 @@ compute_nfs23_args(nfs_args_t *nap, + + #ifdef HAVE_TRANSPORT_TYPE_TLI + /* set up syncaddr field */ +- nap->syncaddr = (struct netbuf *) NULL; ++ nap->syncaddr = NULL; + + /* set up knconf field */ + if (get_knetconfig(&nap->knconf, nfsncp, nfs_proto) < 0) { +@@ -1043,9 +1071,12 @@ compute_nfs23_args(nfs_args_t *nap, + #endif /* HAVE_NFS_ARGS_T_OPTSTR */ + + #if defined(MNT2_NFS_OPT_MAXGRPS) && defined(MNTTAB_OPT_MAXGROUPS) +- nap->maxgrouplist = hasmntval(mntp, MNTTAB_OPT_MAXGROUPS); +- if (nap->maxgrouplist != 0) ++ if (!hasmntval(mntp, MNTTAB_OPT_MAXGROUPS, &val) || val <= 0) ++ nap->maxgrouplist = 0; ++ else { ++ nap->maxgrouplist = val; + nap->flags |= MNT2_NFS_OPT_MAXGRPS; ++ } + #endif /* defined(MNT2_NFS_OPT_MAXGRPS) && defined(MNTTAB_OPT_MAXGROUPS) */ + + /************************************************************************/ +@@ -1267,6 +1298,7 @@ compute_nfs4_args(nfs4_args_t *nap, + { + char *s; + struct nfs_common_args a; ++ int val; + uint16_t nfs_port; + + /* initialize just in case */ +@@ -1304,11 +1336,10 @@ compute_nfs4_args(nfs4_args_t *nap, + nap->host_addr = xmalloc(nap->host_addrlen); + memcpy(nap->host_addr, ip_addr, nap->host_addrlen); + +- nfs_port = hasmntval(mntp, MNTTAB_OPT_PORT); +- if (nfs_port == 0) ++ if (!hasmntval(mntp, MNTTAB_OPT_PORT, &val) || val <= 0 || val > 65536) + nfs_port = htons(NFS_PORT); + else +- nfs_port = htons(nfs_port); ++ nfs_port = htons(val); + + ((struct sockaddr_in *)nap->host_addr)->sin_port = nfs_port; + +@@ -1341,9 +1372,13 @@ compute_nfs4_args(nfs4_args_t *nap, + #endif /* MNT2_NFS_OPT_POSIX && MNTTAB_OPT_POSIX */ + + #if defined(MNT2_NFS_OPT_MAXGRPS) && defined(MNTTAB_OPT_MAXGROUPS) +- nap->maxgrouplist = hasmntval(mntp, MNTTAB_OPT_MAXGROUPS); +- if (nap->maxgrouplist != 0) ++ nap->maxgrouplist = ++ if (!hasmntval(mntp, MNTTAB_OPT_MAXGROUPS, &val) || val <= 0) ++ nap->maxgrouplist = 0; ++ else { ++ nap->maxgrouplist = val; + nap->flags |= MNT2_NFS_OPT_MAXGRPS; ++ } + #endif /* defined(MNT2_NFS_OPT_MAXGRPS) && defined(MNTTAB_OPT_MAXGROUPS) */ + + #ifdef HAVE_NFS_ARGS_T_OPTSTR +--- am-utils-6.2.orig/libamu/mtab.c ++++ am-utils-6.2/libamu/mtab.c +@@ -133,22 +133,12 @@ hasmnteq(mntent_t *mnt, char *opt) + + + /* +- * Wrapper around hasmntvalerr(), which retains backwards compatibiliy with +- * older use of hasmntval(). +- * +- * XXX: eventually, all use of hasmntval() should be replaced with +- * hasmntvalerr(). ++ * Wrapper around hasmntvaldelim(), which uses the standard "," delim + */ + int +-hasmntval(mntent_t *mnt, char *opt) ++hasmntval(mntent_t *mnt, char *opt, int *valp) + { +- int err, val = 0; +- +- err = hasmntvalerr(mnt, opt, &val); +- if (err) /* if there was an error (hasmntvalerr returned 1) */ +- return 0; /* redundant: val==0 above, but leave here for clarity */ +- /* otherwise there was no error */ +- return val; ++ return hasmntvaldelim(mnt, opt, ",", valp); + } + + +@@ -158,36 +148,31 @@ hasmntval(mntent_t *mnt, char *opt) + * valp (argument won't be touched if no value is set, for example due to an + * error). + * +- * Returns non-zero (1) on error; returns 0 on success. +- * +- * XXX: eventually, all use of hasmntval() should be replaced with +- * hasmntvalerr(). ++ * Returns 0 on error; returns 1 on success. + */ +-unsigned int +-hasmntvalerr(mntent_t *mnt, char *opt, int *valp) ++int ++hasmntvaldelim(mntent_t *mnt, char *opt, const char *delim, int *valp) + { + char *str = amu_hasmntopt(mnt, opt); +- int err = 1; /* 1 means no good value was set (an error) */ + char *eq, *endptr; + long int i; + + /* exit if no option specificed */ +- if (!str) { +- goto out; +- } ++ if (!str) ++ return 0; + + eq = hasmnteq(mnt, opt); + + if (!eq) { /* no argument to option ('=' sign was missing) */ + plog(XLOG_MAP, "numeric option to \"%s\" missing", opt); +- goto out; ++ return 0; + } + + /* if got here, then we had an '=' after option name */ + endptr = NULL; + i = strtol(eq, &endptr, 0); /* hex and octal allowed ;-) */ + if (!endptr || +- (endptr != eq && (*endptr == ',' || *endptr == '\0'))) { ++ (endptr != eq && (*endptr == '\0' || strchr(delim, *endptr)))) { + /* + * endptr set means strtol saw a non-digit. If the non-digit is a + * comma, it's probably the start of the next option. If the comma is +@@ -198,15 +183,13 @@ hasmntvalerr(mntent_t *mnt, char *opt, i + * string. + */ + *valp = (int) i; /* set good value */ +- err = 0; /* no error */ ++ return 1; + } else { + /* whatever was after the '=' sign wasn't a number */ + plog(XLOG_MAP, "invalid numeric option in \"%s\": \"%s\"", opt, str); + /* fall through to error/exit processing */ ++ return 0; + } +- +- out: +- return err; + } + + diff --git a/am-utils-6.2-There-is-really-no-ti-rpc-nfsv4-so-dont-send-one.patch b/am-utils-6.2-There-is-really-no-ti-rpc-nfsv4-so-dont-send-one.patch new file mode 100644 index 0000000..78ba30b --- /dev/null +++ b/am-utils-6.2-There-is-really-no-ti-rpc-nfsv4-so-dont-send-one.patch @@ -0,0 +1,45 @@ +commit e7d1bd38b1d1de6b1bec603eeff915ebb57f3c37 +Author: zoulasc +Date: Thu Mar 10 17:50:34 2016 -0500 + + - There is really no ti-rpc nfsv4, so don't send one; instead send a v3 for now. + +diff --git a/amd/srvr_nfs.c b/amd/srvr_nfs.c +index b7c852c..1418a1a 100644 +--- a/amd/srvr_nfs.c ++++ b/amd/srvr_nfs.c +@@ -140,6 +140,7 @@ create_ping_payload(u_long nfs_version) + { + XDR ping_xdr; + struct rpc_msg ping_msg; ++ int rpc_version; + + /* + * Non nfs mounts like /afs/glue.umd.edu have ended up here. +@@ -150,7 +151,17 @@ create_ping_payload(u_long nfs_version) + } else + plog(XLOG_INFO, "%s: nfs_version: %d", __func__, (int) nfs_version); + +- rpc_msg_init(&ping_msg, NFS_PROGRAM, nfs_version, NFSPROC_NULL); ++ /* ++ * There is really no ti-rpc version for NFSv4; most servers respond ++ * with "program unavailable", which is ok since we don't check the ++ * payload, we just care about the pings. Some servers though are ++ * antisocial (Isilon) and don't respond (which is their right to do). ++ * Eventually we should make a new mechanism to do server pings for ++ * NFSv4, but for now it is easiest to downgrade the RPC version to 3. ++ */ ++ rpc_version = nfs_version == 4 ? 3 : nfs_version; ++ ++ rpc_msg_init(&ping_msg, NFS_PROGRAM, rpc_version, NFSPROC_NULL); + + /* + * Create an XDR endpoint +@@ -600,6 +611,7 @@ nfs_keepalive(voidp v) + case ENETUNREACH: + case EHOSTDOWN: + case EHOSTUNREACH: ++ dlog("Failed to NFS ping to %s (%d)", fs->fs_host, error); + np->np_ping = MAX_ALLOWED_PINGS; /* immediately down */ + np->np_ttl = (time_t) 0; + /* diff --git a/am-utils-6.2-Update-the-ctime-of-the-directory-too-since-it-changed.patch b/am-utils-6.2-Update-the-ctime-of-the-directory-too-since-it-changed.patch new file mode 100644 index 0000000..64fbaff --- /dev/null +++ b/am-utils-6.2-Update-the-ctime-of-the-directory-too-since-it-changed.patch @@ -0,0 +1,30 @@ +commit ad416c8656c2dff6f1bcffee8517284de94c9d92 +Author: zoulasc +Date: Thu May 12 10:21:55 2016 -0400 + + Update the ctime of the directory too, since it changed. From Mark Davies + +diff --git a/amd/autil.c b/amd/autil.c +index 35d8708..f44a0e2 100644 +--- a/amd/autil.c ++++ b/amd/autil.c +@@ -183,6 +183,7 @@ forcibly_timeout_mp(am_node *mp) + * more. + */ + clocktime(&mp->am_parent->am_fattr.na_mtime); ++ mp->am_parent->am_fattr.na_ctime = mp->am_parent->am_fattr.na_mtime; + reschedule_timeout_mp(); + } + } +@@ -312,8 +313,10 @@ am_mounted(am_node *mp) + /* + * Update mtime of parent node (copying "struct nfstime" in '=' below) + */ +- if (mp->am_parent && mp->am_parent->am_al->al_mnt) ++ if (mp->am_parent && mp->am_parent->am_al->al_mnt) { + mp->am_parent->am_fattr.na_mtime = mp->am_fattr.na_mtime; ++ mp->am_parent->am_fattr.na_ctime = mp->am_fattr.na_mtime; ++ } + + /* + * This is ugly, but essentially unavoidable diff --git a/am-utils-6.2-add-NFSv3-nfs_quick_reply-functionality.patch b/am-utils-6.2-add-NFSv3-nfs_quick_reply-functionality.patch new file mode 100644 index 0000000..8aaf65f --- /dev/null +++ b/am-utils-6.2-add-NFSv3-nfs_quick_reply-functionality.patch @@ -0,0 +1,241 @@ +am-utils-6.2 - add NFSv3 nfs_quick_reply() functionality + +From: Ian Kent + +The implementation of the NFS v3 server does not use the hack needed +by the nfs_quick_reply() function. + +Now that saving the current transort for later use by nfs_quick_reply() +avoids concurrency races it should be ok to use it. + +Signed-off-by: Ian Kent +--- + amd/nfs_prot_svc.c | 13 +++++ + amd/nfs_subr.c | 137 +++++++++++++++++++++++++++++++++++++++++----------- + 2 files changed, 120 insertions(+), 30 deletions(-) + +diff --git a/amd/nfs_prot_svc.c b/amd/nfs_prot_svc.c +index cbde172..29b7551 100644 +--- a/amd/nfs_prot_svc.c ++++ b/amd/nfs_prot_svc.c +@@ -180,7 +180,7 @@ nfs_program_2(struct svc_req *rqstp, SVCXPRT *transp) + xdr_result = (xdrproc_t) xdr_diropres; + local = (nfssvcproc_t) nfsproc_lookup_2_svc; + /* +- * Cheap way to pass transp down to amfs_auto_lookuppn so it can ++ * Cheap way to pass transp down to amfs_auto_lookup so it can + * be stored in the am_node structure and later used for + * quick_reply(). + */ +@@ -327,6 +327,8 @@ nfs_program_3(struct svc_req *rqstp, register SVCXPRT *transp) + xdrproc_t _xdr_argument, _xdr_result; + nfssvcproc_t local; + ++ current_transp = NULL; ++ + switch (rqstp->rq_proc) { + case AM_NFS3_NULL: + _xdr_argument = (xdrproc_t) xdr_void; +@@ -350,6 +352,12 @@ nfs_program_3(struct svc_req *rqstp, register SVCXPRT *transp) + _xdr_argument = (xdrproc_t) xdr_am_LOOKUP3args; + _xdr_result = (xdrproc_t) xdr_am_LOOKUP3res; + local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_lookup_3_svc; ++ /* ++ * Cheap way to pass transp down to amfs_auto_lookup so it can ++ * be stored in the am_node structure and later used for ++ * quick_reply(). ++ */ ++ current_transp = transp; + break; + + case AM_NFS3_ACCESS: +@@ -476,6 +484,9 @@ nfs_program_3(struct svc_req *rqstp, register SVCXPRT *transp) + } + + result = (*local) (&argument, rqstp); ++ ++ current_transp = NULL; ++ + if (result != NULL && !svc_sendreply(transp, (xdrproc_t) _xdr_result, result)) { + svcerr_systemerr (transp); + } +diff --git a/amd/nfs_subr.c b/amd/nfs_subr.c +index 07d960d..a383618 100644 +--- a/amd/nfs_subr.c ++++ b/amd/nfs_subr.c +@@ -87,6 +87,9 @@ struct am_fh3 { + }; + + /* forward declarations */ ++static int nfs_quick_reply2(am_node *mp, int error); ++static int nfs_quick_reply3(am_node *mp, int error); ++ + /* converting am-filehandles to mount-points */ + static am_node *fh_to_mp3(am_nfs_fh *fhp, int *rp, int vop); + static am_node *fh_to_mp(am_nfs_fh *fhp); +@@ -255,46 +258,65 @@ nfsproc_lookup_2_svc(nfsdiropargs *argp, struct svc_req *rqstp) + return &res; + } + +- + void + nfs_quick_reply(am_node *mp, int error) + { +- SVCXPRT *transp = mp->am_transp; +- nfsdiropres res; +- xdrproc_t xdr_result = (xdrproc_t) xdr_diropres; ++ int ret; + + /* +- * If there's a transp structure then we can reply to the client's +- * nfs lookup request. ++ * If there's no transp structure then we can't reply to the ++ * client's nfs lookup request. + */ +- if (transp) { +- if (error == 0) { +- /* +- * Construct a valid reply to a lookup request. Same +- * code as in nfsproc_lookup_2_svc() above. +- */ +- mp_to_fh(mp, &res.dr_u.dr_drok_u.drok_fhandle); +- res.dr_u.dr_drok_u.drok_attributes = mp->am_fattr; +- res.dr_status = NFS_OK; +- } else +- /* +- * Return the error that was passed to us. +- */ +- res.dr_status = nfs_error(error); ++ if (!mp->am_transp) ++ return; ++ ++ if (nfs_dispatcher == nfs_program_2) ++ ret = nfs_quick_reply2(mp, error); ++ else ++ ret = nfs_quick_reply3(mp, error); ++ ++ if (!ret) ++ svcerr_systemerr(mp->am_transp); ++ ++ /* ++ * Free up transp. It's only used for one reply. ++ */ ++ put_nfs_xprt(mp->am_transp); ++ mp->am_transp = NULL; ++ dlog("Quick reply sent for %s", mp->am_al->al_mnt->mf_mount); ++} + ++ ++static int ++nfs_quick_reply2(am_node *mp, int error) ++{ ++ SVCXPRT *transp = mp->am_transp; ++ nfsdiropres res; ++ xdrproc_t xdr_result = (xdrproc_t) xdr_diropres; ++ int ret; ++ ++ if (error == 0) { + /* +- * Send off our reply ++ * Construct a valid reply to a lookup request. Same ++ * code as in nfsproc_lookup_2_svc() above. + */ +- if (!svc_sendreply(transp, (XDRPROC_T_TYPE) xdr_result, (SVC_IN_ARG_TYPE) & res)) +- svcerr_systemerr(transp); +- ++ mp_to_fh(mp, &res.dr_u.dr_drok_u.drok_fhandle); ++ res.dr_u.dr_drok_u.drok_attributes = mp->am_fattr; ++ res.dr_status = NFS_OK; ++ } else + /* +- * Free up transp. It's only used for one reply. ++ * Return the error that was passed to us. + */ +- put_nfs_xprt(mp->am_transp); +- mp->am_transp = NULL; +- dlog("Quick reply sent for %s", mp->am_al->al_mnt->mf_mount); +- } ++ res.dr_status = nfs_error(error); ++ ++ /* ++ * Send off our reply ++ */ ++ ret = svc_sendreply(transp, ++ (XDRPROC_T_TYPE) xdr_result, ++ (SVC_IN_ARG_TYPE) & res); ++ ++ return ret; + } + + +@@ -890,6 +912,8 @@ mp_to_fh(am_node *mp, am_nfs_fh *fhp) + /* dlog("mp_to_fh: old filehandle: %d", fp->u.s.fhh_id); */ + } + } ++ ++ + void + mp_to_fh3(am_node *mp, am_nfs_fh3 *fhp) + { +@@ -1257,6 +1281,61 @@ am_nfs3_lookup_3_svc(am_LOOKUP3args *argp, struct svc_req *rqstp) + return &result; + } + ++ ++static int ++nfs_quick_reply3(am_node *mp, int error) ++{ ++ SVCXPRT *transp = mp->am_transp; ++ xdrproc_t xdr_result = (xdrproc_t) xdr_am_LOOKUP3res; ++ am_LOOKUP3res result; ++ am_post_op_attr *post_op_dir; ++ am_post_op_attr *post_op_obj; ++ int ret; ++ ++ if (error) { ++ /* ++ * Return the error that was passed to us. ++ */ ++ post_op_dir->attributes_follow = 0; ++ result.status = nfs_error(error); ++ } else { ++ post_op_dir = &result.res_u.ok.dir_attributes; ++ post_op_obj = &result.res_u.ok.obj_attributes; ++ am_fattr3 *fattr3; ++ nfsfattr *fattr; ++ ++ /* ++ * Construct a valid reply to a lookup request. Same ++ * code as in am_nfs3_lookup_3_svc() above. ++ */ ++ ++ /* dir attributes */ ++ post_op_dir->attributes_follow = 1; ++ fattr3 = &post_op_dir->am_post_op_attr_u.attributes; ++ parent_fattr_to_fattr3(mp, fattr3); ++ ++ mp_to_fh3(mp, &result.res_u.ok.object); ++ ++ /* mount attributes */ ++ post_op_obj->attributes_follow = 1; ++ fattr = &mp->am_fattr; ++ fattr3 = &post_op_obj->am_post_op_attr_u.attributes; ++ fattr_to_fattr3(fattr, fattr3); ++ ++ result.status = AM_NFS3_OK; ++ } ++ ++ /* ++ * Send off our reply ++ */ ++ ret = svc_sendreply(transp, ++ (XDRPROC_T_TYPE) xdr_result, ++ (SVC_IN_ARG_TYPE) &result); ++ ++ return ret; ++} ++ ++ + am_ACCESS3res * + am_nfs3_access_3_svc(am_ACCESS3args *argp, struct svc_req *rqstp) + { diff --git a/am-utils-6.2-add-NFSv3-rpc-request-validation.patch b/am-utils-6.2-add-NFSv3-rpc-request-validation.patch new file mode 100644 index 0000000..f5968e1 --- /dev/null +++ b/am-utils-6.2-add-NFSv3-rpc-request-validation.patch @@ -0,0 +1,127 @@ +am-utils-6.2 - add NFSv3 rpc request validation + +From: Ian Kent + +The NFS v2 internal server uses several validation checks for each +RPC request it receives, also add this validation for the NFS v3 +internal server. + +Signed-off-by: Ian Kent +--- + amd/nfs_prot_svc.c | 65 +++++++++++++++++++++++++++++++--------------------- + 1 file changed, 39 insertions(+), 26 deletions(-) + +diff --git a/amd/nfs_prot_svc.c b/amd/nfs_prot_svc.c +index 29b7551..cae12d4 100644 +--- a/amd/nfs_prot_svc.c ++++ b/amd/nfs_prot_svc.c +@@ -71,30 +71,9 @@ dispatcher_t nfs_dispatcher = nfs_program_2; + typedef char *(*nfssvcproc_t)(voidp, struct svc_req *); + + +-void +-nfs_program_2(struct svc_req *rqstp, SVCXPRT *transp) ++static int ++validate_rpc_request(struct svc_req *rqstp, SVCXPRT *transp) + { +- union { +- am_nfs_fh nfsproc_getattr_2_arg; +- nfssattrargs nfsproc_setattr_2_arg; +- nfsdiropargs nfsproc_lookup_2_arg; +- am_nfs_fh nfsproc_readlink_2_arg; +- nfsreadargs nfsproc_read_2_arg; +- nfswriteargs nfsproc_write_2_arg; +- nfscreateargs nfsproc_create_2_arg; +- nfsdiropargs nfsproc_remove_2_arg; +- nfsrenameargs nfsproc_rename_2_arg; +- nfslinkargs nfsproc_link_2_arg; +- nfssymlinkargs nfsproc_symlink_2_arg; +- nfscreateargs nfsproc_mkdir_2_arg; +- nfsdiropargs fsproc_rmdir_2_arg; +- nfsreaddirargs nfsproc_readdir_2_arg; +- am_nfs_fh nfsproc_statfs_2_arg; +- } argument; +- char *result; +- xdrproc_t xdr_argument, xdr_result; +- nfssvcproc_t local; +- + #ifdef HAVE_TRANSPORT_TYPE_TLI + /* + * On TLI systems we don't use an INET network type, but a "ticlts" (see +@@ -109,7 +88,7 @@ nfs_program_2(struct svc_req *rqstp, SVCXPRT *transp) + extern int __rpc_get_local_uid(SVCXPRT *transp, uid_t *uid); + if (__rpc_get_local_uid(transp, &u) >= 0 && u != 0) { + plog(XLOG_WARNING, "ignoring request from UID %ld, must be 0", (long) u); +- return; ++ return 0; + } + # else /* not HAVE___RPC_GET_LOCAL_UID */ + dlog("cannot verify local uid for rpc request"); +@@ -126,7 +105,7 @@ nfs_program_2(struct svc_req *rqstp, SVCXPRT *transp) + plog(XLOG_WARNING, "ignoring request from %s:%u, port not reserved", + inet_dquad(dq, sizeof(dq), sinp->sin_addr.s_addr), + ntohs(sinp->sin_port)); +- return; ++ return 0; + } + # endif /* MNT2_NFS_OPT_RESVPORT */ + /* if the address does not match, ignore the request */ +@@ -136,16 +115,47 @@ nfs_program_2(struct svc_req *rqstp, SVCXPRT *transp) + plog(XLOG_WARNING, "ignoring request from %s:%u, not a local interface", + inet_dquad(dq, sizeof(dq), sinp->sin_addr.s_addr), + ntohs(sinp->sin_port)); ++ return 0; + } + } else { + plog(XLOG_WARNING, "ignoring request from %s:%u, expected %s", + inet_dquad(dq, sizeof(dq), sinp->sin_addr.s_addr), + ntohs(sinp->sin_port), + inet_dquad(dq2, sizeof(dq2), myipaddr.s_addr)); +- return; ++ return 0; + } + } + #endif /* not HAVE_TRANPORT_TYPE_TLI */ ++ return 1; ++} ++ ++ ++void ++nfs_program_2(struct svc_req *rqstp, SVCXPRT *transp) ++{ ++ union { ++ am_nfs_fh nfsproc_getattr_2_arg; ++ nfssattrargs nfsproc_setattr_2_arg; ++ nfsdiropargs nfsproc_lookup_2_arg; ++ am_nfs_fh nfsproc_readlink_2_arg; ++ nfsreadargs nfsproc_read_2_arg; ++ nfswriteargs nfsproc_write_2_arg; ++ nfscreateargs nfsproc_create_2_arg; ++ nfsdiropargs nfsproc_remove_2_arg; ++ nfsrenameargs nfsproc_rename_2_arg; ++ nfslinkargs nfsproc_link_2_arg; ++ nfssymlinkargs nfsproc_symlink_2_arg; ++ nfscreateargs nfsproc_mkdir_2_arg; ++ nfsdiropargs fsproc_rmdir_2_arg; ++ nfsreaddirargs nfsproc_readdir_2_arg; ++ am_nfs_fh nfsproc_statfs_2_arg; ++ } argument; ++ char *result; ++ xdrproc_t xdr_argument, xdr_result; ++ nfssvcproc_t local; ++ ++ if (!validate_rpc_request(rqstp, transp)) ++ return; + + current_transp = NULL; + +@@ -327,6 +337,9 @@ nfs_program_3(struct svc_req *rqstp, register SVCXPRT *transp) + xdrproc_t _xdr_argument, _xdr_result; + nfssvcproc_t local; + ++ if (!validate_rpc_request(rqstp, transp)) ++ return; ++ + current_transp = NULL; + + switch (rqstp->rq_proc) { diff --git a/am-utils-6.2-add-get_nfs_xprt-and-put_nfs_xprt-functions.patch b/am-utils-6.2-add-get_nfs_xprt-and-put_nfs_xprt-functions.patch new file mode 100644 index 0000000..c24b20e --- /dev/null +++ b/am-utils-6.2-add-get_nfs_xprt-and-put_nfs_xprt-functions.patch @@ -0,0 +1,170 @@ +am-utils-6.2 - add get_nfs_xprt() and put_nfs_xprt() functions + +From: Ian Kent + +The nfs_quick_reply() functionality relies on taking a copy of the +current transport for later use. + +The problem with this is the context of the RPC message is kept in +the transport and if any RPC message arrives before nfs_quick_reply() +is called that context will be corrupted. + +So add a function get_nfs_xprt() to replace the current transport +with a new one returning the passed in transort so nfs_quick_reply() +can use it later. + +A function put_nfs_xprt() is also added (although not really needed +since it just destroys the now unused transport) for completeness. + +Signed-off-by: Ian Kent +--- + conf/transp/transp_sockets.c | 44 ++++++++++++++++++++++++++++++++++++++++ + conf/transp/transp_tli.c | 46 +++++++++++++++++++++++++++++++++++++++++- + include/am_utils.h | 2 ++ + 3 files changed, 91 insertions(+), 1 deletion(-) + +diff --git a/conf/transp/transp_sockets.c b/conf/transp/transp_sockets.c +index 6326007..a6e0054 100644 +--- a/conf/transp/transp_sockets.c ++++ b/conf/transp/transp_sockets.c +@@ -45,6 +45,7 @@ + #include + #include + ++static int soNFS = RPC_ANYSOCK; + + /* + * find the IP address that can be used to connect to the local host +@@ -273,9 +274,52 @@ create_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (* + return 3; + } + ++ soNFS = *soNFSp; ++ + return 0; /* all is well */ + } + ++/* ++ * Get a pointer to the current NFS SVCXPRT and replace it ++ * with a new one. ++ */ ++SVCXPRT * ++get_nfs_xprt(SVCXPRT *nfs_xprt) ++{ ++ SVCXPRT *newxprt; ++ int newfd; ++ ++ if (!nfs_xprt || soNFS == RPC_ANYSOCK) ++ return NULL; ++ ++ newfd = dup(soNFS); ++ if (newfd < 0) ++ return NULL; ++ ++ xprt_unregister(nfs_xprt); ++ newxprt = svcudp_create(newfd); ++ if (!newxprt) { ++ plog(XLOG_FATAL, "Can't switch to new transport"); ++ xprt_register(nfs_xprt); ++ close(newfd); ++ return NULL; ++ } ++ ++ soNFS = newfd; ++ ++ return nfs_xprt; ++} ++ ++/* ++ * Destroy a transport previously obtained by get_nfs_xprt(). ++ */ ++void put_nfs_xprt(SVCXPRT *nfs_xprt) ++{ ++ if (!nfs_xprt || soNFS == RPC_ANYSOCK) ++ return; ++ ++ svc_destroy(nfs_xprt); ++} + + /* + * Create the amq service for amd (both TCP and UDP) +diff --git a/conf/transp/transp_tli.c b/conf/transp/transp_tli.c +index d26a511..bfdb526 100644 +--- a/conf/transp/transp_tli.c ++++ b/conf/transp/transp_tli.c +@@ -45,7 +45,8 @@ + #include + #include + +-struct netconfig *nfsncp; ++struct netconfig *nfsncp = NULL; ++static int soNFS = RPC_ANYSOCK; + + + /* +@@ -456,9 +457,52 @@ create_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (* + return 1; + } + ++ soNFS = *soNFSp; ++ + return 0; /* all is well */ + } + ++/* ++ * Get a pointer to the current NFS SVCXPRT and replace it ++ * with a new one. ++ */ ++SVCXPRT * ++get_nfs_xprt(SVCXPRT *nfs_xprt) ++{ ++ SVCXPRT *newxprt; ++ int newfd; ++ ++ if (!nfs_xprt || soNFS == RPC_ANYSOCK) ++ return NULL; ++ ++ newfd = dup(soNFS); ++ if (newfd < 0) ++ return NULL; ++ ++ xprt_unregister(nfs_xprt); ++ newxprt = svc_tli_create(newfd, nfsncp, NULL, 0, 0); ++ if (!newxprt) { ++ plog(XLOG_FATAL, "Can't switch to new transport"); ++ xprt_register(nfs_xprt); ++ close(newfd); ++ return NULL; ++ } ++ ++ soNFS = newfd; ++ ++ return nfs_xprt; ++} ++ ++/* ++ * Destroy a transport previously obtained by get_nfs_xprt(). ++ */ ++void put_nfs_xprt(SVCXPRT *nfs_xprt) ++{ ++ if (!nfs_xprt || soNFS == RPC_ANYSOCK) ++ return; ++ ++ svc_destroy(nfs_xprt); ++} + + /* + * Bind to preferred AMQ port. +diff --git a/include/am_utils.h b/include/am_utils.h +index 0de881a..ff13c26 100644 +--- a/include/am_utils.h ++++ b/include/am_utils.h +@@ -378,6 +378,8 @@ extern void compute_nfs_args(void *nap, mntent_t *mntp, int genflags, struct net + extern void destroy_nfs_args(void *nap, u_long nfs_version); + extern int create_amq_service(int *udp_soAMQp, SVCXPRT **udp_amqpp, struct netconfig **udp_amqncpp, int *tcp_soAMQp, SVCXPRT **tcp_amqpp, struct netconfig **tcp_amqncpp, u_short preferred_amq_port); + extern int create_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (*dispatch_fxn)(struct svc_req *rqstp, SVCXPRT *transp), u_long nfs_version); ++extern SVCXPRT *get_nfs_xprt(SVCXPRT *nfs_xprt); ++extern void put_nfs_xprt(SVCXPRT *nfs_xprt); + extern int amu_svc_register(SVCXPRT *, u_long, u_long, void (*)(struct svc_req *, SVCXPRT *), u_long, struct netconfig *); + + #ifdef HAVE_TRANSPORT_TYPE_TLI diff --git a/am-utils-6.2-add-more-debugging-in-the-unmount-path.patch b/am-utils-6.2-add-more-debugging-in-the-unmount-path.patch new file mode 100644 index 0000000..ea310d0 --- /dev/null +++ b/am-utils-6.2-add-more-debugging-in-the-unmount-path.patch @@ -0,0 +1,94 @@ +commit a5ea57a64a1d70486e8d8ab2da944e50ca51b836 +Author: zoulasc +Date: Tue Mar 8 23:31:26 2016 -0500 + + - add more debugging in the unmount path + - if the EXPIRE_MULTI call fails, with EAGAIN, fail back to the EXPIRE call + seems to fix unmounting with nfsv4 volumes. + +diff --git a/conf/autofs/autofs_linux.c b/conf/autofs/autofs_linux.c +index d543979..5b4ac06 100644 +--- a/conf/autofs/autofs_linux.c ++++ b/conf/autofs/autofs_linux.c +@@ -365,6 +365,7 @@ autofs_expire_one(am_node *mp, char *name, autofs_wqt_t token) + + ap = find_ap(ap_path); + if (ap == NULL) { ++ dlog("%s: could not find %s", __func__, ap_path); + /* not found??? not sure what to do here... */ + send_fail(fh->ioctlfd, token); + goto out; +@@ -376,6 +377,7 @@ autofs_expire_one(am_node *mp, char *name, autofs_wqt_t token) + p->next = fh->pending_umounts; + fh->pending_umounts = p; + ++ dlog("%s: unmount for %s", __func__, ap_path); + unmount_mp(ap); + + out: +@@ -426,6 +428,7 @@ autofs_missing_one(am_node *mp, autofs_wqt_t wait_queue_token, char *name) + dlog("Mount still pending, not sending autofs reply yet"); + return; + } ++ dlog("%s: lookup failed for %s/%s", __func__, mp->am_path, name); + autofs_lookup_failed(mp, name); + } + mp->am_stats.s_lookup++; +@@ -872,15 +875,42 @@ autofs_compute_mount_flags(mntent_t *mnt) + return 0; + } + ++static int autofs_expire_4(am_node *mp) ++{ ++ struct autofs_packet_expire pkt; ++ autofs_fh_t *fh = mp->am_autofs_fh; ++ ++ dlog("Calling AUTOFS_IOC_EXPIRE"); ++ if (ioctl(fh->ioctlfd, AUTOFS_IOC_EXPIRE, &pkt) == -1) ++ { ++ dlog("AUTOFS_IOC_EXPIRE for %s failed %d", mp->am_path, errno); ++ return -1; ++ } ++ ++ autofs_handle_expire(mp, &pkt); ++ return 0; ++} ++ + + #if AUTOFS_MAX_PROTO_VERSION >= 4 + static int autofs_timeout_mp_task(void *arg) + { + am_node *mp = (am_node *)arg; + autofs_fh_t *fh = mp->am_autofs_fh; +- int now = 0; +- +- while (ioctl(fh->ioctlfd, AUTOFS_IOC_EXPIRE_MULTI, &now) == 0); ++ int how = AUTOFS_EXP_IMMEDIATE; ++ ++ for (;;) ++ { ++ dlog("Calling AUTOFS_IOC_EXPIRE_MULTI"); ++ if (ioctl(fh->ioctlfd, AUTOFS_IOC_EXPIRE_MULTI, &how) == -1) ++ { ++ dlog("AUTOFS_IOC_EXPIRE_MULTI for %s failed %d", mp->am_path, errno); ++ if (errno != EAGAIN) ++ break; ++ if (autofs_expire_4(mp) == -1) ++ break; ++ } ++ } + return 0; + } + #endif /* AUTOFS_MAX_PROTO_VERSION >= 4 */ +@@ -895,9 +925,8 @@ void autofs_timeout_mp(am_node *mp) + mp->am_autofs_ttl = now + gopt.am_timeo_w; + + if (fh->version < 4) { +- struct autofs_packet_expire pkt; +- while (ioctl(fh->ioctlfd, AUTOFS_IOC_EXPIRE, &pkt) == 0) +- autofs_handle_expire(mp, &pkt); ++ while (autofs_expire_4(mp) == 0) ++ continue; + return; + } + diff --git a/am-utils-6.2-dont-use-logical-double-ampersand-when-ampersand-is-meant.patch b/am-utils-6.2-dont-use-logical-double-ampersand-when-ampersand-is-meant.patch new file mode 100644 index 0000000..6271797 --- /dev/null +++ b/am-utils-6.2-dont-use-logical-double-ampersand-when-ampersand-is-meant.patch @@ -0,0 +1,19 @@ +commit a187041e062c5b656def30a3ec282156360003f3 +Author: Christos Zoulas +Date: Wed Jan 21 23:28:46 2015 -0500 + + don't use logical && when & is meant + +diff --git a/amd/map.c b/amd/map.c +index fce8273..0d404cf 100644 +--- a/amd/map.c ++++ b/amd/map.c +@@ -752,7 +752,7 @@ umount_exported(void) + } else { + am_unmounted(mp); + } +- if (!(mf->mf_flags && (MFF_UNMOUNTING|MFF_MOUNTED))) ++ if (!(mf->mf_flags & (MFF_UNMOUNTING|MFF_MOUNTED))) + exported_ap[i] = NULL; + } else { + /* diff --git a/am-utils-6.2-fix-Linux-NFS-recognition-of-umounts.patch b/am-utils-6.2-fix-Linux-NFS-recognition-of-umounts.patch new file mode 100644 index 0000000..6513e19 --- /dev/null +++ b/am-utils-6.2-fix-Linux-NFS-recognition-of-umounts.patch @@ -0,0 +1,39 @@ +am-utils-6.2 - fix Linux NFS recognition of umounts + +From: Ian Kent + +Recent Linux NFS uses a simulated attibute cache change detection +method based on ctime. Consequenty the amd use of mtime for this +doesn't work properly for some kernel versions. + +The problem seen with some kernel versions is a failure to recognize +umounts. + +Updating the parent ctime in step with mtime during umount appears +to fix the problem. + +Signed-off-by: Ian Kent +--- + amd/autil.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/amd/autil.c b/amd/autil.c +index cd9514d..efd18ef 100644 +--- a/amd/autil.c ++++ b/amd/autil.c +@@ -709,10 +709,13 @@ am_unmounted(am_node *mp) + --mp->am_parent->am_fattr.na_nlink; + + /* +- * Update mtime of parent node ++ * Update mtime and ctime of parent node (as ctime is needed for some ++ * Linux NFS kernel versions to properly recognize attribute changes). + */ +- if (mp->am_parent && mp->am_parent->am_al->al_mnt) ++ if (mp->am_parent && mp->am_parent->am_al->al_mnt) { + clocktime(&mp->am_parent->am_fattr.na_mtime); ++ mp->am_parent->am_fattr.na_ctime = mp->am_parent->am_fattr.na_mtime; ++ } + + if (mp->am_parent && (mp->am_flags & AMF_REMOUNT)) { + char *fname = xstrdup(mp->am_name); diff --git a/am-utils-6.2-fix-compiler-assignment-warning-due-to-libtirpc.patch b/am-utils-6.2-fix-compiler-assignment-warning-due-to-libtirpc.patch new file mode 100644 index 0000000..2ddb6d1 --- /dev/null +++ b/am-utils-6.2-fix-compiler-assignment-warning-due-to-libtirpc.patch @@ -0,0 +1,57 @@ +am-utils-6.2 - fix compiler assignment warning due to libtirpc + +From: Ian Kent + +When using libtirpc there is a compiler warning on an assignment in +the amq_program_1() function. + +This warning was due to libtirpc using struct sockaddr_in6 for some +address fields in the transport structure as it is backward compatible +with struct sockaddr_in when IPv4 is in use. + +But if TLI is in use svc_getcaller() may not be defined or, if it is, +doesn't work as expected. + +So change to using amu_svc_getcaller(), which deals with the needed +cast for libtirpc, and handle the NULL return if TLI is being used. + +Signed-off-by: Ian Kent +--- + amd/amq_svc.c | 24 +++++++++++++++--------- + 1 file changed, 15 insertions(+), 9 deletions(-) + +diff --git a/amd/amq_svc.c b/amd/amq_svc.c +index 1f2b3d6..40f79fa 100644 +--- a/amd/amq_svc.c ++++ b/amd/amq_svc.c +@@ -162,15 +162,21 @@ amq_program_1(struct svc_req *rqstp, SVCXPRT *transp) + + #if defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) + if (gopt.flags & CFM_USE_TCPWRAPPERS) { +- struct sockaddr_in *remote_addr = svc_getcaller(rqstp->rq_xprt); +- char *remote_hostname = inet_ntoa(remote_addr->sin_addr); +- +- if (!amqsvc_is_client_allowed(remote_addr)) { +- plog(XLOG_WARNING, "Amd denied remote amq service to %s", remote_hostname); +- svcerr_auth(transp, AUTH_FAILED); +- return; +- } else { +- dlog("Amd allowed remote amq service to %s", remote_hostname); ++ struct sockaddr_in *remote_addr = amu_svc_getcaller(rqstp->rq_xprt); ++ char *remote_hostname; ++ ++ /* Check the return from amu_svc_getcaller() becuase it's always NULL ++ * if TLI is in use. ++ */ ++ if (remote_addr) { ++ remote_hostname = inet_ntoa(remote_addr->sin_addr); ++ if (!amqsvc_is_client_allowed(remote_addr)) { ++ plog(XLOG_WARNING, "Amd denied remote amq service to %s", remote_hostname); ++ svcerr_auth(transp, AUTH_FAILED); ++ return; ++ } else { ++ dlog("Amd allowed remote amq service to %s", remote_hostname); ++ } + } + } + #endif /* defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */ diff --git a/am-utils-6.2-fix-logical-not-comparison-in-get_ldap_timestamp.patch b/am-utils-6.2-fix-logical-not-comparison-in-get_ldap_timestamp.patch new file mode 100644 index 0000000..6c5c026 --- /dev/null +++ b/am-utils-6.2-fix-logical-not-comparison-in-get_ldap_timestamp.patch @@ -0,0 +1,24 @@ +am-utils-6.2 - fix logical not comparison in get_ldap_timestamp() + +From: Ian Kent + +Looks like the not in this comparison is not meant to be applied to *ts. + +Signed-off-by: Ian Kent +--- + amd/info_ldap.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/amd/info_ldap.c b/amd/info_ldap.c +index cfed6fd..ecfc210 100644 +--- a/amd/info_ldap.c ++++ b/amd/info_ldap.c +@@ -446,7 +446,7 @@ get_ldap_timestamp(ALD *a, char *map, time_t *ts) + vals[0], map); + err = ENOENT; + } +- if (!*ts > 0) { ++ if (!(*ts > 0)) { + plog(XLOG_USER, "Nonpositive timestamp %ld for map %s\n", + (u_long) *ts, map); + err = ENOENT; diff --git a/am-utils-6.2-fix-umount-to-mount-race.patch b/am-utils-6.2-fix-umount-to-mount-race.patch new file mode 100644 index 0000000..fb8d77d --- /dev/null +++ b/am-utils-6.2-fix-umount-to-mount-race.patch @@ -0,0 +1,123 @@ +am-utils-6.2 - fix umount to mount race + +From: Ian Kent + +If a mount request arrives while its mount fs is being umounted the +the reference count of the mount fs never reaches 1 so the location +MF_MOUNTED is not cleared and the mount fs instance is not freed. + +This leads to amd thinking the mount fs is still mounted and the +mount request succeeds without its corresponding target being +mounted. + +Signed-off-by: Ian Kent +--- + amd/amd.h | 1 + + amd/amfs_generic.c | 10 +++++++--- + amd/autil.c | 9 +++++++++ + amd/map.c | 13 ++++++++++++- + 4 files changed, 29 insertions(+), 4 deletions(-) + +diff --git a/amd/amd.h b/amd/amd.h +index f66f5b7..504bcf7 100644 +--- a/amd/amd.h ++++ b/amd/amd.h +@@ -112,6 +112,7 @@ + #define AMF_AUTOFS 0x0004 /* This node is part of an autofs filesystem */ + #define AMF_REMOUNT 0x0008 /* This node needs to be remounted */ + #define AMF_SOFTLOOKUP 0x0010 /* This node returns EIO if server is down */ ++#define AMF_SOFTUNMOUNT 0x0020 /* unmount_node() returned EAGAIN, mount still referenced */ + + /* + * macros for struct mntfs (list of mounted filesystems) +diff --git a/amd/amfs_generic.c b/amd/amfs_generic.c +index 86d0ab7..7ab2829 100644 +--- a/amd/amfs_generic.c ++++ b/amd/amfs_generic.c +@@ -178,7 +178,7 @@ amfs_lookup_node(am_node *mp, char *fname, int *error_return) + error = mf->mf_error; + continue; + } +- if (!(mf->mf_flags & MFF_MOUNTED) || (mf->mf_flags & MFF_UNMOUNTING)) { ++ if (mf->mf_flags & (MFF_MOUNTING | MFF_UNMOUNTING)) { + in_progrss: + /* + * If the fs is not mounted or it is unmounting then there +@@ -743,9 +743,13 @@ amfs_bgmount(struct continuation *cp) + + if (mf->mf_flags & (MFF_MOUNTING | MFF_UNMOUNTING)) { + /* +- * Still mounting - retry later ++ * Still mounting or umounting - retry later + */ +- dlog("mount of \"%s\" already pending", mf->mf_info); ++ if (mf->mf_flags & MFF_MOUNTING) { ++ dlog("mount of \"%s\" already pending", mf->mf_info); ++ } else { ++ dlog("unmount of \"%s\" already pending", mf->mf_info); ++ } + goto retry; + } + +diff --git a/amd/autil.c b/amd/autil.c +index f44a0e2..1962c71 100644 +--- a/amd/autil.c ++++ b/amd/autil.c +@@ -703,6 +703,15 @@ am_unmounted(am_node *mp) + } + + /* ++ * Clear the mounted flag in case there is a pending mount with ++ * the same target fs and this is the last reference to it. ++ */ ++ if (mp->am_flags & AMF_SOFTUNMOUNT) ++ mp->am_flags &= ~AMF_SOFTUNMOUNT; ++ else ++ mf->mf_flags &= ~MFF_MOUNTED; ++ ++ /* + * If this is a pseudo-directory then adjust the link count + * in the parent + */ +diff --git a/amd/map.c b/amd/map.c +index a6df44b..cf5263e 100644 +--- a/amd/map.c ++++ b/amd/map.c +@@ -819,11 +819,17 @@ unmount_node(opaque_t arg) + #endif /* HAVE_FS_AUTOFS */ + if (mf->mf_refc == 1) + error = mf->mf_ops->umount_fs(mp, mf); ++ ++ /* Mount was not actually unmounted, soft umount. ++ * Tell the caller about it. ++ */ ++ if (!error && mf->mf_refc > 1) ++ error = EAGAIN; + } + + /* do this again, it might have changed */ + mf = mp->am_al->al_mnt; +- if (error) { ++ if (error && error != EAGAIN) { + errno = error; /* XXX */ + dlog("%s: unmount: %m", mf->mf_mount); + } +@@ -870,6 +876,10 @@ free_map_if_success(int rc, int term, opaque_t arg) + #endif /* HAVE_FS_AUTOFS */ + amd_stats.d_uerr++; + } else if (rc) { ++ if (rc == EAGAIN) { ++ mp->am_flags |= AMF_SOFTUNMOUNT; ++ goto done; ++ } + notify_child(mp, AMQ_UMNT_FAILED, rc, 0); + if (mf->mf_ops == &amfs_program_ops || rc == EBUSY) + plog(XLOG_STATS, "\"%s\" on %s still active", mp->am_path, mf->mf_mount); +@@ -885,6 +895,7 @@ free_map_if_success(int rc, int term, opaque_t arg) + #endif /* HAVE_FS_AUTOFS */ + amd_stats.d_uerr++; + } else { ++done: + /* + * am_unmounted() will call notify_child() appropriately. + */ diff --git a/am-utils-6.2-fix-wcc-attr-usage-in-unlink3_or_rmdir3.patch b/am-utils-6.2-fix-wcc-attr-usage-in-unlink3_or_rmdir3.patch new file mode 100644 index 0000000..6239c9f --- /dev/null +++ b/am-utils-6.2-fix-wcc-attr-usage-in-unlink3_or_rmdir3.patch @@ -0,0 +1,52 @@ +am-utils-6.2 - fix wcc attr usage in unlink3_or_rmdir3() + +From: Ian Kent + +The definition of the wcc post op attributes should be am_fattr3 not +am_wcc_attr in unlink3_or_rmdir3(). + +Signed-off-by: Ian Kent +--- + amd/nfs_subr.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/amd/nfs_subr.c b/amd/nfs_subr.c +index a383618..b88a40c 100644 +--- a/amd/nfs_subr.c ++++ b/amd/nfs_subr.c +@@ -1058,7 +1058,8 @@ static am_nfsstat3 unlink3_or_rmdir3(am_diropargs3 *argp, + am_pre_op_attr *pre_op_dir = &wcc_data->before; + am_post_op_attr *post_op_dir = &wcc_data->after; + nfsfattr *fattr; +- am_wcc_attr *pre_op_wcc_attr, *post_op_wcc_attr; ++ am_wcc_attr *pre_op_wcc_attr; ++ am_fattr3 *post_op_wcc_attr; + am_node *mp, *ap; + int retry; + +@@ -1085,7 +1086,7 @@ static am_nfsstat3 unlink3_or_rmdir3(am_diropargs3 *argp, + fattr_to_wcc_attr(fattr, pre_op_wcc_attr); + + if (mp->am_fattr.na_type != NFDIR) { +- fattr_to_wcc_attr(fattr, post_op_wcc_attr); ++ fattr_to_fattr3(fattr, post_op_wcc_attr); + res = nfs_error(ENOTDIR); + goto out; + } +@@ -1105,14 +1106,14 @@ static am_nfsstat3 unlink3_or_rmdir3(am_diropargs3 *argp, + */ + else if (retry == ENOENT) + retry = 0; +- fattr_to_wcc_attr(fattr, post_op_wcc_attr); ++ fattr_to_fattr3(fattr, post_op_wcc_attr); + res = nfs_error(retry); + } else { + forcibly_timeout_mp(mp); + /* we can't wait for the expire so use the attributes as + * they are now for the post op wcc attributes. + */ +- fattr_to_wcc_attr(fattr, post_op_wcc_attr); ++ fattr_to_fattr3(fattr, post_op_wcc_attr); + res = AM_NFS3_OK; + } + diff --git a/am-utils-6.2-make-sure-variables-are-initialized.patch b/am-utils-6.2-make-sure-variables-are-initialized.patch new file mode 100644 index 0000000..b5449de --- /dev/null +++ b/am-utils-6.2-make-sure-variables-are-initialized.patch @@ -0,0 +1,20 @@ +commit 54da7c8206e38d0bf08a250835553754a1235360 +Author: Christos Zoulas +Date: Wed Jan 21 23:28:33 2015 -0500 + + make sure variables are initialized + +diff --git a/amd/nfs_subr.c b/amd/nfs_subr.c +index 7192a6a..30effba 100644 +--- a/amd/nfs_subr.c ++++ b/amd/nfs_subr.c +@@ -1711,6 +1711,9 @@ am_nfs3_fsstat_3_svc(am_FSSTAT3args *argp, struct svc_req *rqstp) + if ((gopt.flags & CFM_SHOW_STATFS_ENTRIES) && + mp->am_al->al_mnt && mp->am_al->al_mnt->mf_mopts) { + mnt.mnt_opts = mp->am_al->al_mnt->mf_mopts; ++ blocks = 0; ++ bfree = 0; ++ bavail = 0; + if (amu_hasmntopt(&mnt, "browsable")) { + count_map_entries(mp, &blocks, &bfree, &bavail); + } diff --git a/am-utils-6.2-print_nfs_common_args-is-only-needed-with-DEBUG.patch b/am-utils-6.2-print_nfs_common_args-is-only-needed-with-DEBUG.patch new file mode 100644 index 0000000..404e51f --- /dev/null +++ b/am-utils-6.2-print_nfs_common_args-is-only-needed-with-DEBUG.patch @@ -0,0 +1,26 @@ +commit 116309607c437e302dafa1efb60330f54f815761 +Author: Christos Zoulas +Date: Sat Jan 17 12:21:24 2015 -0500 + + print_nfs_common_args() is only needed with DEBUG + +diff --git a/libamu/mount_fs.c b/libamu/mount_fs.c +index b5576bd..b577bab 100644 +--- a/libamu/mount_fs.c ++++ b/libamu/mount_fs.c +@@ -647,6 +647,7 @@ compute_nfs_common_args(struct nfs_common_args *nap, mntent_t *mntp, + #endif /* defined(MNT2_NFS_OPT_XLATECOOKIE) && defined(MNTTAB_OPT_XLATECOOKIE) */ + } + ++#ifdef DEBUG + static void + print_nfs_common_args(const struct nfs_common_args *a) + { +@@ -664,6 +665,7 @@ print_nfs_common_args(const struct nfs_common_args *a) + plog(XLOG_DEBUG, "NA->acdirmax = %lu", a->acdirmax); + #endif /* HAVE_NFS_ARGS_T_ACREGMIN */ + } ++#endif + + static void + discard_nfs23_args(nfs_args_t *nap) diff --git a/am-utils-6.2-remove-set-but-not-used-variable-again.patch b/am-utils-6.2-remove-set-but-not-used-variable-again.patch new file mode 100644 index 0000000..b4dcf94 --- /dev/null +++ b/am-utils-6.2-remove-set-but-not-used-variable-again.patch @@ -0,0 +1,26 @@ +commit a87188b9f0596651ce987253a6af23aca4b08b75 +Author: Christos Zoulas +Date: Sat Jan 17 12:42:55 2015 -0500 + + remove set but not used variable + +diff --git a/conf/transp/transp_sockets.c b/conf/transp/transp_sockets.c +index b3ad5fc..6326007 100644 +--- a/conf/transp/transp_sockets.c ++++ b/conf/transp/transp_sockets.c +@@ -418,7 +418,6 @@ u_long + get_nfs_version(char *host, struct sockaddr_in *sin, u_long nfs_version, const char *proto, u_long def) + { + CLIENT *clnt; +- int again = 0; + enum clnt_stat clnt_stat; + struct timeval tv; + int sock; +@@ -433,7 +432,6 @@ get_nfs_version(char *host, struct sockaddr_in *sin, u_long nfs_version, const c + nfs_version = def; + else + nfs_version = NFS_VERS_MAX; +- again = 1; + } + tv.tv_sec = 2; /* retry every 2 seconds, but also timeout */ + tv.tv_usec = 0; diff --git a/am-utils-6.2-remove-set-but-not-used-variable-mp_error.patch b/am-utils-6.2-remove-set-but-not-used-variable-mp_error.patch new file mode 100644 index 0000000..1f08d8a --- /dev/null +++ b/am-utils-6.2-remove-set-but-not-used-variable-mp_error.patch @@ -0,0 +1,28 @@ +commit ed717dad0fee421744a24e6fb43e09d62b3f898d +Author: Christos Zoulas +Date: Sat Jan 17 12:45:22 2015 -0500 + + remove set but not used variable + +diff --git a/amd/amfs_generic.c b/amd/amfs_generic.c +index 25d734b..c352a32 100644 +--- a/amd/amfs_generic.c ++++ b/amd/amfs_generic.c +@@ -1153,7 +1153,6 @@ amfs_generic_lookup_child(am_node *mp, char *fname, int *error_return, int op) + { + am_node *new_mp; + am_loc **al_array; +- int mp_error; + + dlog("in amfs_generic_lookup_child"); + +@@ -1178,9 +1177,6 @@ amfs_generic_lookup_child(am_node *mp, char *fname, int *error_return, int op) + return new_mp; + } + +- /* save error_return */ +- mp_error = *error_return; +- + al_array = amfs_lookup_loc(new_mp, error_return); + if (!al_array) { + new_mp->am_error = new_mp->am_al->al_mnt->mf_error = *error_return; diff --git a/am-utils-6.2-remove-set-but-not-used-variable-s.patch b/am-utils-6.2-remove-set-but-not-used-variable-s.patch new file mode 100644 index 0000000..20f5911 --- /dev/null +++ b/am-utils-6.2-remove-set-but-not-used-variable-s.patch @@ -0,0 +1,38 @@ +commit 79bb90caf12d2713b4736c3820135f0f00424f10 +Author: Christos Zoulas +Date: Sat Jan 17 12:29:03 2015 -0500 + + remove set but not used variable + +diff --git a/hlfsd/hlfsd.c b/hlfsd/hlfsd.c +index 686bb63..701abcd 100644 +--- a/hlfsd/hlfsd.c ++++ b/hlfsd/hlfsd.c +@@ -144,7 +144,6 @@ main(int argc, char *argv[]) + int opterrs = 0; + int retry; + int soNFS; /* NFS socket */ +- int s = -99; + mntent_t mnt; + nfs_args_t nfs_args; + am_nfs_handle_t anh; +@@ -449,17 +448,16 @@ main(int argc, char *argv[]) + * set this signal handler. + */ + if (amuDebug(D_DAEMON)) { +- s = -99; + while (stoplight != SIGUSR2) { + plog(XLOG_INFO, "parent waits for child to setup (stoplight=%d)", stoplight); + #ifdef HAVE_SIGSUSPEND + { + sigset_t mask; + sigemptyset(&mask); +- s = sigsuspend(&mask); /* wait for child to set up */ ++ (void)sigsuspend(&mask); /* wait for child to set up */ + } + #else /* not HAVE_SIGSUSPEND */ +- s = sigpause(0); /* wait for child to set up */ ++ (void)sigpause(0); /* wait for child to set up */ + #endif /* not HAVE_SIGSUSPEND */ + sleep(1); + } diff --git a/am-utils-6.2-remove-unused-function-show_map.patch b/am-utils-6.2-remove-unused-function-show_map.patch new file mode 100644 index 0000000..f7b6648 --- /dev/null +++ b/am-utils-6.2-remove-unused-function-show_map.patch @@ -0,0 +1,22 @@ +commit f61becdba8df1d6d515f5476d312d3cf4e933946 +Author: Christos Zoulas +Date: Sat Jan 17 12:43:32 2015 -0500 + + remove unused function + +diff --git a/amq/amq.c b/amq/amq.c +index e99732f..5d4ed7a 100644 +--- a/amq/amq.c ++++ b/amq/amq.c +@@ -256,11 +256,6 @@ show_mi(amq_mount_info_list *ml, enum show_opt e, int *mwid, int *dwid, int *twi + } + + static void +-show_map(amq_map_info *mi) +-{ +-} +- +-static void + show_mapinfo(amq_map_info_list *ml, enum show_opt e, int *nwid, int *wwid) + { + u_int i; diff --git a/am-utils-6.2-uid_t-might-be-a-different-size-than-unsigned-int.patch b/am-utils-6.2-uid_t-might-be-a-different-size-than-unsigned-int.patch new file mode 100644 index 0000000..9b5fbc4 --- /dev/null +++ b/am-utils-6.2-uid_t-might-be-a-different-size-than-unsigned-int.patch @@ -0,0 +1,59 @@ +commit 76e1a5ddc9ef9730205b2da2ed6b654d8fbaef40 +Author: Christos Zoulas +Date: Sat Jan 17 12:27:56 2015 -0500 + + uid_t might be a different size than unsigned int, so XXX: truncate. + +diff --git a/hlfsd/stubs.c b/hlfsd/stubs.c +index b26e5f4..70876b7 100644 +--- a/hlfsd/stubs.c ++++ b/hlfsd/stubs.c +@@ -60,6 +60,21 @@ static int started; + static am_nfs_fh slink; + static am_nfs_fh un_fhandle; + ++static void ++xgetuid(uid_t *uid, const void *p) ++{ ++ u_int xuid; ++ (void)memcpy(&xuid, p, sizeof(xuid)); ++ *uid = xuid; ++} ++ ++static void ++xputuid(void *p, uid_t uid) ++{ ++ u_int xuid = uid; ++ (void)memcpy(p, &xuid, sizeof(xuid)); ++} ++ + /* + * GLOBALS: + */ +@@ -160,7 +175,7 @@ nfsproc_getattr_2_svc(am_nfs_fh *argp, struct svc_req *rqstp) + if (gid != hlfs_gid) { + res.ns_status = NFSERR_STALE; + } else { +- (void)memcpy(&uid, argp->fh_data, sizeof(uid)); ++ xgetuid(&uid, argp->fh_data); + if (plt_search(uid) != (uid2home_t *) NULL) { + res.ns_status = NFS_OK; + un_fattr.na_fileid = uid; +@@ -278,7 +293,7 @@ nfsproc_lookup_2_svc(nfsdiropargs *argp, struct svc_req *rqstp) + un_fattr.na_fileid = untab[idx].uid; + res.dr_u.dr_drok_u.drok_attributes = un_fattr; + memset(&un_fhandle, 0, sizeof(un_fhandle)); +- memcpy(un_fhandle.fh_data, &untab[idx].uid, sizeof(untab[idx].uid)); ++ xputuid(un_fhandle.fh_data, untab[idx].uid); + xstrlcpy((char *) &un_fhandle.fh_data[sizeof(int)], + untab[idx].username, + sizeof(am_nfs_fh) - sizeof(int)); +@@ -333,7 +348,7 @@ nfsproc_readlink_2_svc(am_nfs_fh *argp, struct svc_req *rqstp) + } + + if (groupid == hlfs_gid) { +- memcpy(&userid, argp->fh_data, sizeof(userid)); ++ xgetuid(&userid, argp->fh_data); + username = (char *) &argp->fh_data[sizeof(int)]; + if (!(res.rlr_u.rlr_data_u = mailbox(userid, username))) + return (nfsreadlinkres *) NULL; diff --git a/am-utils-6.2-use-linux-libtirpc-if-present.patch b/am-utils-6.2-use-linux-libtirpc-if-present.patch new file mode 100644 index 0000000..df20d5c --- /dev/null +++ b/am-utils-6.2-use-linux-libtirpc-if-present.patch @@ -0,0 +1,93 @@ +am-utils-6.2 - use Linux libtirpc if present + +From: Ian Kent + +For Linux systems, if the header files and shared libraries of libtirpc +are present use them instead of the glibc RPC implementation. + +Signed-off-by: Ian Kent +--- + Makefile.am | 3 ++- + configure.ac | 4 ++++ + include/am_compat.h | 8 ++++++-- + m4/macros/check_linux_libtirpc.m4 | 13 +++++++++++++ + 4 files changed, 25 insertions(+), 3 deletions(-) + create mode 100644 m4/macros/check_linux_libtirpc.m4 + +diff --git a/Makefile.am b/Makefile.am +index bae4615..e094e95 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -146,7 +146,8 @@ EXTRA_DIST_M4 = \ + m4/macros/type_xdrproc_t.m4 \ + m4/macros/type_xfs_args.m4 \ + m4/macros/type_yp_order_outorder.m4 \ +- m4/macros/with_addon.m4 ++ m4/macros/with_addon.m4 \ ++ m4/macros/check_linux_libtirpc.m4 + + EXTRA_DIST_CONF = \ + conf/autofs/autofs_default.h \ +diff --git a/configure.ac b/configure.ac +index ce61925..98b444d 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -222,6 +222,9 @@ dnl lots of code. So I am forced to use a special purpose macro that sets + dnl the libraries based on the OS. Sigh. -Erez. + AMU_CHECK_OS_LIBS + ++dnl use Linux libtirpc if possible ++AMU_CHECK_LIBTIRPC ++ + dnl librpc and librpcsvc are needed on Solaris + AC_CHECK_LIB(rpc, clnt_sperrno) + AC_CHECK_LIB(rpcsvc, xdr_fhandle) +@@ -433,6 +436,7 @@ AC_CHECK_HEADERS( \ + arpa/nameser.h \ + arpa/inet.h \ + bsd/rpc/rpc.h \ ++ tirpc/netconfig.h \ + cdfs/cdfsmount.h \ + cdfs/cdfs_mount.h \ + fs/udf/udf_mount.h \ +diff --git a/include/am_compat.h b/include/am_compat.h +index 3463f3f..d6826fc 100644 +--- a/include/am_compat.h ++++ b/include/am_compat.h +@@ -454,11 +454,15 @@ struct hsfs_args { + /* + * Define a dummy struct netconfig for non-TLI systems + */ +-#if !defined(HAVE_NETCONFIG_H) && !defined(HAVE_SYS_NETCONFIG_H) ++#if !defined(HAVE_NETCONFIG_H) ++# if !defined(HAVE_SYS_NETCONFIG_H) ++# if !defined(HAVE_TIRPC_NETCONFIG_H) + struct netconfig { + int dummy; + }; +-#endif /* not HAVE_NETCONFIG_H and not HAVE_SYS_NETCONFIG_H */ ++# endif /* not HAVE_TIRPC_NETCONFIG_H */ ++# endif /* not HAVE_SYS_NETCONFIG_H */ ++#endif /* not HAVE_NETCONFIG_H */ + + /* some OSs don't define INADDR_NONE and assume it's unsigned -1 */ + #ifndef INADDR_NONE +diff --git a/m4/macros/check_linux_libtirpc.m4 b/m4/macros/check_linux_libtirpc.m4 +new file mode 100644 +index 0000000..918423c +--- /dev/null ++++ b/m4/macros/check_linux_libtirpc.m4 +@@ -0,0 +1,13 @@ ++dnl ###################################################################### ++dnl Check for Linux libtirpc library ++AC_DEFUN([AMU_CHECK_LIBTIRPC],[ ++TIRPC_CPPFLAGS="" ++TIRPC_LIBS="" ++ ++AC_CHECK_HEADER(tirpc/netconfig.h,[ ++ TIRPC_CPPFLAGS="-I/usr/include/tirpc" ++ AC_DEFINE(HAVE_LIBTIRPC, 1, [Define to 1 if you have libtirpc headers installed]) ++ AC_CHECK_LIB(tirpc, clnt_tli_create, [TIRPC_LIBS="-ltirpc"], [TIRPC_CPPFLAGS=""])]) ++ AMU_CFLAGS="$AMU_CFLAGS $TIRPC_CPPFLAGS" ++ LIBS="$LIBS $TIRPC_LIBS" ++]) diff --git a/am-utils-6.2-use-new-get_nfs_xprt-and-put_nfs_xprt-functions.patch b/am-utils-6.2-use-new-get_nfs_xprt-and-put_nfs_xprt-functions.patch new file mode 100644 index 0000000..8594739 --- /dev/null +++ b/am-utils-6.2-use-new-get_nfs_xprt-and-put_nfs_xprt-functions.patch @@ -0,0 +1,60 @@ +am-utils-6.2 - use new get_nfs_xprt() and put_nfs_xprt() functions + +From: Ian Kent + +The nfs_quick_reply() function needs to know the current RPC transport +outside of the NFS LOOKUP method call. It needs this to reply to the +NFS LOOKUP call that initiated the mount. + +Now there are functions that avoid transport corruption if another +request comes in during the backgroud mount make nfs_quick_reply() +use them. + +Signed-off-by: Ian Kent +--- + amd/amfs_generic.c | 3 +-- + amd/map.c | 2 +- + amd/nfs_subr.c | 3 ++- + 3 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/amd/amfs_generic.c b/amd/amfs_generic.c +index c352a32..86d0ab7 100644 +--- a/amd/amfs_generic.c ++++ b/amd/amfs_generic.c +@@ -1129,8 +1129,7 @@ amfs_generic_mount_child(am_node *new_mp, int *error_return) + */ + if (current_transp && !new_mp->am_transp) { + dlog("Saving RPC transport for %s", new_mp->am_path); +- new_mp->am_transp = (SVCXPRT *) xmalloc(sizeof(SVCXPRT)); +- *(new_mp->am_transp) = *current_transp; ++ new_mp->am_transp = get_nfs_xprt(current_transp); + } + if (error && new_mp->am_al && new_mp->am_al->al_mnt && + (new_mp->am_al->al_mnt->mf_ops == &amfs_error_ops)) +diff --git a/amd/map.c b/amd/map.c +index 0d404cf..bcb2156 100644 +--- a/amd/map.c ++++ b/amd/map.c +@@ -471,7 +471,7 @@ free_map(am_node *mp) + XFREE(mp->am_name); + XFREE(mp->am_path); + XFREE(mp->am_pref); +- XFREE(mp->am_transp); ++ put_nfs_xprt(mp->am_transp); + + if (mp->am_al) + free_loc(mp->am_al); +diff --git a/amd/nfs_subr.c b/amd/nfs_subr.c +index 0a43b98..07d960d 100644 +--- a/amd/nfs_subr.c ++++ b/amd/nfs_subr.c +@@ -291,7 +291,8 @@ nfs_quick_reply(am_node *mp, int error) + /* + * Free up transp. It's only used for one reply. + */ +- XFREE(mp->am_transp); ++ put_nfs_xprt(mp->am_transp); ++ mp->am_transp = NULL; + dlog("Quick reply sent for %s", mp->am_al->al_mnt->mf_mount); + } + } diff --git a/am-utils.spec b/am-utils.spec index 7659a22..e36532f 100644 --- a/am-utils.spec +++ b/am-utils.spec @@ -2,7 +2,7 @@ Summary: Automount utilities including an updated version of Amd Name: am-utils Version: 6.2.0 %define upstream_version 6.2 -Release: 10%{?dist} +Release: 23%{?dist} License: BSD Epoch: 5 Group: System Environment/Daemons @@ -27,11 +27,13 @@ BuildRequires: systemd-units BuildRequires: texinfo BuildRequires: gcc BuildRequires: m4 +BuildRequires: libtirpc-devel Requires: rpcbind Requires: grep Requires: gawk Requires: findutils +Requires: libtirpc Requires(pre): /bin/grep Requires(post): /sbin/install-info @@ -43,12 +45,43 @@ Requires(preun): /sbin/install-info # Fix problems with possible future libtool rebases (#1181698) Patch1: am-utils-6.2-dont-include-auto-generated-macros-in-aclinlude_m4.patch +Patch2: am-utils-6.2-print_nfs_common_args-is-only-needed-with-DEBUG.patch +Patch3: am-utils-6.2-uid_t-might-be-a-different-size-than-unsigned-int.patch +Patch4: am-utils-6.2-remove-set-but-not-used-variable-s.patch +Patch5: am-utils-6.2-remove-set-but-not-used-variable-again.patch +Patch6: am-utils-6.2-remove-unused-function-show_map.patch +Patch7: am-utils-6.2-remove-set-but-not-used-variable-mp_error.patch +Patch8: am-utils-6.2-32-bit-fixes.patch +Patch9: am-utils-6.2-make-sure-variables-are-initialized.patch +Patch10: am-utils-6.2-dont-use-logical-double-ampersand-when-ampersand-is-meant.patch +Patch11: am-utils-6.2-Fix-nfs-args-setting-code.patch -Patch2: am-utils-6.2-add-debug-log-trace-to-NFSv3-readdirplus.patch -Patch3: am-utils-6.2-fix-NFSv3-access-method-return-on-non-existent-mount-point.patch -Patch4: am-utils-6.2-fix-NFSv3-lookup-dir-attribute-return-value.patch -Patch5: am-utils-6.2-fix-NFSv3-readdir-post_op_dir-attributes-return.patch -Patch6: am-utils-6.2-fix-NFSv3-unlink3_or_rmdir3-post_op-attributes-return.patch +Patch12: am-utils-6.2-add-debug-log-trace-to-NFSv3-readdirplus.patch +Patch13: am-utils-6.2-fix-NFSv3-access-method-return-on-non-existent-mount-point.patch +Patch14: am-utils-6.2-fix-NFSv3-lookup-dir-attribute-return-value.patch +Patch15: am-utils-6.2-fix-NFSv3-readdir-post_op_dir-attributes-return.patch +Patch16: am-utils-6.2-fix-NFSv3-unlink3_or_rmdir3-post_op-attributes-return.patch + +Patch17: am-utils-6.2-fix-Linux-NFS-recognition-of-umounts.patch +Patch18: am-utils-6.2-add-get_nfs_xprt-and-put_nfs_xprt-functions.patch +Patch19: am-utils-6.2-use-new-get_nfs_xprt-and-put_nfs_xprt-functions.patch +Patch20: am-utils-6.2-add-NFSv3-nfs_quick_reply-functionality.patch +Patch21: am-utils-6.2-add-NFSv3-rpc-request-validation.patch +Patch22: am-utils-6.2-fix-wcc-attr-usage-in-unlink3_or_rmdir3.patch + +Patch23: am-utils-6.2-Add-the-sys-alias-for-unix-as-well-as-none-and-null.patch +Patch24: am-utils-6.2-Default-to-string-mount-options-for-NFSv4.patch +Patch25: am-utils-6.2-Improve-debugging-for-unmounting.patch +Patch26: am-utils-6.2-add-more-debugging-in-the-unmount-path.patch +Patch27: am-utils-6.2-There-is-really-no-ti-rpc-nfsv4-so-dont-send-one.patch +Patch28: am-utils-6.2-Fix-SEGV-on-amq-entries-that-print-times.patch +Patch29: am-utils-6.2-Make-hasmntval-return-an-0-on-error-1-on-success.patch +Patch30: am-utils-6.2-Update-the-ctime-of-the-directory-too-since-it-changed.patch + +Patch31: am-utils-6.2-use-linux-libtirpc-if-present.patch +Patch32: am-utils-6.2-fix-compiler-assignment-warning-due-to-libtirpc.patch +Patch33: am-utils-6.2-fix-logical-not-comparison-in-get_ldap_timestamp.patch +Patch34: am-utils-6.2-fix-umount-to-mount-race.patch # Not needed since autoreconf/libtool appear to do this automatically # Leaving it set doesn't appear to be a problem so leave it set in @@ -79,6 +112,34 @@ mounting and unmounting filesystems. %patch4 -p1 %patch5 -p1 %patch6 -p1 +%patch7 -p1 +%patch8 -p1 +%patch9 -p1 +%patch10 -p1 +%patch11 -p1 +%patch12 -p1 +%patch13 -p1 +%patch14 -p1 +%patch15 -p1 +%patch16 -p1 +%patch17 -p1 +%patch18 -p1 +%patch19 -p1 +%patch20 -p1 +%patch21 -p1 +%patch22 -p1 +%patch23 -p1 +%patch24 -p1 +%patch25 -p1 +%patch26 -p1 +%patch27 -p1 +%patch28 -p1 +%patch29 -p1 +%patch30 -p1 +%patch31 -p1 +%patch32 -p1 +%patch33 -p1 +%patch34 -p1 ./bootstrap @@ -190,6 +251,50 @@ fi %{_libdir}/libamu.so* %changelog +* Thu Dec 1 2016 Ian Kent - 5:6.2.0-23 +- fix fix-umount-to-mount-race patch (bug 1399213). + +* Mon Oct 3 2016 Ian Kent - 5:6.2.0-22 +- fix ambiguous else due to dlog() macro usage. + +* Mon Oct 3 2016 Ian Kent - 5:6.2.0-21 +- fix typo in libtirpc configure macro. + +* Mon Oct 3 2016 Ian Kent - 5:6.2.0-20 +- print_nfs_common_args() is only needed with DEBUG. +- uid_t might be a different size than unsigned int. +- remove set but not used variable s. +- remove set but not used variable again. +- remove unused function show_map(). +- remove set but not used variable mp_error. +- 32 bit fixes. +- make sure variables are initialized. +- dont use logical double ampersand when ampersand is meant. +- Fix nfs args setting code. +- Add the sys alias for unix as well as none and null. +- Default to string mount options for NFSv4. +- Improve debugging for unmounting. +- add more debugging in the unmount path. +- There is really no ti-rpc nfsv4 so dont send one. +- Fix SEGV on amq entries that print times. +- Make hasmntval return an 0 on error 1 on success. +- Update the ctime of the directory too since it changed. +- fix compiler assignment warning due to libtirpc. +- fix logical not comparison in get_ldap_timestamp(). +- fix umount to mount race. + +* Fri Mar 4 2016 Ian Kent - 5:6.2.0-12 +- add get_nfs_xprt() and put_nfs_xprt() functions. +- use new get_nfs_xprt() and put_nfs_xprt() functions. +- add NFSv3 nfs_quick_reply() functionality. +- add NFSv3 rpc request validation. +- fix wcc attr usage in unlink3_or_rmdir3(). +- use Linux libtirpc if present. + +* Mon Feb 29 2016 Ian Kent - 5:6.2.0-11 +- fix Linux NFS recognition of umounts. +- add systemd dependency on nfs-lock.service. + * Wed Feb 03 2016 Fedora Release Engineering - 5:6.2.0-10 - Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild diff --git a/amd.service b/amd.service index 0ca9365..e20da2e 100644 --- a/amd.service +++ b/amd.service @@ -1,7 +1,7 @@ [Unit] Description=automount daemon that mounts devices and NFS hosts on demand After=syslog.target network.target network-online.target rpcbind.service -Wants=network-online.target rpcbind.service +Wants=network-online.target rpcbind.service nfs-lock.service [Service] EnvironmentFile=-/etc/sysconfig/amd