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

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