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

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