Ian Kent cc4062
autofs-5.0.5 - fix remount locking
Ian Kent cc4062
Ian Kent cc4062
From: Ian Kent <raven@themaw.net>
Ian Kent cc4062
Ian Kent cc4062
When autofs is restarted with active mounts it is possible, due
Ian Kent cc4062
to possible recursion when mounting multi-mount map entries, that
Ian Kent cc4062
a lookup module will take a write lock on the map entry cache
Ian Kent cc4062
when a read lock is alreay held.
Ian Kent cc4062
Ian Kent cc4062
Since, during the re-mount, we are still essentially running
Ian Kent cc4062
single threaded we need only take care to ensure we don't take
Ian Kent cc4062
the write lock.
Ian Kent cc4062
---
Ian Kent cc4062
Ian Kent cc4062
 CHANGELOG                |    1 +
Ian Kent cc4062
 modules/lookup_file.c    |   27 +++++++++++++++++----------
Ian Kent cc4062
 modules/lookup_hosts.c   |   24 +++++++++++++++---------
Ian Kent cc4062
 modules/lookup_ldap.c    |   24 ++++++++++++++++--------
Ian Kent cc4062
 modules/lookup_nisplus.c |   29 ++++++++++++++++++-----------
Ian Kent cc4062
 modules/lookup_program.c |   29 +++++++++++++++++++++--------
Ian Kent cc4062
 modules/lookup_yp.c      |   27 +++++++++++++++++----------
Ian Kent cc4062
 7 files changed, 105 insertions(+), 56 deletions(-)
Ian Kent cc4062
Ian Kent cc4062
Ian Kent cc4062
--- autofs-5.0.5.orig/CHANGELOG
Ian Kent cc4062
+++ autofs-5.0.5/CHANGELOG
Ian Kent cc4062
@@ -33,6 +33,7 @@
Ian Kent cc4062
 - fix random selection for host on different network.
Ian Kent cc4062
 - make redhat init script more lsb compliant.
Ian Kent cc4062
 - don't hold lock for simple mounts.
Ian Kent cc4062
+- fix remount locking.
Ian Kent cc4062
 
Ian Kent cc4062
 03/09/2009 autofs-5.0.5
Ian Kent cc4062
 -----------------------
Ian Kent cc4062
--- autofs-5.0.5.orig/modules/lookup_file.c
Ian Kent cc4062
+++ autofs-5.0.5/modules/lookup_file.c
Ian Kent cc4062
@@ -871,7 +871,6 @@ static int check_map_indirect(struct aut
Ian Kent cc4062
 	if (ret == CHE_FAIL)
Ian Kent cc4062
 		return NSS_STATUS_NOTFOUND;
Ian Kent cc4062
 
Ian Kent cc4062
-	pthread_cleanup_push(cache_lock_cleanup, mc);
Ian Kent cc4062
 	cache_writelock(mc);
Ian Kent cc4062
 	exists = cache_lookup_distinct(mc, key);
Ian Kent cc4062
 	/* Not found in the map but found in the cache */
Ian Kent cc4062
@@ -882,7 +881,7 @@ static int check_map_indirect(struct aut
Ian Kent cc4062
 			exists->status = 0;
Ian Kent cc4062
 		}
Ian Kent cc4062
 	}
Ian Kent cc4062
-	pthread_cleanup_pop(1);
Ian Kent cc4062
+	cache_unlock(mc);
Ian Kent cc4062
 
