Blob Blame History Raw
autofs-5.1.5 - support strictexpire mount option

From: Ian Kent <raven@themaw.net>

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 <raven@themaw.net>
---
 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 <strtype> map
 %type <strtype> 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;