Blame SOURCES/autofs-5.0.8-dont-clobber-mapent-for-negative-cache.patch

4d476f
autofs-5.0.8 - dont clobber mapent for negative cache
4d476f
4d476f
From: Ian Kent <raven@themaw.net>
4d476f
4d476f
When negative caching a map entry on mount fail don't save the mapent
4d476f
and restore it when the negative cache timeout expires.
4d476f
4d476f
Deleting the mapent, as is done now, can be expensive especially when
4d476f
it causes a file read for a large file map.
4d476f
---
4d476f
 daemon/lookup.c          |    6 ++-
4d476f
 include/automount.h      |    9 ++++
4d476f
 lib/cache.c              |   85 ++++++++++++++++++++++++++++++++++++++++++++++-
4d476f
 modules/lookup_file.c    |    6 ++-
4d476f
 modules/lookup_hosts.c   |   10 +++--
4d476f
 modules/lookup_ldap.c    |    6 ++-
4d476f
 modules/lookup_nisplus.c |   10 +++--
4d476f
 modules/lookup_program.c |   10 +++--
4d476f
 modules/lookup_sss.c     |    6 ++-
4d476f
 modules/lookup_yp.c      |    6 ++-
4d476f
 10 files changed, 135 insertions(+), 19 deletions(-)