Ian Kent cc4062
 	if (ret == CHE_MISSING) {
Ian Kent cc4062
 		struct mapent *we;
Ian Kent cc4062
@@ -896,7 +895,6 @@ static int check_map_indirect(struct aut
Ian Kent cc4062
 		 * Check for map change and update as needed for
Ian Kent cc4062
 		 * following cache lookup.
Ian Kent cc4062
 		 */
Ian Kent cc4062
-		pthread_cleanup_push(cache_lock_cleanup, mc);
Ian Kent cc4062
 		cache_writelock(mc);
Ian Kent cc4062
 		we = cache_lookup_distinct(mc, "*");
Ian Kent cc4062
 		if (we) {
Ian Kent cc4062
@@ -904,7 +902,7 @@ static int check_map_indirect(struct aut
Ian Kent cc4062
 			if (we->source == source && (wild & CHE_MISSING))
Ian Kent cc4062
 				cache_delete(mc, "*");
Ian Kent cc4062
 		}
Ian Kent cc4062
-		pthread_cleanup_pop(1);
Ian Kent cc4062
+		cache_unlock(mc);
Ian Kent cc4062
 
Ian Kent cc4062
 		if (wild & (CHE_OK | CHE_UPDATED))
Ian Kent cc4062
 			return NSS_STATUS_SUCCESS;
Ian Kent cc4062
@@ -957,13 +955,22 @@ int lookup_mount(struct autofs_point *ap
Ian Kent cc4062
 		if (me->status >= time(NULL)) {
Ian Kent cc4062
 			cache_unlock(me->mc);
Ian Kent cc4062
 			return NSS_STATUS_NOTFOUND;
Ian Kent cc4062
+		} else {
Ian Kent cc4062
+			struct mapent_cache *smc = me->mc;
Ian Kent cc4062
+			struct mapent *sme;
Ian Kent cc4062
+
Ian Kent cc4062
+			if (me->mapent)
Ian Kent cc4062
+				cache_unlock(smc);
Ian Kent cc4062
+			else {
Ian Kent cc4062
+				cache_unlock(smc);
Ian Kent cc4062
+				cache_writelock(smc);
Ian Kent cc4062
+				sme = cache_lookup_distinct(smc, key);
Ian Kent cc4062
+				/* Negative timeout expired for non-existent entry. */
Ian Kent cc4062
+				if (sme && !sme->mapent)
Ian Kent cc4062
+					cache_delete(smc, key);
Ian Kent cc4062
+				cache_unlock(smc);
Ian Kent cc4062
+			}
Ian Kent cc4062
 		}
Ian Kent cc4062
-
Ian Kent cc4062
-		/* Negative timeout expired for non-existent entry. */
Ian Kent cc4062
-		if (!me->mapent)
Ian Kent cc4062
-			cache_delete(me->mc, key);
Ian Kent cc4062
-
Ian Kent cc4062
-		cache_unlock(me->mc);
Ian Kent cc4062
 	}
Ian Kent cc4062
 
Ian Kent cc4062
 	/*
Ian Kent cc4062
--- autofs-5.0.5.orig/modules/lookup_hosts.c
Ian Kent cc4062
+++ autofs-5.0.5/modules/lookup_hosts.c
Ian Kent cc4062
@@ -146,19 +146,25 @@ int lookup_mount(struct autofs_point *ap
Ian Kent cc4062
 	/* Check if we recorded a mount fail for this key anywhere */
Ian Kent cc4062
 	me = lookup_source_mapent(ap, name, LKP_DISTINCT);
Ian Kent cc4062
 	if (me) {
Ian Kent cc4062
-		struct mapent_cache *fmc = me->mc;
Ian Kent cc4062
-
Ian Kent cc4062
 		if (me->status >= time(NULL)) {
Ian Kent cc4062
-			cache_unlock(fmc);
Ian Kent cc4062
+			cache_unlock(me->mc);
Ian Kent cc4062
 			return NSS_STATUS_NOTFOUND;
Ian Kent cc4062
-		}
Ian Kent cc4062
+		} else {
Ian Kent cc4062
+			struct mapent_cache *smc = me->mc;
Ian Kent cc4062
+			struct mapent *sme;
Ian Kent cc4062
 
Ian Kent cc4062
-		if (!me->mapent) {
Ian Kent cc4062
-			cache_delete(fmc, name);
Ian Kent cc4062
-			me = NULL;
Ian Kent cc4062
+			if (me->mapent)
Ian Kent cc4062
+				cache_unlock(smc);
Ian Kent cc4062
+			else {
Ian Kent cc4062
+				cache_unlock(smc);
Ian Kent cc4062
+				cache_writelock(smc);
Ian Kent cc4062
+				sme = cache_lookup_distinct(smc, name);
Ian Kent cc4062
+				/* Negative timeout expired for non-existent entry. */
Ian Kent cc4062
+				if (sme && !sme->mapent)
Ian Kent cc4062
+					cache_delete(smc, name);
Ian Kent cc4062
+				cache_unlock(smc);
Ian Kent cc4062
+			}
Ian Kent cc4062
 		}
Ian Kent cc4062
-
Ian Kent cc4062
-		cache_unlock(fmc);
Ian Kent cc4062
 	}
Ian Kent cc4062
 
Ian Kent cc4062
 	cache_readlock(mc);
Ian Kent cc4062
--- autofs-5.0.5.orig/modules/lookup_ldap.c
Ian Kent cc4062
+++ autofs-5.0.5/modules/lookup_ldap.c
Ian Kent cc4062
@@ -2681,7 +2681,6 @@ next:
Ian Kent cc4062
 	unbind_ldap_connection(ap->logopt, ldap, ctxt);
Ian Kent cc4062
 
Ian Kent cc4062
 	/* Failed to find wild entry, update cache if needed */
Ian Kent cc4062
-	pthread_cleanup_push(cache_lock_cleanup, mc);
Ian Kent cc4062
 	cache_writelock(mc);
Ian Kent cc4062
 	we = cache_lookup_distinct(mc, "*");
Ian Kent cc4062
 	if (we) {
Ian Kent cc4062
@@ -2707,7 +2706,7 @@ next:
Ian Kent cc4062
 			}
Ian Kent cc4062
 		}
Ian Kent cc4062
 	}
Ian Kent cc4062
-	pthread_cleanup_pop(1);
Ian Kent cc4062
+	cache_unlock(mc);
Ian Kent cc4062
 	free(query);
Ian Kent cc4062
 
Ian Kent cc4062
 	return ret;
Ian Kent cc4062
@@ -2817,13 +2816,22 @@ int lookup_mount(struct autofs_point *ap
Ian Kent cc4062
 		if (me->status >= time(NULL)) {
Ian Kent cc4062
 			cache_unlock(me->mc);
Ian Kent cc4062
 			return NSS_STATUS_NOTFOUND;
Ian Kent cc4062
+		} else {
Ian Kent cc4062
+			struct mapent_cache *smc = me->mc;
Ian Kent cc4062
+			struct mapent *sme;
Ian Kent cc4062
+
Ian Kent cc4062
+			if (me->mapent)
Ian Kent cc4062
+				cache_unlock(smc);
Ian Kent cc4062
+			else {
Ian Kent cc4062
+				cache_unlock(smc);
Ian Kent cc4062
+				cache_writelock(smc);
Ian Kent cc4062
+				sme = cache_lookup_distinct(smc, key);
Ian Kent cc4062
+				/* Negative timeout expired for non-existent entry. */
Ian Kent cc4062
+				if (sme && !sme->mapent)
Ian Kent cc4062
+					cache_delete(smc, key);
Ian Kent cc4062
+				cache_unlock(smc);
Ian Kent cc4062
+			}
Ian Kent cc4062
 		}
Ian Kent cc4062
-
Ian Kent cc4062
-		/* Negative timeout expired for non-existent entry. */
Ian Kent cc4062
-		if (!me->mapent)
Ian Kent cc4062
-			cache_delete(me->mc, key);
Ian Kent cc4062
-
Ian Kent cc4062
-		cache_unlock(me->mc);
Ian Kent cc4062
 	}
Ian Kent cc4062
 
Ian Kent cc4062
         /*
Ian Kent cc4062
--- autofs-5.0.5.orig/modules/lookup_nisplus.c
Ian Kent cc4062
+++ autofs-5.0.5/modules/lookup_nisplus.c
Ian Kent cc4062
@@ -421,7 +421,6 @@ static int check_map_indirect(struct aut
Ian Kent cc4062
 		return NSS_STATUS_UNAVAIL;
Ian Kent cc4062
 	}
Ian Kent cc4062
 
Ian Kent cc4062
-	pthread_cleanup_push(cache_lock_cleanup, mc);
Ian Kent cc4062
 	cache_writelock(mc);
Ian Kent cc4062
 	t_last_read = ap->exp_runfreq + 1;
Ian Kent cc4062
 	me = cache_lookup_first(mc);
Ian Kent cc4062
@@ -442,8 +441,8 @@ static int check_map_indirect(struct aut
Ian Kent cc4062
 			exists->status = 0;
Ian Kent cc4062
 		}
Ian Kent cc4062
 	}
Ian Kent cc4062
-	pthread_cleanup_pop(1);
Ian Kent cc4062
-	
Ian Kent cc4062
+	cache_unlock(mc);
Ian Kent cc4062
+
Ian Kent cc4062
 	if (t_last_read > ap->exp_runfreq && ret & CHE_UPDATED)
Ian Kent cc4062
 		source->stale = 1;
Ian Kent cc4062
 
Ian Kent cc4062
@@ -459,7 +458,6 @@ static int check_map_indirect(struct aut
Ian Kent cc4062
 		 * Check for map change and update as needed for
Ian Kent cc4062
 		 * following cache lookup.
Ian Kent cc4062
 		*/
Ian Kent cc4062
-		pthread_cleanup_push(cache_lock_cleanup, mc);
Ian Kent cc4062
 		cache_writelock(mc);
Ian Kent cc4062
 		we = cache_lookup_distinct(mc, "*");
Ian Kent cc4062
 		if (we) {
Ian Kent cc4062
@@ -473,7 +471,7 @@ static int check_map_indirect(struct aut
Ian Kent cc4062
 			if (wild & (CHE_OK | CHE_UPDATED))
Ian Kent cc4062
 				source->stale = 1;
Ian Kent cc4062
 		}
Ian Kent cc4062
-		pthread_cleanup_pop(1);
Ian Kent cc4062
+		cache_unlock(mc);
Ian Kent cc4062
 
Ian Kent cc4062
 		if (wild & (CHE_UPDATED | CHE_OK))
Ian Kent cc4062
 			return NSS_STATUS_SUCCESS;
Ian Kent cc4062
@@ -516,13 +514,22 @@ int lookup_mount(struct autofs_point *ap
Ian Kent cc4062
 		if (me->status >= time(NULL)) {
Ian Kent cc4062
 			cache_unlock(me->mc);
Ian Kent cc4062
 			return NSS_STATUS_NOTFOUND;
Ian Kent cc4062
-		}
Ian Kent cc4062
-
Ian Kent cc4062
-		/* Negative timeout expired for non-existent entry. */
Ian Kent cc4062
-		if (!me->mapent)
Ian Kent cc4062
-			cache_delete(me->mc, key);
Ian Kent cc4062
+		} else {
Ian Kent cc4062
+			struct mapent_cache *smc = me->mc;
Ian Kent cc4062
+			struct mapent *sme;
Ian Kent cc4062
 
Ian Kent cc4062
-		cache_unlock(me->mc);
Ian Kent cc4062
+			if (me->mapent)
Ian Kent cc4062
+				cache_unlock(smc);
Ian Kent cc4062
+			else {
Ian Kent cc4062
+				cache_unlock(smc);
Ian Kent cc4062
+				cache_writelock(smc);
Ian Kent cc4062
+				sme = cache_lookup_distinct(smc, key);
Ian Kent cc4062
+				/* Negative timeout expired for non-existent entry. */
Ian Kent cc4062
+				if (sme && !sme->mapent)
Ian Kent cc4062
+					cache_delete(smc, key);
Ian Kent cc4062
+				cache_unlock(smc);
Ian Kent cc4062
+			}
Ian Kent cc4062
+		}
Ian Kent cc4062
 	}
Ian Kent cc4062
 
Ian Kent cc4062
 	/*
Ian Kent cc4062
--- autofs-5.0.5.orig/modules/lookup_program.c
Ian Kent cc4062
+++ autofs-5.0.5/modules/lookup_program.c
Ian Kent cc4062
@@ -135,17 +135,26 @@ int lookup_mount(struct autofs_point *ap
Ian Kent cc4062
 		if (me->status >= time(NULL)) {
Ian Kent cc4062
 			cache_unlock(me->mc);
Ian Kent cc4062
 			return NSS_STATUS_NOTFOUND;
Ian Kent cc4062
-		}
Ian Kent cc4062
-
Ian Kent cc4062
-		/* Negative timeout expired for non-existent entry. */
Ian Kent cc4062
-		if (!me->mapent)
Ian Kent cc4062
-			cache_delete(me->mc, name);
Ian Kent cc4062
+		} else {
Ian Kent cc4062
+			struct mapent_cache *smc = me->mc;
Ian Kent cc4062
+			struct mapent *sme;
Ian Kent cc4062
 
Ian Kent cc4062
-		cache_unlock(me->mc);
Ian Kent cc4062
+			if (me->mapent)
Ian Kent cc4062
+				cache_unlock(smc);
Ian Kent cc4062
+			else {
Ian Kent cc4062
+				cache_unlock(smc);
Ian Kent cc4062
+				cache_writelock(smc);
Ian Kent cc4062
+				sme = cache_lookup_distinct(smc, name);
Ian Kent cc4062
+				/* Negative timeout expired for non-existent entry. */
Ian Kent cc4062
+				if (sme && !sme->mapent)
Ian Kent cc4062
+					cache_delete(smc, name);
Ian Kent cc4062
+				cache_unlock(smc);
Ian Kent cc4062
+			}
Ian Kent cc4062
+		}
Ian Kent cc4062
 	}
