Blame SOURCES/autofs-5.1.2-add-ref-counting-to-struct-map_source.patch

304803
autofs-5.1.2 - add ref counting to struct map_source
304803
304803
From: Ian Kent <raven@themaw.net>
304803
304803
amd map format maps that are type "auto" frequently refer to the
304803
current map in their map entries.
304803
304803
While this isn't a problem for relatively small maps it can be very
304803
wasteful for large maps and even more so for maps that have multi-
304803
component keys that trigger type "auto" mounts as they progress down
304803
the directory tree.
304803
304803
So add a reference count in order for amd type "auto" mounts to use
304803
the parent map if it matches.
304803
304803
sun format maps are much less likley to use the same map and if they
304803
do they are usually trivial, one line maps, so it isn't a problem.
304803
304803
But, more importantly, sun format maps need to track recursive inclusion
304803
and inclusion depth for a given map source when plus map inclusion is
304803
used which prevents the map soucre from being shared.
304803
304803
Signed-off-by: Ian Kent <raven@themaw.net>
304803
---
304803
 CHANGELOG              |    1 
304803
 daemon/indirect.c      |    7 ++++-
304803
 include/master.h       |    3 ++
304803
 lib/master.c           |   22 +++++++++++++++++
304803
 modules/mount_autofs.c |   60 ++++++++++++++++++++++++++++++++-----------------
304803
 5 files changed, 72 insertions(+), 21 deletions(-)
304803
304803
--- autofs-5.0.7.orig/CHANGELOG
304803
+++ autofs-5.0.7/CHANGELOG
304803
@@ -223,6 +223,7 @@
304803
 - fix argc off by one in mount_autofs.c.
304803
 - fix _strncmp() usage.
304803
 - fix typos in README.amd-maps.
304803
+- add ref counting to struct map_source.
304803
 
304803
 25/07/2012 autofs-5.0.7
304803
 =======================
