autofs-5.0.6 - move timeout to map_source

From: Ian Kent <ikent@redhat.com>

Move the map entry timeout field from "struct autofs_point" to
"struct map_source".

The result of this change is that an individual timeout may be
set for each direct map master map entry.
---

 CHANGELOG              |    1 +
 daemon/automount.c     |    2 +-
 daemon/direct.c        |   32 +++++++++++++++++++++-----------
 daemon/indirect.c      |    7 +++----
 daemon/lookup.c        |    2 ++
 daemon/state.c         |   18 +++++++++++++++++-
 include/automount.h    |    5 +++--
 include/master.h       |    3 ++-
 include/mounts.h       |    2 +-
 lib/master.c           |    9 ++++-----
 lib/master_parse.y     |   32 +++++++++++++-------------------
 lib/mounts.c           |   37 ++++++++++++++++++-------------------
 modules/mount_autofs.c |    5 +++--
 13 files changed, 89 insertions(+), 66 deletions(-)


Index: autofs-5.0.5/CHANGELOG
===================================================================
--- autofs-5.0.5.orig/CHANGELOG
+++ autofs-5.0.5/CHANGELOG
@@ -80,6 +80,7 @@
 - fix parse buffer initialization.
 - fix fix map source check in file lookup.
 - update ->timeout() function to not return timeout.
+- move timeout to map_source (allow per direct map timeout).
 
 03/09/2009 autofs-5.0.5
 -----------------------
Index: autofs-5.0.5/daemon/automount.c
===================================================================
--- autofs-5.0.5.orig/daemon/automount.c
+++ autofs-5.0.5/daemon/automount.c
@@ -1542,7 +1542,7 @@ void *handle_mounts(void *arg)
 
 	/* We often start several automounters at the same time.  Add some
 	   randomness so we don't all expire at the same time. */
-	if (!ap->submount && ap->exp_timeout)
+	if (!ap->submount && ap->exp_runfreq)
 		alarm_add(ap, ap->exp_runfreq + rand() % ap->exp_runfreq);
 
 	pthread_setcancelstate(cancel_state, NULL);