Ian Kent cc4062
 
Ian Kent cc4062
 	/* Catch installed direct offset triggers */
Ian Kent cc4062
-	cache_writelock(mc);
Ian Kent cc4062
+	cache_readlock(mc);
Ian Kent cc4062
 	me = cache_lookup_distinct(mc, name);
Ian Kent cc4062
 	if (!me) {
Ian Kent cc4062
 		cache_unlock(mc);
Ian Kent cc4062
@@ -191,7 +200,11 @@ int lookup_mount(struct autofs_point *ap
Ian Kent cc4062
 				     " key %s, returning fail", name);
Ian Kent cc4062
 				return NSS_STATUS_UNAVAIL;
Ian Kent cc4062
 			}
Ian Kent cc4062
-			cache_delete(mc, name);
Ian Kent cc4062
+			cache_unlock(mc);
Ian Kent cc4062
+			cache_writelock(mc);
Ian Kent cc4062
+			me = cache_lookup_distinct(mc, name);
Ian Kent cc4062
+			if (me)
Ian Kent cc4062
+				cache_delete(mc, name);
Ian Kent cc4062
 			cache_unlock(mc);
Ian Kent cc4062
 		}
Ian Kent cc4062
 	}
Ian Kent cc4062
--- autofs-5.0.5.orig/modules/lookup_yp.c
Ian Kent cc4062
+++ autofs-5.0.5/modules/lookup_yp.c
Ian Kent cc4062
@@ -533,7 +533,6 @@ static int check_map_indirect(struct aut
Ian Kent cc4062
 		source->stale = 1;
Ian Kent cc4062
 	}
