autofs-5.0.8 - add negative cache lookup to hesiod lookup

From: Ian Kent <raven@themaw.net>

Warning, this is completely untested.

I don't have a hesiod test environment so I can't test this at all.
If we do in fact have hesiod users then I'll need to work with them
to fix any reported problems.
---
 CHANGELOG               |    1 +
 modules/lookup_hesiod.c |   39 ++++++++++++++++++++++++++++++++++++++-
 2 files changed, 39 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG b/CHANGELOG
index b75a603..10a2a68 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -28,6 +28,7 @@
 - dont clobber mapent for negative cache.
 - fix macro_addvar() and move init to main thread.
 - change walk_tree() to take ap.
+- add negative cache lookup to hesiod lookup.
 
 17/10/2013 autofs-5.0.8
 =======================
diff --git a/modules/lookup_hesiod.c b/modules/lookup_hesiod.c
index 0a2ee44..c4f3558 100644
--- a/modules/lookup_hesiod.c
+++ b/modules/lookup_hesiod.c
@@ -99,10 +99,11 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context)
  */
 int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *context)
 {
+	struct lookup_context *ctxt = (struct lookup_context *) context;
 	struct map_source *source;
 	struct mapent_cache *mc;
+	struct mapent *me;
 	char **hes_result;
-	struct lookup_context *ctxt = (struct lookup_context *) context;
 	int status, rv;
 	char **record, *best_record = NULL, *p;
 	int priority, lowest_priority = INT_MAX;	
@@ -117,6 +118,32 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
 	      MODPREFIX "looking up root=\"%s\", name=\"%s\"",
 	      ap->path, name);
 
+	/* Check if we recorded a mount fail for this key anywhere */
+	me = lookup_source_mapent(ap, name, LKP_DISTINCT);
+	if (me) {
+		if (me->status >= time(NULL)) {
+			cache_unlock(me->mc);
+			return NSS_STATUS_NOTFOUND;
+		} else {
+			struct mapent_cache *smc = me->mc;
+			struct mapent *sme;
+
+			if (me->mapent)
+				cache_unlock(smc);
+			else {
+				cache_unlock(smc);
+				cache_writelock(smc);
+				sme = cache_lookup_distinct(smc, name);
+				/* Negative timeout expired for non-existent entry. */
+				if (sme && !sme->mapent) {
+					if (cache_pop_mapent(sme) == CHE_FAIL)
+						cache_delete(smc, name);
+				}
+				cache_unlock(smc);
+			}
+		}
+	}
+
 	chdir("/");		/* If this is not here the filesystem stays
 				   busy, for some reason... */
 
@@ -171,6 +198,16 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
 	if (status)
 		fatal(status);
 
+	if (rv) {
+		/* Don't update negative cache when re-connecting */
+		if (ap->flags & MOUNT_FLAG_REMOUNT)
+			return NSS_STATUS_TRYAGAIN;
+		cache_writelock(mc);
+		cache_update_negative(mc, source, name, ap->negative_timeout);
+		cache_unlock(mc);
+		return NSS_STATUS_TRYAGAIN;
+	}
+
 	/*
 	 * Unavailable due to error such as module load fail 
 	 * or out of memory, etc.