Index: autofs-5.0.5/daemon/direct.c
===================================================================
--- autofs-5.0.5.orig/daemon/direct.c
+++ autofs-5.0.5/daemon/direct.c
@@ -286,7 +286,7 @@ static int unlink_active_mounts(struct a
 
 	if (tree_get_mnt_list(mnts, &list, me->key, 1)) {
 		if (ap->state == ST_READMAP) {
-			time_t tout = ap->exp_timeout;
+			time_t tout = me->source->exp_timeout;
 			int save_ioctlfd, ioctlfd;
 
 			save_ioctlfd = ioctlfd = me->ioctlfd;
@@ -321,18 +321,26 @@ static int unlink_active_mounts(struct a
 	return 1;
 }
 
-int do_mount_autofs_direct(struct autofs_point *ap, struct mnt_list *mnts, struct mapent *me)
+int do_mount_autofs_direct(struct autofs_point *ap,
+			   struct mnt_list *mnts, struct mapent *me,
+			   time_t timeout)
 {
 	const char *str_direct = mount_type_str(t_direct);
 	struct ioctl_ops *ops = get_ioctl_ops();
 	struct mnt_params *mp;
-	time_t timeout = ap->exp_timeout;
 	struct stat st;
 	int status, ret, ioctlfd;
 	const char *map_name;
+	time_t runfreq;
 
-	/* Calculate the timeouts */
-	ap->exp_runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO;
+	if (timeout) {
+		/* Calculate the expire run frequency */
+		runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO;
+		if (ap->exp_runfreq)
+			ap->exp_runfreq = min(ap->exp_runfreq, runfreq);
+		else
+			ap->exp_runfreq = runfreq;
+	}
 
 	if (ops->version && !do_force_unlink) {
 		ap->flags |= MOUNT_FLAG_REMOUNT;
@@ -425,7 +433,7 @@ int do_mount_autofs_direct(struct autofs
 	}
 
 	ops->timeout(ap->logopt, ioctlfd, timeout);
-	notify_mount_result(ap, me->key, str_direct);
+	notify_mount_result(ap, me->key, timeout, str_direct);
 	cache_set_ino_index(me->mc, me->key, st.st_dev, st.st_ino);
 	ops->close(ap->logopt, ioctlfd);
 
@@ -473,6 +481,7 @@ int mount_autofs_direct(struct autofs_po
 	pthread_cleanup_push(cache_lock_cleanup, nc);
 	map = ap->entry->maps;
 	while (map) {
+		time_t timeout;
 		/*
 		 * Only consider map sources that have been read since
 		 * the map entry was last updated.
@@ -483,6 +492,7 @@ int mount_autofs_direct(struct autofs_po
 		}
 
 		mc = map->mc;
+		timeout = map->exp_timeout;
 		cache_readlock(mc);
 		pthread_cleanup_push(cache_lock_cleanup, mc);
 		me = cache_enumerate(mc, NULL);
@@ -491,7 +501,7 @@ int mount_autofs_direct(struct autofs_po
 			if (ne) {
 				if (map->master_line < ne->age) {
 					/* TODO: check return, locking me */
-					do_mount_autofs_direct(ap, mnts, me);
+					do_mount_autofs_direct(ap, mnts, me, timeout);
 				}
 				me = cache_enumerate(mc, me);
 				continue;
@@ -508,7 +518,7 @@ int mount_autofs_direct(struct autofs_po
 			}
 
 			/* TODO: check return, locking me */
-			do_mount_autofs_direct(ap, mnts, me);
+			do_mount_autofs_direct(ap, mnts, me, timeout);
 
 			me = cache_enumerate(mc, me);
 		}
@@ -639,7 +649,7 @@ int mount_autofs_offset(struct autofs_po
 	struct ioctl_ops *ops = get_ioctl_ops();
 	char buf[MAX_ERR_BUF];
 	struct mnt_params *mp;
-	time_t timeout = ap->exp_timeout;
+	time_t timeout = me->source->exp_timeout;
 	struct stat st;
 	int ioctlfd, status, ret;
 	const char *hosts_map_name = "-hosts";
@@ -774,9 +784,9 @@ int mount_autofs_offset(struct autofs_po
 	ops->timeout(ap->logopt, ioctlfd, timeout);
 	cache_set_ino_index(me->mc, me->key, st.st_dev, st.st_ino);
 	if (ap->logopt & LOGOPT_DEBUG)
-		notify_mount_result(ap, mountpoint, str_offset);
+		notify_mount_result(ap, mountpoint, timeout, str_offset);
 	else
-		notify_mount_result(ap, me->key, str_offset);
+		notify_mount_result(ap, me->key, timeout, str_offset);
 	ops->close(ap->logopt, ioctlfd);
 
 	debug(ap->logopt, "mounted trigger %s at %s", me->key, mountpoint);
Index: autofs-5.0.5/daemon/indirect.c
===================================================================
--- autofs-5.0.5.orig/daemon/indirect.c
+++ autofs-5.0.5/daemon/indirect.c
@@ -87,7 +87,7 @@ static int do_mount_autofs_indirect(stru
 {
 	const char *str_indirect = mount_type_str(t_indirect);
 	struct ioctl_ops *ops = get_ioctl_ops();
-	time_t timeout = ap->exp_timeout;
+	time_t timeout = ap->entry->maps->exp_timeout;
 	char *options = NULL;
 	const char *hosts_map_name = "-hosts";
 	const char *map_name = hosts_map_name;
@@ -170,13 +170,12 @@ static int do_mount_autofs_indirect(stru
 	}
 
 	ap->dev = st.st_dev;	/* Device number for mount point checks */
-	ap->exp_runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO;
 
 	ops->timeout(ap->logopt, ap->ioctlfd, timeout);
 	if (ap->logopt & LOGOPT_DEBUG)
-		notify_mount_result(ap, root, str_indirect);
+		notify_mount_result(ap, root, timeout, str_indirect);
 	else
-		notify_mount_result(ap, ap->path, str_indirect);
+		notify_mount_result(ap, ap->path, timeout, str_indirect);
 
 	return 0;
 
Index: autofs-5.0.5/daemon/lookup.c
===================================================================
--- autofs-5.0.5.orig/daemon/lookup.c
+++ autofs-5.0.5/daemon/lookup.c
@@ -411,6 +411,7 @@ static enum nsswitch_status read_map_sou
 	tmap.lookup = map->lookup;
 	tmap.mc = map->mc;
 	tmap.instance = map->instance;
+	tmap.exp_timeout = map->exp_timeout;
 	tmap.recurse = map->recurse;
 	tmap.depth = map->depth;
 	tmap.stale = map->stale;
@@ -771,6 +772,7 @@ static enum nsswitch_status lookup_map_n
 	tmap.format = map->format;
 	tmap.mc = map->mc;
 	tmap.instance = map->instance;
+	tmap.exp_timeout = map->exp_timeout;
 	tmap.recurse = map->recurse;
 	tmap.depth = map->depth;
 	tmap.argc = 0;
Index: autofs-5.0.5/daemon/state.c
===================================================================
--- autofs-5.0.5.orig/daemon/state.c
+++ autofs-5.0.5/daemon/state.c
@@ -400,6 +400,9 @@ static void do_readmap_mount(struct auto
 		}
 		if (valid) {
 			struct mapent_cache *vmc = valid->mc;
+			struct ioctl_ops *ops = get_ioctl_ops();
+			time_t runfreq;
+
 			cache_unlock(vmc);
 			debug(ap->logopt,
 			     "updating cache entry for valid direct trigger %s",
@@ -412,13 +415,22 @@ static void do_readmap_mount(struct auto
 			/* Set device and inode number of the new mapent */
 			cache_set_ino_index(vmc, me->key, me->dev, me->ino);
 			cache_unlock(vmc);
+			/* Set timeout and calculate the expire run frequency */
+			ops->timeout(ap->logopt, valid->ioctlfd, map->exp_timeout);
+			if (map->exp_timeout) {
+				runfreq = (map->exp_timeout + CHECK_RATIO - 1) / CHECK_RATIO;
+				if (ap->exp_runfreq)
+					ap->exp_runfreq = min(ap->exp_runfreq, runfreq);
+				else
+					ap->exp_runfreq = runfreq;
+			}
 		} else if (!tree_is_mounted(mnts, me->key, MNTS_REAL))
 			do_umount_autofs_direct(ap, mnts, me);
 		else
 			debug(ap->logopt,
 			      "%s is mounted", me->key);
 	} else
-		do_mount_autofs_direct(ap, mnts, me);
+		do_mount_autofs_direct(ap, mnts, me, map->exp_timeout);
 
 	return;
 }
@@ -466,6 +478,10 @@ static void *do_readmap(void *arg)
 	pthread_cleanup_pop(1);
 
 	if (ap->type == LKP_INDIRECT) {
+		struct ioctl_ops *ops = get_ioctl_ops();
+		time_t timeout = ap->entry->maps->exp_timeout;
+		ap->exp_runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO;
+		ops->timeout(ap->logopt, ap->ioctlfd, timeout);
 		lookup_prune_cache(ap, now);
 		status = lookup_ghost(ap, ap->path);
 	} else {
Index: autofs-5.0.5/include/automount.h
===================================================================
--- autofs-5.0.5.orig/include/automount.h
+++ autofs-5.0.5/include/automount.h
@@ -114,6 +114,8 @@ int load_autofs4_module(void);
 #define DB(x)           do { } while(0)
 #endif
 
+#define min(a, b)	(a <= b ? a : b)
+
 /* Forward declaraion */
 struct autofs_point; 
 
@@ -453,7 +455,6 @@ struct autofs_point {
 	dev_t dev;			/* "Device" number assigned by kernel */
 	struct master_mapent *entry;	/* Master map entry for this mount */
 	unsigned int type;		/* Type of map direct or indirect */
-	time_t exp_timeout;		/* Timeout for expiring mounts */
 	time_t exp_runfreq;		/* Frequency for polling for timeouts */
 	time_t negative_timeout;	/* timeout in secs for failed mounts */
 	unsigned int flags;		/* autofs mount flags */
@@ -487,7 +488,7 @@ void *expire_proc_indirect(void *);
 void *expire_proc_direct(void *);
 int expire_offsets_direct(struct autofs_point *ap, struct mapent *me, int now);
 int mount_autofs_indirect(struct autofs_point *ap, const char *root);
-int do_mount_autofs_direct(struct autofs_point *ap, struct mnt_list *mnts, struct mapent *me);
+int do_mount_autofs_direct(struct autofs_point *ap, struct mnt_list *mnts, struct mapent *me, time_t timeout);
 int mount_autofs_direct(struct autofs_point *ap);
 int mount_autofs_offset(struct autofs_point *ap, struct mapent *me, const char *root, const char *offset);
 void submount_signal_parent(struct autofs_point *ap, unsigned int success);
Index: autofs-5.0.5/include/master.h
===================================================================
--- autofs-5.0.5.orig/include/master.h
+++ autofs-5.0.5/include/master.h
@@ -23,6 +23,7 @@
 struct map_source {
 	char *type;
 	char *format;
+	time_t exp_timeout;		/* Timeout for expiring mounts */
 	time_t age;
 	unsigned int master_line;
 	struct mapent_cache *mc;
@@ -78,7 +79,7 @@ void master_mutex_unlock(void);
 void master_mutex_lock_cleanup(void *);
 void master_set_default_timeout(void);
 void master_set_default_ghost_mode(void);
-int master_add_autofs_point(struct master_mapent *, time_t, unsigned, unsigned, int);
+int master_add_autofs_point(struct master_mapent *, unsigned, unsigned, int);
 void master_free_autofs_point(struct autofs_point *);
 struct map_source *
 master_add_map_source(struct master_mapent *, char *, char *, time_t, int, const char **);
Index: autofs-5.0.5/include/mounts.h
===================================================================
--- autofs-5.0.5.orig/include/mounts.h
+++ autofs-5.0.5/include/mounts.h
@@ -94,7 +94,7 @@ int tree_find_mnt_ents(struct mnt_list *
 int tree_is_mounted(struct mnt_list *mnts, const char *path, unsigned int type);
 void set_tsd_user_vars(unsigned int, uid_t, gid_t);
 const char *mount_type_str(unsigned int);
-void notify_mount_result(struct autofs_point *, const char *, const char *);
+void notify_mount_result(struct autofs_point *, const char *, time_t, const char *);
 int try_remount(struct autofs_point *, struct mapent *, unsigned int);
 int umount_ent(struct autofs_point *, const char *);
 int mount_multi_triggers(struct autofs_point *, struct mapent *, const char *, unsigned int, const char *);
Index: autofs-5.0.5/lib/master.c
===================================================================
--- autofs-5.0.5.orig/lib/master.c
+++ autofs-5.0.5/lib/master.c
@@ -65,7 +65,7 @@ void master_mutex_lock_cleanup(void *arg
 }
 
 int master_add_autofs_point(struct master_mapent *entry,
-		time_t timeout, unsigned logopt, unsigned ghost, int submount) 
+		unsigned logopt, unsigned ghost, int submount)
 {
 	struct autofs_point *ap;
 	int status;
@@ -89,7 +89,6 @@ int master_add_autofs_point(struct maste
 	ap->entry = entry;
 	ap->exp_thread = 0;
 	ap->readmap_thread = 0;
-	ap->exp_timeout = timeout;
 	/*
 	 * Program command line option overrides config.
 	 * We can't use 0 negative timeout so use default.
@@ -98,7 +97,7 @@ int master_add_autofs_point(struct maste
 		ap->negative_timeout = defaults_get_negative_timeout();
 	else
 		ap->negative_timeout = global_negative_timeout;
-	ap->exp_runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO;
+	ap->exp_runfreq = 0;
 	ap->flags = 0;
 	if (ghost)
 		ap->flags = MOUNT_FLAG_GHOST;
@@ -432,6 +431,7 @@ master_add_source_instance(struct map_so
 	new->age = age;
 	new->master_line = 0;
 	new->mc = source->mc;
+	new->exp_timeout = source->exp_timeout;
 	new->stale = 1;
 
 	tmpargv = copy_argv(argc, argv);
Index: autofs-5.0.5/lib/master_parse.y
===================================================================
--- autofs-5.0.5.orig/lib/master_parse.y
+++ autofs-5.0.5/lib/master_parse.y
@@ -757,9 +757,6 @@ int master_parse_entry(const char *buffe
 		logopt |= (verbose ? LOGOPT_VERBOSE : 0);
 	}
 
-	if (timeout < 0)
-		timeout = default_timeout;
-
 	new = NULL;
 	entry = master_find_mapent(master, path);
 	if (!entry) {
@@ -781,8 +778,19 @@ int master_parse_entry(const char *buffe
 		}
 	}
 
+	if (timeout < 0) {
+		/*
+		 * If no timeout is given get the timout from first
+		 * map (if it exists).
+		 */
+		if (entry->maps)
+			timeout = entry->maps->exp_timeout;
+		else
+			timeout = default_timeout;
+	}
+
 	if (!entry->ap) {
-		ret = master_add_autofs_point(entry, timeout, logopt, ghost, 0);
+		ret = master_add_autofs_point(entry, logopt, ghost, 0);
 		if (!ret) {
 			error(m_logopt, "failed to add autofs_point");
 			if (new)
@@ -790,20 +798,6 @@ int master_parse_entry(const char *buffe
 			local_free_vars();
 			return 0;
 		}
-	} else {
-		struct ioctl_ops *ops = get_ioctl_ops();
-		struct autofs_point *ap = entry->ap;
-
-		/*
-		 * Second and subsequent instances of a mount point
-		 * use the ghost, log and timeout of the first
-		 */
-		if (entry->age < age) {
-			ap->exp_timeout = timeout;
-			ap->exp_runfreq = (ap->exp_timeout + CHECK_RATIO - 1) / CHECK_RATIO;
-			if (ap->ioctlfd != -1 && ap->type == LKP_INDIRECT)
-				ops->timeout(ap->logopt, ap->ioctlfd, timeout);
-		}
 	}
 	if (random_selection)
 		entry->ap->flags |= MOUNT_FLAG_RANDOM_SELECT;
@@ -828,7 +822,7 @@ int master_parse_entry(const char *buffe
 		local_free_vars();
 		return 0;
 	}
-
+	source->exp_timeout = timeout;
 	source->master_line = lineno;
 
 	entry->age = age;
Index: autofs-5.0.5/lib/mounts.c
===================================================================
--- autofs-5.0.5.orig/lib/mounts.c
+++ autofs-5.0.5/lib/mounts.c
@@ -1128,13 +1128,12 @@ const char *mount_type_str(const unsigne
 }
 
 void notify_mount_result(struct autofs_point *ap,
-			 const char *path, const char *type)
+			 const char *path, time_t timeout, const char *type)
 {
-	if (ap->exp_timeout)
+	if (timeout)
 		info(ap->logopt,
 		    "mounted %s on %s with timeout %u, freq %u seconds",
-		    type, path,
-		    (unsigned int) ap->exp_timeout,
+		    type, path, (unsigned int) timeout,
 		    (unsigned int) ap->exp_runfreq);
 	else
 		info(ap->logopt,
@@ -1242,16 +1241,14 @@ static int do_remount_indirect(struct au
 }
 
 static int remount_active_mount(struct autofs_point *ap,
-				struct mapent_cache *mc,
-				const char *path, dev_t devid,
-				const unsigned int type,
-				int *ioctlfd)
+				struct mapent *me, const char *path, dev_t devid,
+				const unsigned int type, int *ioctlfd)
 {
 	struct ioctl_ops *ops = get_ioctl_ops();
-	time_t timeout = ap->exp_timeout;
 	const char *str_type = mount_type_str(type);
 	char buf[MAX_ERR_BUF];
 	unsigned int mounted;
+	time_t timeout;
 	struct stat st;
 	int fd;
 
@@ -1261,6 +1258,12 @@ static int remount_active_mount(struct a
 	ops->open(ap->logopt, &fd, devid, path);
 	if (fd == -1)
 		return REMOUNT_OPEN_FAIL;
+	else {
+		if (type == t_indirect || type == t_offset)
+			timeout = ap->entry->maps->exp_timeout;
+		else
+			timeout = me->source->exp_timeout;
+	}
 
 	/* Re-reading the map, set timeout and return */
 	if (ap->state == ST_READMAP) {
@@ -1294,11 +1297,11 @@ static int remount_active_mount(struct a
 		ops->close(ap->logopt, fd);
 		return REMOUNT_STAT_FAIL;
 	}
-	if (mc)
-		cache_set_ino_index(mc, path, st.st_dev, st.st_ino);
+	if (type != t_indirect)
+		cache_set_ino_index(me->mc, path, st.st_dev, st.st_ino);
 	else
 		ap->dev = st.st_dev;
-	notify_mount_result(ap, path, str_type);
+	notify_mount_result(ap, path, timeout, str_type);
 
 	*ioctlfd = fd;
 
@@ -1341,24 +1344,20 @@ static int remount_active_mount(struct a
 int try_remount(struct autofs_point *ap, struct mapent *me, unsigned int type)
 {
 	struct ioctl_ops *ops = get_ioctl_ops();
-	struct mapent_cache *mc;
 	const char *path;
 	int ret, fd;
 	dev_t devid;
 
-	if (type == t_indirect) {
-		mc = NULL;
+	if (type == t_indirect)
 		path = ap->path;
-	} else {
-		mc = me->mc;
+	else
 		path = me->key;
-	}
 
 	ret = ops->mount_device(ap->logopt, path, type, &devid);
 	if (ret == -1 || ret == 0)
 		return -1;
 
-	ret = remount_active_mount(ap, mc, path, devid, type, &fd);
+	ret = remount_active_mount(ap, me, path, devid, type, &fd);
 
 	/*
 	 * The directory must exist since we found a device
Index: autofs-5.0.5/modules/mount_autofs.c
===================================================================
--- autofs-5.0.5.orig/modules/mount_autofs.c
+++ autofs-5.0.5/modules/mount_autofs.c
@@ -49,7 +49,7 @@ int mount_mount(struct autofs_point *ap,
 	char mountpoint[PATH_MAX];
 	const char **argv;
 	int argc, status, ghost = ap->flags & MOUNT_FLAG_GHOST;
-	time_t timeout = ap->exp_timeout;
+	time_t timeout = ap->entry->maps->exp_timeout;
 	unsigned logopt = ap->logopt;
 	struct map_type_info *info;
 	struct master *master;
@@ -145,7 +145,7 @@ int mount_mount(struct autofs_point *ap,
 		return 1;
 	}
 
-	ret = master_add_autofs_point(entry, timeout, logopt, ghost, 1);
+	ret = master_add_autofs_point(entry, logopt, ghost, 1);
 	if (!ret) {
 		error(ap->logopt,
 		      MODPREFIX "failed to add autofs_point to entry");
@@ -199,6 +199,7 @@ int mount_mount(struct autofs_point *ap,
 		return 1;
 	}
 	free_map_type_info(info);
+	source->exp_timeout = timeout;
 
 	mounts_mutex_lock(ap);
 
