Ian Kent c5187b
autofs-5.0.4 - always read file maps
Ian Kent c5187b
Ian Kent c5187b
From: Ian Kent <raven@themaw.net>
Ian Kent c5187b
Ian Kent c5187b
autofs tries to not load an entire map into the internal cache unless it
Ian Kent c5187b
has to. For maps that do get loaded into the cache it relies on checks to
Ian Kent c5187b
work out if a map is up to date in order to trigger a map read. This is
Ian Kent c5187b
fine for maps that can do direct key lookups but file maps need to do a
Ian Kent c5187b
linear search through the file when locating an entry for a key. For large
Ian Kent c5187b
maps this can be a huge overhead. This patch make autofs always load file
Ian Kent c5187b
based maps at start and makes use of the map file mtime to discover if the
Ian Kent c5187b
cache needs to be refreshed.
Ian Kent c5187b
---
Ian Kent c5187b
Ian Kent c5187b
 CHANGELOG             |    1 +
Ian Kent c5187b
 daemon/lookup.c       |    9 +++++--
Ian Kent c5187b
 modules/lookup_file.c |   65 ++++++++++++++++---------------------------------
Ian Kent c5187b
 3 files changed, 28 insertions(+), 47 deletions(-)
Ian Kent c5187b
Ian Kent c5187b
Ian Kent c5187b
diff --git a/CHANGELOG b/CHANGELOG
Ian Kent c5187b
index d4dd70b..afd1335 100644
Ian Kent c5187b
--- a/CHANGELOG
Ian Kent c5187b
+++ b/CHANGELOG
Ian Kent c5187b
@@ -14,6 +14,7 @@
Ian Kent c5187b
 - check for stale SASL credentials upon connect fail.
Ian Kent c5187b
 - add "forcestart" and "forcerestart" init script options to allow
Ian Kent c5187b
   use of 5.0.3 strartup behavior if required.
Ian Kent c5187b
+- always read entire file map into cache to speed lookups.
Ian Kent c5187b
 
Ian Kent c5187b
 4/11/2008 autofs-5.0.4
Ian Kent c5187b
 -----------------------
Ian Kent c5187b
diff --git a/daemon/lookup.c b/daemon/lookup.c
Ian Kent c5187b
index 741d846..e034348 100644
Ian Kent c5187b
--- a/daemon/lookup.c
Ian Kent c5187b
+++ b/daemon/lookup.c
Ian Kent c5187b
@@ -283,10 +283,13 @@ static int do_read_map(struct autofs_point *ap, struct map_source *map, time_t a
Ian Kent c5187b
 	 * for the fail cases to function correctly and to cache the
Ian Kent c5187b
 	 * lookup handle.
Ian Kent c5187b
 	 *
Ian Kent c5187b
-	 * We always need to whole map for direct mounts in order to
Ian Kent c5187b
-	 * mount the triggers.
Ian Kent c5187b
+	 * We always need to read the whole map for direct mounts in
Ian Kent c5187b
+	 * order to mount the triggers. We also want to read the whole
Ian Kent c5187b
+	 * map if it's a file map to avoid potentially lengthy linear
Ian Kent c5187b
+	 * file scanning.
Ian Kent c5187b
 	 */
Ian Kent c5187b
-	if (!(ap->flags & MOUNT_FLAG_GHOST) && ap->type != LKP_DIRECT)
Ian Kent c5187b
+	if (strcmp(map->type, "file") &&
Ian Kent c5187b
+	    !(ap->flags & MOUNT_FLAG_GHOST) && ap->type != LKP_DIRECT)
Ian Kent c5187b
 		return NSS_STATUS_SUCCESS;
Ian Kent c5187b
 
Ian Kent c5187b
 	if (!map->stale)
Ian Kent c5187b
diff --git a/modules/lookup_file.c b/modules/lookup_file.c
Ian Kent c5187b
index 95b9f6f..aafeb8b 100644
Ian Kent c5187b
--- a/modules/lookup_file.c
Ian Kent c5187b
+++ b/modules/lookup_file.c
Ian Kent c5187b
@@ -44,7 +44,6 @@ typedef enum { esc_none, esc_char, esc_val, esc_all } ESCAPES;
Ian Kent c5187b
 
Ian Kent c5187b
 struct lookup_context {
Ian Kent c5187b
 	const char *mapname;
Ian Kent c5187b
-	time_t mtime;
Ian Kent c5187b
 	struct parse_mod *parse;
Ian Kent c5187b
 };
Ian Kent c5187b
 
Ian Kent c5187b
@@ -54,7 +53,6 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
Ian Kent c5187b
 {
Ian Kent c5187b
 	struct lookup_context *ctxt;
Ian Kent c5187b
 	char buf[MAX_ERR_BUF];
Ian Kent c5187b
-	struct stat st;
Ian Kent c5187b
 
Ian Kent c5187b
 	*context = NULL;
Ian Kent c5187b
 
Ian Kent c5187b
@@ -87,15 +85,6 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
Ian Kent c5187b
 		return 1;
Ian Kent c5187b
 	}
Ian Kent c5187b
 
Ian Kent c5187b
-	if (stat(ctxt->mapname, &st)) {
Ian Kent c5187b
-		free(ctxt);
Ian Kent c5187b
-		logmsg(MODPREFIX "file map %s, could not stat",
Ian Kent c5187b
-		     argv[0]);
Ian Kent c5187b
-		return 1;
Ian Kent c5187b
-	}
Ian Kent c5187b
-		
Ian Kent c5187b
-	ctxt->mtime = st.st_mtime;
Ian Kent c5187b
-
Ian Kent c5187b
 	if (!mapfmt)
Ian Kent c5187b
 		mapfmt = MAPFMT_DEFAULT;
Ian Kent c5187b
 
Ian Kent c5187b
@@ -391,9 +380,7 @@ int lookup_read_master(struct master *master, time_t age, void *context)
Ian Kent c5187b
 	int blen;
Ian Kent c5187b
 	char *path;
Ian Kent c5187b
 	char *ent;
Ian Kent c5187b
-	struct stat st;
Ian Kent c5187b
 	FILE *f;
Ian Kent c5187b
-	int fd;
Ian Kent c5187b
 	unsigned int path_len, ent_len;
Ian Kent c5187b
 	int entry, cur_state;
Ian Kent c5187b
 
Ian Kent c5187b
@@ -428,8 +415,6 @@ int lookup_read_master(struct master *master, time_t age, void *context)
Ian Kent c5187b
 		return NSS_STATUS_UNAVAIL;
Ian Kent c5187b
 	}
