2005-09-18 Erez Zadok <ezk@cs.sunysb.edu>
+ * libamu/mount_fs.c (compute_nfs_attrcache_flags): cleanup the
+ code that sets the ac{reg,dir}{min,max} fields so it also sets the
+ appropriate nfs_args->flags such as MNT2_NFS_OPT_ACREGMIN.
+
+ * configure.in: check for nfs_args fields acregmax and acdirmax.
+
* README.attrcache: new file documenting in detail OS bugs
relating to attribute caching, which can affect Amd's reliability
under heavy load.
+ Update status of freebsd and openbsd.
* doc/Makefile.am: install README.attrcache file as attrache.txt
file on am-utils Web site.
- Bugs fixed:
* abort with an error if yacc/lex programs not found
+ * properly turn off the attrcache in freebsd and openbsd
Amd now understands a new log_option called "defaults" which is synonymous
with "fatal,error,user,warning,info" (and is also what logging happens by
fixed this problem and switched to using a microsecond resolution mtime.
After fixing this in Amd, we went on to verify that things work for other
-OSs. When we got to FreeBSD 5.4 and NetBSD 2.0.2, we found out that they
-always cache directory entries, and there is no way to turn it off
-completely. Specifically, if we set the ac{reg,dir}{min,max} fields in
-struct nfs_args all to zero, the kernel seems to cache the entries for a
-default number of seconds (something like 5-30 seconds). On some OSs,
-setting these four fields to 0 turns off the attribute cache, but not on
-these two BSDs. We were able to verify this using Amd and a script that
-exercises the interaction of the kernel's attrcache and Amd. (If you're
-interested, the script can be made available.)
+OSs. When we got to test certain BSDs, we found out that they always cache
+directory entries, and there is no way to turn it off completely.
+Specifically, if we set the ac{reg,dir}{min,max} fields in struct nfs_args
+all to zero, the kernel seems to cache the entries for a default number of
+seconds (something like 5-30 seconds). On some OSs, setting these four
+fields to 0 turns off the attribute cache, but not on some BSDs. We were
+able to verify this using Amd and a script that exercises the interaction of
+the kernel's attrcache and Amd. (If you're interested, the script can be
+made available.)
We then experimented by setting the ac{reg,dir}{min,max} fields in struct
nfs_args all to 1, the smallest non-zero value we could. When we ran the
set these nfs_args fields to 1 instead of 0. I wish I didn't have to create
such ugly workaround features in Amd, but I've got no choice.
-The near term solution is for FreeBSD to support a true 'noac' flag, which
+The near term solution is for every OS to support a true 'noac' flag, which
can be added fairly easily. This'd make Amd work reliably.
The long term solution is to implement Autofs support for all OSs and to
Sun Solaris 8 and 9 (10 probably works fine)
Linux: 2.6.11 kernel (2.4.latest probably works fine)
+FreeBSD 5.4 and 6.0-SNAP001 (older versions probably work fine)
+OpenBSD 3.7 (older versions probably work fine)
** Vulnerable (don't support a proper "noac" flag):
NetBSD 2.0.2 (older versions also probably affected)
-FreeBSD 5.4 (older versions also probably affected)
-OpenBSD 3.7 (older versions also probably affected)
Note: NetBSD has promised to support a noac flag hopefully after 2.1.0 is
released (maybe in 3.0 or 2.2).
dnl
dnl AC_CONFIG_AUX_DIR(m4)
AC_PREREQ(2.52)
-AC_REVISION($Revision: 1.114 $)
+AC_REVISION($Revision: 1.115 $)
AC_COPYRIGHT([Copyright (c) 1997-2005 Erez Zadok])
dnl find out system type
AC_MSG_NOTICE(*** SYSTEM TYPES ***)
AMU_CHECK_FIELD(struct fhstatus.fhs_fh)
AMU_CHECK_FIELD(struct statfs.f_fstypename)
AMU_CHECK_FIELD(nfs_args_t.acdirmin)
+AMU_CHECK_FIELD(nfs_args_t.acdirmax)
AMU_CHECK_FIELD(nfs_args_t.acregmin)
+AMU_CHECK_FIELD(nfs_args_t.acregmax)
AMU_CHECK_FIELD(nfs_args_t.bsize)
AMU_CHECK_FIELD(nfs_args_t.fh_len)
AMU_CHECK_FIELD(nfs_args_t.fhsize)
acval = hasmntval(mntp, MNTTAB_OPT_ACTIMEO); /* attr cache timeout (sec) */
#endif /* MNTTAB_OPT_ACTIMEO */
- if (acval) {
+ /*** acregmin ***/
#ifdef HAVE_NFS_ARGS_T_ACREGMIN
+ if (acval) {
nap->acregmin = acval; /* min ac timeout for reg files (sec) */
- nap->acregmax = acval; /* max ac timeout for reg files (sec) */
-#endif /* HAVE_NFS_ARGS_T_ACREGMIN */
-#ifdef HAVE_NFS_ARGS_T_ACDIRMIN
- nap->acdirmin = acval; /* min ac timeout for dirs (sec) */
- nap->acdirmax = acval; /* max ac timeout for dirs (sec) */
-#endif /* HAVE_NFS_ARGS_T_ACDIRMIN */
} else {
-#ifdef HAVE_NFS_ARGS_T_ACREGMIN
# ifdef MNTTAB_OPT_ACREGMIN
nap->acregmin = hasmntval(mntp, MNTTAB_OPT_ACREGMIN);
# else /* not MNTTAB_OPT_ACREGMIN */
nap->acregmin = 0;
# endif /* not MNTTAB_OPT_ACREGMIN */
+ }
+ /* set this flag, because if we got here, then we changed acregmin */
+# ifdef MNT2_NFS_OPT_ACREGMIN
+ nap->flags |= MNT2_NFS_OPT_ACREGMIN;
+# endif /* MNT2_NFS_OPT_ACREGMIN */
+#endif /* HAVE_NFS_ARGS_T_ACREGMIN */
+
+ /*** acregmax ***/
+#ifdef HAVE_NFS_ARGS_T_ACREGMAX
+ if (acval) {
+ nap->acregmax = acval; /* min ac timeout for reg files (sec) */
+ } else {
# ifdef MNTTAB_OPT_ACREGMAX
nap->acregmax = hasmntval(mntp, MNTTAB_OPT_ACREGMAX);
# else /* not MNTTAB_OPT_ACREGMAX */
nap->acregmax = 0;
# endif /* not MNTTAB_OPT_ACREGMAX */
-#endif /* HAVE_NFS_ARGS_T_ACREGMIN */
+ }
+ /* set this flag, because if we got here, then we changed acregmax */
+# ifdef MNT2_NFS_OPT_ACREGMAX
+ nap->flags |= MNT2_NFS_OPT_ACREGMAX;
+# endif /* MNT2_NFS_OPT_ACREGMAX */
+#endif /* HAVE_NFS_ARGS_T_ACREGMAX */
+
+ /*** acdirmin ***/
#ifdef HAVE_NFS_ARGS_T_ACDIRMIN
+ if (acval) {
+ nap->acdirmin = acval; /* min ac timeout for reg files (sec) */
+ } else {
# ifdef MNTTAB_OPT_ACDIRMIN
nap->acdirmin = hasmntval(mntp, MNTTAB_OPT_ACDIRMIN);
# else /* not MNTTAB_OPT_ACDIRMIN */
nap->acdirmin = 0;
# endif /* not MNTTAB_OPT_ACDIRMIN */
+ }
+ /* set this flag, because if we got here, then we changed acdirmin */
+# ifdef MNT2_NFS_OPT_ACDIRMIN
+ nap->flags |= MNT2_NFS_OPT_ACDIRMIN;
+# endif /* MNT2_NFS_OPT_ACDIRMIN */
+#endif /* HAVE_NFS_ARGS_T_ACDIRMIN */
+
+ /*** acdirmax ***/
+#ifdef HAVE_NFS_ARGS_T_ACDIRMAX
+ if (acval) {
+ nap->acdirmax = acval; /* min ac timeout for reg files (sec) */
+ } else {
# ifdef MNTTAB_OPT_ACDIRMAX
nap->acdirmax = hasmntval(mntp, MNTTAB_OPT_ACDIRMAX);
# else /* not MNTTAB_OPT_ACDIRMAX */
nap->acdirmax = 0;
# endif /* not MNTTAB_OPT_ACDIRMAX */
-#endif /* HAVE_NFS_ARGS_T_ACDIRMIN */
- } /* end of "if (acval)" statement */
-
-#ifdef MNT2_NFS_OPT_ACREGMIN
- if (nap->acregmin)
- nap->flags |= MNT2_NFS_OPT_ACREGMIN;
-#endif /* MNT2_NFS_OPT_ACREGMIN */
-#ifdef MNT2_NFS_OPT_ACREGMAX
- if (nap->acregmax)
- nap->flags |= MNT2_NFS_OPT_ACREGMAX;
-#endif /* MNT2_NFS_OPT_ACREGMAX */
-#ifdef MNT2_NFS_OPT_ACDIRMIN
- if (nap->acdirmin)
- nap->flags |= MNT2_NFS_OPT_ACDIRMIN;
-#endif /* MNT2_NFS_OPT_ACDIRMIN */
-#ifdef MNT2_NFS_OPT_ACDIRMAX
- if (nap->acdirmax)
- nap->flags |= MNT2_NFS_OPT_ACDIRMAX;
-#endif /* MNT2_NFS_OPT_ACDIRMAX */
+ }
+ /* set this flag, because if we got here, then we changed acdirmax */
+# ifdef MNT2_NFS_OPT_ACDIRMAX
+ nap->flags |= MNT2_NFS_OPT_ACDIRMAX;
+# endif /* MNT2_NFS_OPT_ACDIRMAX */
+#endif /* HAVE_NFS_ARGS_T_ACDIRMAX */
#ifdef MNTTAB_OPT_NOAC /* don't cache attributes */
if (amu_hasmntopt(mntp, MNTTAB_OPT_NOAC) != NULL)