4d476f
4d476f
--- autofs-5.0.7.orig/daemon/lookup.c
4d476f
+++ autofs-5.0.7/daemon/lookup.c
4d476f
@@ -860,7 +860,11 @@ static void update_negative_cache(struct
4d476f
 			int rv = CHE_FAIL;
4d476f
 
4d476f
 			cache_writelock(map->mc);
4d476f
-			rv = cache_update(map->mc, map, name, NULL, now);
4d476f
+			me = cache_lookup_distinct(map->mc, name);
4d476f
+			if (me)
4d476f
+				rv = cache_push_mapent(me, NULL);
4d476f
+			else
4d476f
+				rv = cache_update(map->mc, map, name, NULL, now);
4d476f
 			if (rv != CHE_FAIL) {
4d476f
 				me = cache_lookup_distinct(map->mc, name);
4d476f
 				me->status = now + ap->negative_timeout;
4d476f
--- autofs-5.0.7.orig/include/automount.h
4d476f
+++ autofs-5.0.7/include/automount.h
4d476f
@@ -146,6 +146,12 @@ struct mapent_cache {
4d476f
 	struct mapent **hash;
4d476f
 };
4d476f
 
4d476f
+struct stack {
4d476f
+	char *mapent;
4d476f
+	time_t age;
4d476f
+	struct stack *next;
4d476f
+};
4d476f
+
4d476f
 struct mapent {
4d476f
 	struct mapent *next;
4d476f
 	struct list_head ino_index;
4d476f
@@ -159,6 +165,7 @@ struct mapent {
4d476f
 	struct mapent *parent;
4d476f
 	char *key;
4d476f
 	char *mapent;
4d476f
+	struct stack *stack;
4d476f
 	time_t age;
4d476f
 	/* Time of last mount fail */
4d476f
 	time_t status;
4d476f
@@ -175,6 +182,8 @@ void cache_readlock(struct mapent_cache
4d476f
 void cache_writelock(struct mapent_cache *mc);
4d476f
 int cache_try_writelock(struct mapent_cache *mc);
4d476f
 void cache_unlock(struct mapent_cache *mc);
4d476f
+int cache_push_mapent(struct mapent *me, char *mapent);
4d476f
+int cache_pop_mapent(struct mapent *me);
4d476f
 struct mapent_cache *cache_init(struct autofs_point *ap, struct map_source *map);
4d476f
 struct mapent_cache *cache_init_null_cache(struct master *master);
4d476f
 int cache_set_ino_index(struct mapent_cache *mc, const char *key, dev_t dev, ino_t ino);
4d476f
--- autofs-5.0.7.orig/lib/cache.c
4d476f
+++ autofs-5.0.7/lib/cache.c
4d476f
@@ -177,6 +177,69 @@ static inline void ino_index_unlock(stru
4d476f
 	return;
4d476f
 }
4d476f
 
4d476f
+/* Save the cache entry mapent field onto a stack and set a new mapent */
4d476f
+int cache_push_mapent(struct mapent *me, char *mapent)
4d476f
+{
4d476f
+	struct stack *s;
4d476f
+	char *new;
4d476f
+
4d476f
+	if (!me->mapent)
4d476f
+		return CHE_FAIL;
4d476f
+
4d476f
+	if (!mapent)
4d476f
+		new = NULL;
4d476f
+	else {
4d476f
+		new = strdup(mapent);
4d476f
+		if (!new)
4d476f
+			return CHE_FAIL;
4d476f
+	}
4d476f
+
4d476f
+	s = malloc(sizeof(struct stack));
4d476f
+	if (!s) {
4d476f
+		if (new)
4d476f
+			free(new);
4d476f
+		return CHE_FAIL;
4d476f
+	}
4d476f
+	memset(s, 0, sizeof(*s));
4d476f
+
4d476f
+	s->mapent = me->mapent;
4d476f
+	s->age = me->age;
4d476f
+	me->mapent = mapent;
4d476f
+
4d476f
+	if (me->stack)
4d476f
+		s->next = me->stack;
4d476f
+	me->stack = s;
4d476f
+
4d476f
+	return CHE_OK;
4d476f
+}
4d476f
+
4d476f
+/* Restore cache entry mapent to a previously saved mapent, discard current */
4d476f
+int cache_pop_mapent(struct mapent *me)
4d476f
+{
4d476f
+	struct stack *s = me->stack;
4d476f
+	char *mapent;
4d476f
+	time_t age;
4d476f
+
4d476f
+	if (!s || !s->mapent)
4d476f
+		return CHE_FAIL;
4d476f
+
4d476f
+	mapent = s->mapent;
4d476f
+	age = s->age;
4d476f
+	me->stack = s->next;
4d476f
+	free(s);
4d476f
+
4d476f
+	if (age < me->age) {
4d476f
+		free(mapent);
4d476f
+		return CHE_OK;
4d476f
+	}
4d476f
+
4d476f
+	if (me->mapent)
4d476f
+		free(me->mapent);
4d476f
+	me->mapent = mapent;
4d476f
+
4d476f
+	return CHE_OK;
4d476f
+}
4d476f
+
4d476f
 struct mapent_cache *cache_init(struct autofs_point *ap, struct map_source *map)
4d476f
 {
4d476f
 	struct mapent_cache *mc;
4d476f
@@ -578,6 +641,8 @@ int cache_add(struct mapent_cache *mc, s
4d476f
 	} else
4d476f
 		me->mapent = NULL;
4d476f
 
4d476f
+	me->stack = NULL;
4d476f
+
4d476f
 	me->age = age;
4d476f
 	me->status = 0;
4d476f
 	me->mc = mc;
4d476f
@@ -689,7 +754,9 @@ void cache_update_negative(struct mapent
4d476f
 	int rv = CHE_OK;
4d476f
 
4d476f
 	me = cache_lookup_distinct(mc, key);
4d476f
-	if (!me)
4d476f
+	if (me)
4d476f
+		rv = cache_push_mapent(me, NULL);
4d476f
+	else
4d476f
 		rv = cache_update(mc, ms, key, NULL, now);
4d476f
 	if (rv != CHE_FAIL) {
4d476f
 		me = cache_lookup_distinct(mc, key);
4d476f
@@ -858,6 +925,7 @@ int cache_delete(struct mapent_cache *mc
4d476f
 		pred = me;
4d476f
 		me = me->next;
4d476f
 		if (strcmp(this, me->key) == 0) {
4d476f
+			struct stack *s = me->stack;
4d476f
 			if (me->multi && !list_empty(&me->multi_list)) {
4d476f
 				ret = CHE_FAIL;
4d476f
 				goto done;
4d476f
@@ -872,6 +940,13 @@ int cache_delete(struct mapent_cache *mc
4d476f
 			free(me->key);
4d476f
 			if (me->mapent)
4d476f
 				free(me->mapent);
4d476f
+			while (s) {
4d476f
+				struct stack *next = s->next;
4d476f
+				if (s->mapent)
4d476f
+					free(s->mapent);
4d476f
+				free(s);
4d476f
+				s = next;
4d476f
+			}
4d476f
 			free(me);
4d476f
 			me = pred;
4d476f
 		}
4d476f
@@ -882,6 +957,7 @@ int cache_delete(struct mapent_cache *mc
4d476f
 		goto done;
4d476f
 
4d476f
 	if (strcmp(this, me->key) == 0) {
4d476f
+		struct stack *s = me->stack;
4d476f
 		if (me->multi && !list_empty(&me->multi_list)) {
4d476f
 			ret = CHE_FAIL;
4d476f
 			goto done;
4d476f
@@ -896,6 +972,13 @@ int cache_delete(struct mapent_cache *mc
4d476f
 		free(me->key);
4d476f
 		if (me->mapent)
4d476f
 			free(me->mapent);
4d476f
+		while (s) {
4d476f
+			struct stack *next = s->next;
4d476f
+			if (s->mapent)
4d476f
+				free(s->mapent);
4d476f
+			free(s);
4d476f
+			s = next;
4d476f
+		}
4d476f
 		free(me);
4d476f
 	}
4d476f
 done:
4d476f
--- autofs-5.0.7.orig/modules/lookup_file.c
4d476f
+++ autofs-5.0.7/modules/lookup_file.c
4d476f
@@ -988,8 +988,10 @@ int lookup_mount(struct autofs_point *ap
4d476f
 				cache_writelock(smc);
4d476f
 				sme = cache_lookup_distinct(smc, key);
4d476f
 				/* Negative timeout expired for non-existent entry. */
4d476f
-				if (sme && !sme->mapent)
4d476f
-					cache_delete(smc, key);
4d476f
+				if (sme && !sme->mapent) {
4d476f
+					if (cache_pop_mapent(sme) == CHE_FAIL)
4d476f
+						cache_delete(smc, key);
4d476f
+				}
4d476f
 				cache_unlock(smc);
4d476f
 			}
4d476f
 		}
4d476f
--- autofs-5.0.7.orig/modules/lookup_hosts.c
4d476f
+++ autofs-5.0.7/modules/lookup_hosts.c
4d476f
@@ -155,7 +155,9 @@ static int do_parse_mount(struct autofs_
4d476f
 
4d476f
 		cache_writelock(mc);
4d476f
 		me = cache_lookup_distinct(mc, name);
4d476f
-		if (!me)
4d476f
+		if (me)
4d476f
+			rv = cache_push_mapent(me, NULL);
4d476f
+		else
4d476f
 			rv = cache_update(mc, source, name, NULL, now);
4d476f
 		if (rv != CHE_FAIL) {
4d476f
 			me = cache_lookup_distinct(mc, name);
4d476f
@@ -315,8 +317,10 @@ int lookup_mount(struct autofs_point *ap
4d476f
 				cache_writelock(smc);
4d476f
 				sme = cache_lookup_distinct(smc, name);
4d476f
 				/* Negative timeout expired for non-existent entry. */
4d476f
-				if (sme && !sme->mapent)
4d476f
-					cache_delete(smc, name);
4d476f
+				if (sme && !sme->mapent) {
4d476f
+					if (cache_pop_mapent(sme) == CHE_FAIL)
4d476f
+						cache_delete(smc, name);
4d476f
+				}
4d476f
 				cache_unlock(smc);
4d476f
 			}
4d476f
 		}
4d476f
--- autofs-5.0.7.orig/modules/lookup_ldap.c
4d476f
+++ autofs-5.0.7/modules/lookup_ldap.c
4d476f
@@ -2937,8 +2937,10 @@ int lookup_mount(struct autofs_point *ap
4d476f
 				cache_writelock(smc);
4d476f
 				sme = cache_lookup_distinct(smc, key);
4d476f
 				/* Negative timeout expired for non-existent entry. */
4d476f
-				if (sme && !sme->mapent)
4d476f
-					cache_delete(smc, key);
4d476f
+				if (sme && !sme->mapent) {
4d476f
+					if (cache_pop_mapent(sme) == CHE_FAIL)
4d476f
+						cache_delete(smc, key);
4d476f
+				}
4d476f
 				cache_unlock(smc);
4d476f
 			}
4d476f
 		}
4d476f
--- autofs-5.0.7.orig/modules/lookup_nisplus.c
4d476f
+++ autofs-5.0.7/modules/lookup_nisplus.c
4d476f
@@ -509,8 +509,10 @@ int lookup_mount(struct autofs_point *ap
4d476f
 				cache_writelock(smc);
4d476f
 				sme = cache_lookup_distinct(smc, key);
4d476f
 				/* Negative timeout expired for non-existent entry. */
4d476f
-				if (sme && !sme->mapent)
4d476f
-					cache_delete(smc, key);
4d476f
+				if (sme && !sme->mapent) {
4d476f
+					if (cache_pop_mapent(sme) == CHE_FAIL)
4d476f
+						cache_delete(smc, key);
4d476f
+				}
4d476f
 				cache_unlock(smc);
4d476f
 			}
4d476f
 		}
4d476f
@@ -602,7 +604,9 @@ int lookup_mount(struct autofs_point *ap
4d476f
 			return NSS_STATUS_TRYAGAIN;
4d476f
 		cache_writelock(mc);
4d476f
 		me = cache_lookup_distinct(mc, key);
4d476f
-		if (!me)
4d476f
+		if (me)
4d476f
+			rv = cache_push_mapent(me, NULL);
4d476f
+		else
4d476f
 			rv = cache_update(mc, source, key, NULL, now);
4d476f
 		if (rv != CHE_FAIL) {
4d476f
 			me = cache_lookup_distinct(mc, key);
4d476f
--- autofs-5.0.7.orig/modules/lookup_program.c
4d476f
+++ autofs-5.0.7/modules/lookup_program.c
4d476f
@@ -156,8 +156,10 @@ int lookup_mount(struct autofs_point *ap
4d476f
 				cache_writelock(smc);
4d476f
 				sme = cache_lookup_distinct(smc, name);
4d476f
 				/* Negative timeout expired for non-existent entry. */
4d476f
-				if (sme && !sme->mapent)
4d476f
-					cache_delete(smc, name);
4d476f
+				if (sme && !sme->mapent) {
4d476f
+					if (cache_pop_mapent(sme) == CHE_FAIL)
4d476f
+						cache_delete(smc, name);
4d476f
+				}
4d476f
 				cache_unlock(smc);
4d476f
 			}
4d476f
 		}
4d476f
@@ -451,7 +453,9 @@ out_free:
4d476f
 
4d476f
 		cache_writelock(mc);
4d476f
 		me = cache_lookup_distinct(mc, name);
4d476f
-		if (!me)
4d476f
+		if (me)
4d476f
+			rv = cache_push_mapent(me, NULL);
4d476f
+		else
4d476f
 			rv = cache_update(mc, source, name, NULL, now);
4d476f
 		if (rv != CHE_FAIL) {
4d476f
 			me = cache_lookup_distinct(mc, name);
4d476f
--- autofs-5.0.7.orig/modules/lookup_sss.c
4d476f
+++ autofs-5.0.7/modules/lookup_sss.c
4d476f
@@ -599,8 +599,10 @@ int lookup_mount(struct autofs_point *ap
4d476f
 				cache_writelock(smc);
4d476f
 				sme = cache_lookup_distinct(smc, key);
4d476f
 				/* Negative timeout expired for non-existent entry. */
4d476f
-				if (sme && !sme->mapent)
4d476f
-					cache_delete(smc, key);
4d476f
+				if (sme && !sme->mapent) {
4d476f
+					if (cache_pop_mapent(sme) == CHE_FAIL)
4d476f
+						cache_delete(smc, key);
4d476f
+				}
4d476f
 				cache_unlock(smc);
4d476f
 			}
4d476f
 		}
4d476f
--- autofs-5.0.7.orig/modules/lookup_yp.c
4d476f
+++ autofs-5.0.7/modules/lookup_yp.c
4d476f
@@ -613,8 +613,10 @@ int lookup_mount(struct autofs_point *ap
4d476f
 				cache_writelock(smc);
4d476f
 				sme = cache_lookup_distinct(smc, key);
4d476f
 				/* Negative timeout expired for non-existent entry. */
4d476f
-				if (sme && !sme->mapent)
4d476f
-					cache_delete(smc, key);
4d476f
+				if (sme && !sme->mapent) {
4d476f
+					if (cache_pop_mapent(sme) == CHE_FAIL)
4d476f
+						cache_delete(smc, key);
4d476f
+				}
4d476f
 				cache_unlock(smc);
4d476f
 			}
4d476f
 		}