From 8e963aad47e30f971ac1d58d3f5bc8a2e003c432 Mon Sep 17 00:00:00 2001 From: Erez Zadok Date: Mon, 19 Sep 2005 02:53:30 +0000 Subject: [PATCH] * 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. Update status of freebsd and openbsd. --- ChangeLog | 7 +++++ NEWS | 1 + README.attrcache | 24 ++++++++-------- configure.in | 4 ++- libamu/mount_fs.c | 71 ++++++++++++++++++++++++++++------------------- 5 files changed, 66 insertions(+), 41 deletions(-) diff --git a/ChangeLog b/ChangeLog index d7e1727..ac1b4cc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,8 +1,15 @@ 2005-09-18 Erez Zadok + * 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. diff --git a/NEWS b/NEWS index 97ba184..13db4ea 100644 --- a/NEWS +++ b/NEWS @@ -37,6 +37,7 @@ XXX: Dan, document sun_map_syntax flag in more detail in am-utils.texi and - 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 diff --git a/README.attrcache b/README.attrcache index d290ce9..b167da3 100644 --- a/README.attrcache +++ b/README.attrcache @@ -50,15 +50,15 @@ resolution of only 1 second, which was not fine enough under heavy load. We 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 @@ -76,7 +76,7 @@ configuration parameter called "broken_attrcache" which, if turned on, will 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 @@ -95,12 +95,12 @@ any OS not listed is unknown as of the date at the top of this file. 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). diff --git a/configure.in b/configure.in index ca04bdc..df416cc 100644 --- a/configure.in +++ b/configure.in @@ -55,7 +55,7 @@ AH_BOTTOM([ 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 ***) @@ -866,7 +866,9 @@ AMU_CHECK_FIELD(xfs_args_t.fspec) 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) diff --git a/libamu/mount_fs.c b/libamu/mount_fs.c index 29d6868..a6f97a1 100644 --- a/libamu/mount_fs.c +++ b/libamu/mount_fs.c @@ -349,58 +349,73 @@ compute_nfs_attrcache_flags(nfs_args_t *nap, mntent_t *mntp) 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) -- 2.43.0