autofs-5.1.5 - support strictexpire mount option From: Ian Kent Kernel commit 092a53452b (("autofs: take more care to not update last_used on path walk") helped to (partially) resolve a problem where automounts were not expiring due to aggressive accesses from user space. This patch was later reverted because, for very large environments, it meant more mount requests from clients and when there are a lot of clients this caused a fairly significant increase in server load. But there is a need for both types of expire check, depending on use case, so a mount option to allow for strict update of last use of autofs dentrys has been added ito the autofs file system (which just means not updating the last use on path walk accesses). So add support for this master map mount entry option in the user space code. Signed-off-by: Ian Kent --- CHANGELOG | 1 + daemon/direct.c | 10 ++++++++++ daemon/indirect.c | 10 ++++++++++ include/automount.h | 3 +++ lib/master_parse.y | 8 +++++++- lib/master_tok.l | 1 + man/auto.master.5.in | 8 ++++++++ modules/mount_autofs.c | 5 +++++ 8 files changed, 45 insertions(+), 1 deletion(-) --- autofs-5.1.4.orig/CHANGELOG +++ autofs-5.1.4/CHANGELOG @@ -44,6 +44,7 @@ xx/xx/2018 autofs-5.1.5 - use flags for startup boolean options. - move close stdio descriptors to become_daemon(). - add systemd service command line option. +- support strictexpire mount option. 19/12/2017 autofs-5.1.4 - fix spec file url. --- autofs-5.1.4.orig/daemon/direct.c +++ autofs-5.1.4/daemon/direct.c @@ -421,6 +421,16 @@ int do_mount_autofs_direct(struct autofs mp->options = make_options_string(ap->path, ap->kpipefd, str_direct); if (!mp->options) return 0; + + if ((ap->flags & MOUNT_FLAG_STRICTEXPIRE) && + ((get_kver_major() == 5 && get_kver_minor() > 3) || + (get_kver_major() > 5))) { + char *tmp = realloc(mp->options, strlen(mp->options) + 12); + if (tmp) { + strcat(tmp, ",strictexpire"); + mp->options = tmp; + } + } } /* In case the directory doesn't exist, try to mkdir it */ --- autofs-5.1.4.orig/daemon/indirect.c +++ autofs-5.1.4/daemon/indirect.c @@ -132,6 +132,16 @@ static int do_mount_autofs_indirect(stru goto out_err; } + if ((ap->flags & MOUNT_FLAG_STRICTEXPIRE) && + ((get_kver_major() == 5 && get_kver_minor() > 3) || + (get_kver_major() > 5))) { + char *tmp = realloc(options, strlen(options) + 12); + if (tmp) { + strcat(tmp, ",strictexpire"); + options = tmp; + } + } + /* In case the directory doesn't exist, try to mkdir it */ if (mkdir_path(root, mp_mode) < 0) { if (errno != EEXIST && errno != EROFS) { --- autofs-5.1.4.orig/include/automount.h +++ autofs-5.1.4/include/automount.h @@ -553,6 +553,9 @@ struct kernel_mod_version { #define MOUNT_FLAG_SLAVE 0x0100 #define MOUNT_FLAG_PRIVATE 0x0200 +/* Use strict expire semantics if requested and kernel supports it */ +#define MOUNT_FLAG_STRICTEXPIRE 0x0400 + struct autofs_point { pthread_t thid; char *path; /* Mount point name */ --- autofs-5.1.4.orig/lib/master_parse.y +++ autofs-5.1.4/lib/master_parse.y @@ -58,6 +58,7 @@ static char *format; static long timeout; static long negative_timeout; static unsigned symlnk; +static unsigned strictexpire; static unsigned slave; static unsigned private; static unsigned nobind; @@ -105,7 +106,7 @@ static int master_fprintf(FILE *, char * %token MAP %token OPT_TIMEOUT OPT_NTIMEOUT OPT_NOBIND OPT_NOGHOST OPT_GHOST OPT_VERBOSE %token OPT_DEBUG OPT_RANDOM OPT_USE_WEIGHT OPT_SYMLINK OPT_MODE -%token OPT_SLAVE OPT_PRIVATE +%token OPT_STRICTEXPIRE OPT_SLAVE OPT_PRIVATE %token COLON COMMA NL DDASH %type map %type options @@ -206,6 +207,7 @@ line: | PATH OPT_DEBUG { master_notify($1); YYABORT; } | PATH OPT_TIMEOUT { master_notify($1); YYABORT; } | PATH OPT_SYMLINK { master_notify($1); YYABORT; } + | PATH OPT_STRICTEXPIRE { master_notify($1); YYABORT; } | PATH OPT_SLAVE { master_notify($1); YYABORT; } | PATH OPT_PRIVATE { master_notify($1); YYABORT; } | PATH OPT_NOBIND { master_notify($1); YYABORT; } @@ -619,6 +621,7 @@ option: daemon_option daemon_option: OPT_TIMEOUT NUMBER { timeout = $2; } | OPT_NTIMEOUT NUMBER { negative_timeout = $2; } | OPT_SYMLINK { symlnk = 1; } + | OPT_STRICTEXPIRE { strictexpire = 1; } | OPT_SLAVE { slave = 1; } | OPT_PRIVATE { private = 1; } | OPT_NOBIND { nobind = 1; } @@ -693,6 +696,7 @@ static void local_init_vars(void) timeout = -1; negative_timeout = 0; symlnk = 0; + strictexpire = 0; slave = 0; private = 0; nobind = 0; @@ -901,6 +905,8 @@ int master_parse_entry(const char *buffe entry->ap->flags |= MOUNT_FLAG_USE_WEIGHT_ONLY; if (symlnk) entry->ap->flags |= MOUNT_FLAG_SYMLINK; + if (strictexpire) + entry->ap->flags |= MOUNT_FLAG_STRICTEXPIRE; if (slave) entry->ap->flags |= MOUNT_FLAG_SLAVE; if (private) --- autofs-5.1.4.orig/lib/master_tok.l +++ autofs-5.1.4/lib/master_tok.l @@ -391,6 +391,7 @@ MODE (--mode{OPTWS}|--mode{OPTWS}={OPTW -?nobrowse { return(OPT_NOGHOST); } -?slave { return(OPT_SLAVE); } -?private { return(OPT_PRIVATE); } + -?strictexpire { return(OPT_STRICTEXPIRE); } -g|--ghost|-?browse { return(OPT_GHOST); } -v|--verbose { return(OPT_VERBOSE); } -d|--debug { return(OPT_DEBUG); } --- autofs-5.1.4.orig/man/auto.master.5.in +++ autofs-5.1.4/man/auto.master.5.in @@ -199,6 +199,14 @@ entries only, either in the master map ( or with individual map entries. The option is ignored for direct mounts and non-root offest mount entries. .TP +.I "strictexpire" +Use a strict expire policy for this automount. Using this option means +that last use of autofs directory entries will not be updated during +path walks so that mounts in an automount won't be kept mounted by +applications scanning the mount tree. Note that this doesn't completely +resolve the problem of expired automounts being immediately re-mounted +due to application accesses triggered by the expire itself. +.TP .I slave \fPor\fI private This option allows mount propagation of bind mounts to be set to either \fIslave\fP or \fIprivate\fP. This option may be needed when using --- autofs-5.1.4.orig/modules/mount_autofs.c +++ autofs-5.1.4/modules/mount_autofs.c @@ -57,6 +57,7 @@ int mount_mount(struct autofs_point *ap, int nobind = ap->flags & MOUNT_FLAG_NOBIND; int ghost = ap->flags & MOUNT_FLAG_GHOST; int symlnk = ap->flags & MOUNT_FLAG_SYMLINK; + int strictexpire = ap->flags & MOUNT_FLAG_STRICTEXPIRE; time_t timeout = get_exp_timeout(ap, ap->entry->maps); unsigned logopt = ap->logopt; struct map_type_info *info; @@ -131,6 +132,8 @@ int mount_mount(struct autofs_point *ap, ghost = 1; else if (_strncmp("symlink", cp, 7) == 0) symlnk = 1; + else if (_strncmp("strictexpire", cp, 12) == 0) + strictexpire = 1; else if (_strncmp("hosts", cp, 5) == 0) hosts = 1; else if (_strncmp("timeout=", cp, 8) == 0) { @@ -173,6 +176,8 @@ int mount_mount(struct autofs_point *ap, nap->parent = ap; if (symlnk) nap->flags |= MOUNT_FLAG_SYMLINK; + if (strictexpire) + nap->flags |= MOUNT_FLAG_STRICTEXPIRE; if (hosts) argc = 0;