Ian Kent c5187b
 
Ian Kent c5187b
-	fd = fileno(f);
Ian Kent c5187b
-
Ian Kent c5187b
 	while(1) {
Ian Kent c5187b
 		entry = read_one(logopt, f, path, &path_len, ent, &ent_len);
Ian Kent c5187b
 		if (!entry) {
Ian Kent c5187b
@@ -504,13 +489,6 @@ int lookup_read_master(struct master *master, time_t age, void *context)
Ian Kent c5187b
 			break;
Ian Kent c5187b
 	}
Ian Kent c5187b
 
Ian Kent c5187b
-	if (fstat(fd, &st)) {
Ian Kent c5187b
-		crit(logopt, MODPREFIX "file map %s, could not stat",
Ian Kent c5187b
-		       ctxt->mapname);
Ian Kent c5187b
-		return NSS_STATUS_UNAVAIL;
Ian Kent c5187b
-	}
Ian Kent c5187b
-	ctxt->mtime = st.st_mtime;
Ian Kent c5187b
-
Ian Kent c5187b
 	fclose(f);
Ian Kent c5187b
 
Ian Kent c5187b
 	return NSS_STATUS_SUCCESS;
Ian Kent c5187b
@@ -642,9 +620,7 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context)
Ian Kent c5187b
 	struct mapent_cache *mc;
Ian Kent c5187b
 	char *key;
Ian Kent c5187b
 	char *mapent;
Ian Kent c5187b
-	struct stat st;
Ian Kent c5187b
 	FILE *f;
Ian Kent c5187b
-	int fd;
Ian Kent c5187b
 	unsigned int k_len, m_len;
Ian Kent c5187b
 	int entry;
Ian Kent c5187b
 
Ian Kent c5187b
@@ -684,8 +660,6 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context)
Ian Kent c5187b
 		return NSS_STATUS_UNAVAIL;
Ian Kent c5187b
 	}
Ian Kent c5187b
 
Ian Kent c5187b
-	fd = fileno(f);
Ian Kent c5187b
-
Ian Kent c5187b
 	while(1) {
Ian Kent c5187b
 		entry = read_one(ap->logopt, f, key, &k_len, mapent, &m_len);
Ian Kent c5187b
 		if (!entry) {
Ian Kent c5187b
@@ -748,13 +722,6 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context)
Ian Kent c5187b
 			break;
Ian Kent c5187b
 	}
Ian Kent c5187b
 
Ian Kent c5187b
-	if (fstat(fd, &st)) {
Ian Kent c5187b
-		crit(ap->logopt,
Ian Kent c5187b
-		     MODPREFIX "file map %s, could not stat",
Ian Kent c5187b
-		     ctxt->mapname);
Ian Kent c5187b
-		return NSS_STATUS_UNAVAIL;
Ian Kent c5187b
-	}
Ian Kent c5187b
-	ctxt->mtime = st.st_mtime;
Ian Kent c5187b
 	source->age = age;