Ian Kent cc4062
 
Ian Kent cc4062
-	pthread_cleanup_push(cache_lock_cleanup, mc);
Ian Kent cc4062
 	cache_writelock(mc);
Ian Kent cc4062
 	exists = cache_lookup_distinct(mc, key);
Ian Kent cc4062
 	/* Not found in the map but found in the cache */
Ian Kent cc4062
@@ -545,7 +544,7 @@ static int check_map_indirect(struct aut
Ian Kent cc4062
 			exists->status = 0;
Ian Kent cc4062
 		}
Ian Kent cc4062
 	}
Ian Kent cc4062
-	pthread_cleanup_pop(1);
Ian Kent cc4062
+	cache_unlock(mc);
Ian Kent cc4062
 
Ian Kent cc4062
 	if (ret == CHE_MISSING) {
Ian Kent cc4062
 		struct mapent *we;
Ian Kent cc4062
@@ -559,7 +558,6 @@ static int check_map_indirect(struct aut
Ian Kent cc4062
 		 * Check for map change and update as needed for
Ian Kent cc4062
 		 * following cache lookup.
Ian Kent cc4062
 		 */
Ian Kent cc4062
-		pthread_cleanup_push(cache_lock_cleanup, mc);
Ian Kent cc4062
 		cache_writelock(mc);
Ian Kent cc4062
 		we = cache_lookup_distinct(mc, "*");
Ian Kent cc4062
 		if (we) {
Ian Kent cc4062
@@ -573,7 +571,7 @@ static int check_map_indirect(struct aut
Ian Kent cc4062
 			if (wild & (CHE_OK | CHE_UPDATED))
Ian Kent cc4062
 				source->stale = 1;
Ian Kent cc4062
 		}
Ian Kent cc4062
-		pthread_cleanup_pop(1);
Ian Kent cc4062
+		cache_unlock(mc);
Ian Kent cc4062
 
Ian Kent cc4062
 		if (wild & (CHE_OK | CHE_UPDATED))
Ian Kent cc4062
 			return NSS_STATUS_SUCCESS;
Ian Kent cc4062
@@ -616,13 +614,22 @@ int lookup_mount(struct autofs_point *ap
Ian Kent cc4062
 		if (me->status >= time(NULL)) {
Ian Kent cc4062
 			cache_unlock(me->mc);
Ian Kent cc4062
 			return NSS_STATUS_NOTFOUND;
Ian Kent cc4062
-		}
Ian Kent cc4062
-
Ian Kent cc4062
-		/* Negative timeout expired for non-existent entry. */
Ian Kent cc4062
-		if (!me->mapent)
Ian Kent cc4062
-			cache_delete(me->mc, key);
Ian Kent cc4062
+		} else {
Ian Kent cc4062
+			struct mapent_cache *smc = me->mc;
Ian Kent cc4062
+			struct mapent *sme;
Ian Kent cc4062
 
Ian Kent cc4062
-		cache_unlock(me->mc);
Ian Kent cc4062
+			if (me->mapent)
Ian Kent cc4062
+				cache_unlock(smc);
Ian Kent cc4062
+			else {
Ian Kent cc4062
+				cache_unlock(smc);
Ian Kent cc4062
+				cache_writelock(smc);
Ian Kent cc4062
+				sme = cache_lookup_distinct(smc, key);
Ian Kent cc4062
+				/* Negative timeout expired for non-existent entry. */
Ian Kent cc4062
+				if (sme && !sme->mapent)
Ian Kent cc4062
+					cache_delete(smc, key);
Ian Kent cc4062
+				cache_unlock(smc);
Ian Kent cc4062
+			}
Ian Kent cc4062
+		}
Ian Kent cc4062
 	}
Ian Kent cc4062
 
Ian Kent cc4062
 	 /*