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

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