Ian Kent c5187b
 
Ian Kent c5187b
 	fclose(f);
Ian Kent c5187b
@@ -951,9 +918,6 @@ static int check_map_indirect(struct autofs_point *ap,
Ian Kent c5187b
 	if (ret == CHE_FAIL)
Ian Kent c5187b
 		return NSS_STATUS_NOTFOUND;
Ian Kent c5187b
 
Ian Kent c5187b
-	if (ret & CHE_UPDATED)
Ian Kent c5187b
-		source->stale = 1;
Ian Kent c5187b
-
Ian Kent c5187b
 	pthread_cleanup_push(cache_lock_cleanup, mc);
Ian Kent c5187b
 	cache_writelock(mc);
Ian Kent c5187b
 	exists = cache_lookup_distinct(mc, key);
Ian Kent c5187b
@@ -963,7 +927,6 @@ static int check_map_indirect(struct autofs_point *ap,
Ian Kent c5187b
 			free(exists->mapent);
Ian Kent c5187b
 			exists->mapent = NULL;
Ian Kent c5187b
 			exists->status = 0;
Ian Kent c5187b
-			source->stale = 1;
Ian Kent c5187b
 		}
Ian Kent c5187b
 	}
Ian Kent c5187b
 	pthread_cleanup_pop(1);
Ian Kent c5187b
@@ -985,14 +948,8 @@ static int check_map_indirect(struct autofs_point *ap,
Ian Kent c5187b
 		we = cache_lookup_distinct(mc, "*");
Ian Kent c5187b
 		if (we) {
Ian Kent c5187b
 			/* Wildcard entry existed and is now gone */
Ian Kent c5187b
-			if (we->source == source && (wild & CHE_MISSING)) {
Ian Kent c5187b
+			if (we->source == source && (wild & CHE_MISSING))
Ian Kent c5187b
 				cache_delete(mc, "*");
Ian Kent c5187b
-				source->stale = 1;
Ian Kent c5187b
-			}
Ian Kent c5187b
-		} else {
Ian Kent c5187b
-			/* Wildcard not in map but now is */
Ian Kent c5187b
-			if (wild & (CHE_OK | CHE_UPDATED))
Ian Kent c5187b
-				source->stale = 1;
Ian Kent c5187b
 		}
Ian Kent c5187b
 		pthread_cleanup_pop(1);
Ian Kent c5187b
 
Ian Kent c5187b
@@ -1062,9 +1019,28 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
Ian Kent c5187b
 	 * we never know about it.
Ian Kent c5187b
 	 */
Ian Kent c5187b
 	if (ap->type == LKP_INDIRECT && *key != '/') {
Ian Kent c5187b
+		struct stat st;
Ian Kent c5187b
 		char *lkp_key;
Ian Kent c5187b
 
Ian Kent c5187b
+		/*
Ian Kent c5187b
+		 * We can skip the map lookup and cache update altogether
Ian Kent c5187b
+		 * if we know the map hasn't been modified since it was
Ian Kent c5187b
+		 * last read. If it has then we can mark the map stale
Ian Kent c5187b
+		 * so a re-read is triggered following the lookup.
Ian Kent c5187b
+		 */
Ian Kent c5187b
+		if (stat(ctxt->mapname, &st)) {
Ian Kent c5187b
+			error(ap->logopt, MODPREFIX
Ian Kent c5187b
+			      "file map %s, could not stat", ctxt->mapname);
Ian Kent c5187b
+			return NSS_STATUS_UNAVAIL;
Ian Kent c5187b
+		}
Ian Kent c5187b
+
Ian Kent c5187b
 		cache_readlock(mc);
Ian Kent c5187b
+		me = cache_lookup_first(mc);
Ian Kent c5187b
+		if (me && st.st_mtime <= me->age)
Ian Kent c5187b
+			goto do_cache_lookup;
Ian Kent c5187b
+		else
Ian Kent c5187b
+			source->stale = 1;
Ian Kent c5187b
+
Ian Kent c5187b
 		me = cache_lookup_distinct(mc, key);
Ian Kent c5187b
 		if (me && me->multi)
Ian Kent c5187b
 			lkp_key = strdup(me->multi->key);
Ian Kent c5187b
@@ -1088,6 +1064,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
Ian Kent c5187b
 	}
Ian Kent c5187b
 
Ian Kent c5187b
 	cache_readlock(mc);
Ian Kent c5187b
+do_cache_lookup:
Ian Kent c5187b
 	me = cache_lookup(mc, key);
Ian Kent c5187b
 	/* Stale mapent => check for entry in alternate source or wildcard */
Ian Kent c5187b
 	if (me && !me->mapent) {