304803
--- autofs-5.0.7.orig/daemon/indirect.c
304803
+++ autofs-5.0.7/daemon/indirect.c
304803
@@ -96,7 +96,12 @@ static int do_mount_autofs_indirect(stru
304803
 	struct mnt_list *mnts;
304803
 	int ret;
304803
 
304803
-	ap->exp_runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO;
304803
+	/* If the map is being shared the exp_timeout can't be inherited
304803
+	 * from the map source since it may be different so the autofs
304803
+	 * point exp_runfreq must have already been set.
304803
+	 */
304803
+	if (ap->entry->maps->ref <= 1)
304803
+		ap->exp_runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO;
304803
 
304803
 	if (ops->version && !do_force_unlink) {
304803
 		ap->flags |= MOUNT_FLAG_REMOUNT;
304803
--- autofs-5.0.7.orig/include/master.h
304803
+++ autofs-5.0.7/include/master.h
304803
@@ -23,6 +23,7 @@
304803
 #define MAP_FLAG_FORMAT_AMD	0x0001
304803
 
304803
 struct map_source {
304803
+	unsigned int ref;
304803
 	unsigned int flags;
304803
 	char *type;
304803
 	char *format;
304803
@@ -89,6 +90,8 @@ struct map_source *
304803
 master_add_map_source(struct master_mapent *, char *, char *, time_t, int, const char **);
304803
 struct map_source *
304803
 master_find_map_source(struct master_mapent *, const char *, const char *, int, const char **);
304803
+struct map_source *
304803
+master_get_map_source(struct master_mapent *, const char *, const char *, int, const char **);
304803
 void master_free_map_source(struct map_source *, unsigned int);
304803
 struct map_source *
304803
 master_find_source_instance(struct map_source *, const char *, const char *, int, const char **);
304803
--- autofs-5.0.7.orig/lib/master.c
304803
+++ autofs-5.0.7/lib/master.c
304803
@@ -180,6 +180,7 @@ master_add_map_source(struct master_mape
304803
 	if (!source)
304803
 		return NULL;
304803
 	memset(source, 0, sizeof(struct map_source));
304803
+	source->ref = 1;
304803
 
304803
 	if (type) {
304803
 		ntype = strdup(type);
304803
@@ -231,6 +232,8 @@ master_add_map_source(struct master_mape
304803
 
304803
 		this = __master_find_map_source(entry, type, format, argc, tmpargv);
304803
 		if (this) {
304803
+			error(entry->ap->logopt,
304803
+			      "map source used without taking reference");
304803
 			this->age = age;
304803
 			master_free_map_source(source, 0);
304803
 			master_source_unlock(entry);
304803
@@ -329,8 +332,27 @@ struct map_source *master_find_map_sourc
304803
 	return source;
304803
 }
304803
 
304803
+struct map_source *
304803
+master_get_map_source(struct master_mapent *entry,
304803
+		      const char *type, const char *format,
304803
+		      int argc, const char **argv)
304803
+{
304803
+	struct map_source *source = NULL;
304803
+
304803
+	master_source_readlock(entry);
304803
+	source = __master_find_map_source(entry, type, format, argc, argv);
304803
+	if (source)
304803
+		source->ref++;
304803
+	master_source_unlock(entry);
304803
+
304803
+	return source;
304803
+}
304803
+
304803
 static void __master_free_map_source(struct map_source *source, unsigned int free_cache)
304803
 {
304803
+	/* instance map sources are not ref counted */
304803
+	if (source->ref && --source->ref)
304803
+		return;
304803
 	if (source->type)
304803
 		free(source->type);
304803
 	if (source->format)
304803
--- autofs-5.0.7.orig/modules/mount_autofs.c
304803
+++ autofs-5.0.7/modules/mount_autofs.c
304803
@@ -208,18 +208,37 @@ int mount_mount(struct autofs_point *ap,
304803
 	}
304803
 	if (info->map)
304803
 		argv[0] = info->map;
304803
+
304803
+	if (options) {
304803
+		p = options;
304803
+		while ((p = strchr(p, ',')) != NULL) {
304803
+			if (*p == ',') {
304803
+				*p = '\0';
304803
+				p++;
304803
+			}
304803
+			argv[argc++] = p;
304803
+		}
304803
+	}
304803
+	argv[argc] = NULL;
304803
+
304803
 	/*
304803
-	 * If the parent map format is amd and the format isn't
304803
-	 * specified in the map entry set it from the parent map
304803
-	 * source.
304803
+	 * For amd type "auto" the map is often re-used so check
304803
+	 * if the the parent map can be used and use it if it
304803
+	 * matches.
304803
+	 *
304803
+	 * Also if the parent map format is amd and the format
304803
+	 * isn't specified in the map entry set it from the parent
304803
+	 * map source.
304803
 	 */
304803
-	if (!info->format && ap->entry->maps) {
304803
+	source = NULL;
304803
+	if (ap->entry->maps && ap->entry->maps->flags & MAP_FLAG_FORMAT_AMD) {
304803
 		struct map_source *s = ap->entry->maps;
304803
+
304803
 		/*
304803
 		 * For amd maps, if the format and source type aren't
304803
 		 * specified try and set them from the parent.
304803
 		 */
304803
-		if (s->flags & MAP_FLAG_FORMAT_AMD) {
304803
+		if (!info->format) {
304803
 			info->format = strdup("amd");
304803
 			if (!info->format)
304803
 				warn(ap->logopt, MODPREFIX
304803
@@ -231,23 +250,18 @@ int mount_mount(struct autofs_point *ap,
304803
 					     "failed to set amd map type");
304803
 			}
304803
 		}
304803
-	}
304803
 
304803
-	if (options) {
304803
-		p = options;
304803
-		while ((p = strchr(p, ',')) != NULL) {
304803
-			if (*p == ',') {
304803
-				*p = '\0';
304803
-				p++;
304803
-			}
304803
-			argv[argc++] = p;
304803
-		}
304803
+		source = master_get_map_source(ap->entry,
304803
+					       info->type, info->format,
304803
+					       argc, argv);
304803
+		if (source)
304803
+			entry->maps = source;
304803
 	}
304803
-	argv[argc] = NULL;
304803
 
304803
-	source = master_add_map_source(entry,
304803
-				       info->type, info->format,
304803
-				       time(NULL), argc, argv);
304803
+	if (!source)
304803
+		source = master_add_map_source(entry,
304803
+					       info->type, info->format,
304803
+					       time(NULL), argc, argv);
304803
 	if (!source) {
304803
 		error(ap->logopt,
304803
 		      MODPREFIX "failed to add map source to entry");
304803
@@ -256,7 +270,13 @@ int mount_mount(struct autofs_point *ap,
304803
 		return 1;
304803
 	}
304803
 	free_map_type_info(info);
304803
-	source->exp_timeout = timeout;
304803
+	/* The exp_timeout can't be inherited if the map is shared, so
304803
+	 * the autofs point exp_runfreq must be set here.
304803
+	 */
304803
+	if (source->ref <= 1)
304803
+		source->exp_timeout = timeout;
304803
+	else
304803
+		nap->exp_runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO;
304803
 
304803
 	mounts_mutex_lock(ap);
304803