Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 130701790bf2d95e902edf16031ff596 > files > 87

autofs-5.0.1-0.rc2.164.el5_8.src.rpm

autofs-5.0.1 - fix remount locking

From: Ian Kent <raven@themaw.net>

When autofs is restarted with active mounts it is possible, due
to possible recursion when mounting multi-mount map entries, that
a lookup module will take a write lock on the map entry cache
when a read lock is alreay held.

Since, during the re-mount, we are still essentially running
single threaded we need only take care to ensure we don't take
the write lock.
---

 modules/lookup_file.c    |   27 +++++++++++++++++----------
 modules/lookup_hosts.c   |   24 +++++++++++++++---------
 modules/lookup_ldap.c    |   24 ++++++++++++++++--------
 modules/lookup_nisplus.c |   29 ++++++++++++++++++-----------
 modules/lookup_program.c |   29 +++++++++++++++++++++--------
 modules/lookup_yp.c      |   27 +++++++++++++++++----------
 6 files changed, 104 insertions(+), 56 deletions(-)


--- autofs-5.0.1.orig/modules/lookup_file.c
+++ autofs-5.0.1/modules/lookup_file.c
@@ -949,7 +949,6 @@ static int check_map_indirect(struct aut
 	if (ret == CHE_FAIL)
 		return NSS_STATUS_NOTFOUND;
 
-	pthread_cleanup_push(cache_lock_cleanup, mc);
 	cache_writelock(mc);
 	exists = cache_lookup_distinct(mc, key);
 	/* Not found in the map but found in the cache */
@@ -960,7 +959,7 @@ static int check_map_indirect(struct aut
 			exists->status = 0;
 		}
 	}
-	pthread_cleanup_pop(1);
+	cache_unlock(mc);
 
 	if (ret == CHE_MISSING) {
 		struct mapent *we;
@@ -974,7 +973,6 @@ static int check_map_indirect(struct aut
 		 * Check for map change and update as needed for
 		 * following cache lookup.
 		 */
-		pthread_cleanup_push(cache_lock_cleanup, mc);
 		cache_writelock(mc);
 		we = cache_lookup_distinct(mc, "*");
 		if (we) {
@@ -982,7 +980,7 @@ static int check_map_indirect(struct aut
 			if (we->source == source && (wild & CHE_MISSING))
 				cache_delete(mc, "*");
 		}
-		pthread_cleanup_pop(1);
+		cache_unlock(mc);
 
 		if (wild & (CHE_OK | CHE_UPDATED))
 			return NSS_STATUS_SUCCESS;
@@ -1035,13 +1033,22 @@ int lookup_mount(struct autofs_point *ap
 		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, key);
+				/* Negative timeout expired for non-existent entry. */
+				if (sme && !sme->mapent)
+					cache_delete(smc, key);
+				cache_unlock(smc);
+			}
 		}
-
-		/* Negative timeout expired for non-existent entry. */
-		if (!me->mapent)
-			cache_delete(me->mc, key);
-
-		cache_unlock(me->mc);
 	}
 
 	/*
--- autofs-5.0.1.orig/modules/lookup_hosts.c
+++ autofs-5.0.1/modules/lookup_hosts.c
@@ -141,19 +141,25 @@ int lookup_mount(struct autofs_point *ap
 	/* Check if we recorded a mount fail for this key anywhere */
 	me = lookup_source_mapent(ap, name, LKP_DISTINCT);
 	if (me) {
-		struct mapent_cache *fmc = me->mc;
-
 		if (me->status >= time(NULL)) {
-			cache_unlock(fmc);
+			cache_unlock(me->mc);
 			return NSS_STATUS_NOTFOUND;
-		}
+		} else {
+			struct mapent_cache *smc = me->mc;
+			struct mapent *sme;
 
-		if (!me->mapent) {
-			cache_delete(fmc, name);
-			me = NULL;
+			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)
+					cache_delete(smc, name);
+				cache_unlock(smc);
+			}
 		}
-
-		cache_unlock(fmc);
 	}
 
 	cache_readlock(mc);
--- autofs-5.0.1.orig/modules/lookup_ldap.c
+++ autofs-5.0.1/modules/lookup_ldap.c
@@ -2517,7 +2517,6 @@ next:
 	unbind_ldap_connection(ap->logopt, ldap, ctxt);
 
 	/* Failed to find wild entry, update cache if needed */
-	pthread_cleanup_push(cache_lock_cleanup, mc);
 	cache_writelock(mc);
 	we = cache_lookup_distinct(mc, "*");
 	if (we) {
@@ -2543,7 +2542,7 @@ next:
 			}
 		}
 	}
-	pthread_cleanup_pop(1);
+	cache_unlock(mc);
 
 	return ret;
 }
@@ -2652,13 +2651,22 @@ int lookup_mount(struct autofs_point *ap
 		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, key);
+				/* Negative timeout expired for non-existent entry. */
+				if (sme && !sme->mapent)
+					cache_delete(smc, key);
+				cache_unlock(smc);
+			}
 		}
-
-		/* Negative timeout expired for non-existent entry. */
-		if (!me->mapent)
-			cache_delete(me->mc, key);
-
-		cache_unlock(me->mc);
 	}
 
         /*
--- autofs-5.0.1.orig/modules/lookup_nisplus.c
+++ autofs-5.0.1/modules/lookup_nisplus.c
@@ -412,7 +412,6 @@ static int check_map_indirect(struct aut
 		return NSS_STATUS_UNAVAIL;
 	}
 
-	pthread_cleanup_push(cache_lock_cleanup, mc);
 	cache_writelock(mc);
 	t_last_read = ap->exp_runfreq + 1;
 	me = cache_lookup_first(mc);
@@ -433,8 +432,8 @@ static int check_map_indirect(struct aut
 			exists->status = 0;
 		}
 	}
-	pthread_cleanup_pop(1);
-	
+	cache_unlock(mc);
+
 	if (t_last_read > ap->exp_runfreq && ret & CHE_UPDATED)
 		source->stale = 1;
 
@@ -450,7 +449,6 @@ static int check_map_indirect(struct aut
 		 * Check for map change and update as needed for
 		 * following cache lookup.
 		*/
-		pthread_cleanup_push(cache_lock_cleanup, mc);
 		cache_writelock(mc);
 		we = cache_lookup_distinct(mc, "*");
 		if (we) {
@@ -464,7 +462,7 @@ static int check_map_indirect(struct aut
 			if (wild & (CHE_OK | CHE_UPDATED))
 				source->stale = 1;
 		}
-		pthread_cleanup_pop(1);
+		cache_unlock(mc);
 
 		if (wild & (CHE_UPDATED | CHE_OK))
 			return NSS_STATUS_SUCCESS;
@@ -507,13 +505,22 @@ int lookup_mount(struct autofs_point *ap
 		if (me->status >= time(NULL)) {
 			cache_unlock(me->mc);
 			return NSS_STATUS_NOTFOUND;
-		}
-
-		/* Negative timeout expired for non-existent entry. */
-		if (!me->mapent)
-			cache_delete(me->mc, key);
+		} else {
+			struct mapent_cache *smc = me->mc;
+			struct mapent *sme;
 
-		cache_unlock(me->mc);
+			if (me->mapent)
+				cache_unlock(smc);
+			else {
+				cache_unlock(smc);
+				cache_writelock(smc);
+				sme = cache_lookup_distinct(smc, key);
+				/* Negative timeout expired for non-existent entry. */
+				if (sme && !sme->mapent)
+					cache_delete(smc, key);
+				cache_unlock(smc);
+			}
+		}
 	}
 
 	/*
--- autofs-5.0.1.orig/modules/lookup_program.c
+++ autofs-5.0.1/modules/lookup_program.c
@@ -136,17 +136,26 @@ int lookup_mount(struct autofs_point *ap
 		if (me->status >= time(NULL)) {
 			cache_unlock(me->mc);
 			return NSS_STATUS_NOTFOUND;
-		}
-
-		/* Negative timeout expired for non-existent entry. */
-		if (!me->mapent)
-			cache_delete(me->mc, name);
+		} else {
+			struct mapent_cache *smc = me->mc;
+			struct mapent *sme;
 
-		cache_unlock(me->mc);
+			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)
+					cache_delete(smc, name);
+				cache_unlock(smc);
+			}
+		}
 	}
 
 	/* Catch installed direct offset triggers */
-	cache_writelock(mc);
+	cache_readlock(mc);
 	me = cache_lookup_distinct(mc, name);
 	if (!me) {
 		cache_unlock(mc);
@@ -192,7 +201,11 @@ int lookup_mount(struct autofs_point *ap
 				     " key %s, returning fail", name);
 				return NSS_STATUS_UNAVAIL;
 			}
-			cache_delete(mc, name);
+			cache_unlock(mc);
+			cache_writelock(mc);
+			me = cache_lookup_distinct(mc, name);
+			if (me)
+				cache_delete(mc, name);
 			cache_unlock(mc);
 		}
 	}
--- autofs-5.0.1.orig/modules/lookup_yp.c
+++ autofs-5.0.1/modules/lookup_yp.c
@@ -533,7 +533,6 @@ static int check_map_indirect(struct aut
 		source->stale = 1;
 	}
 
-	pthread_cleanup_push(cache_lock_cleanup, mc);
 	cache_writelock(mc);
 	exists = cache_lookup_distinct(mc, key);
 	/* Not found in the map but found in the cache */
@@ -545,7 +544,7 @@ static int check_map_indirect(struct aut
 			exists->status = 0;
 		}
 	}
-	pthread_cleanup_pop(1);
+	cache_unlock(mc);
 
 	if (ret == CHE_MISSING) {
 		struct mapent *we;
@@ -559,7 +558,6 @@ static int check_map_indirect(struct aut
 		 * Check for map change and update as needed for
 		 * following cache lookup.
 		 */
-		pthread_cleanup_push(cache_lock_cleanup, mc);
 		cache_writelock(mc);
 		we = cache_lookup_distinct(mc, "*");
 		if (we) {
@@ -573,7 +571,7 @@ static int check_map_indirect(struct aut
 			if (wild & (CHE_OK | CHE_UPDATED))
 				source->stale = 1;
 		}
-		pthread_cleanup_pop(1);
+		cache_unlock(mc);
 
 		if (wild & (CHE_OK | CHE_UPDATED))
 			return NSS_STATUS_SUCCESS;
@@ -616,13 +614,22 @@ int lookup_mount(struct autofs_point *ap
 		if (me->status >= time(NULL)) {
 			cache_unlock(me->mc);
 			return NSS_STATUS_NOTFOUND;
-		}
-
-		/* Negative timeout expired for non-existent entry. */
-		if (!me->mapent)
-			cache_delete(me->mc, key);
+		} else {
+			struct mapent_cache *smc = me->mc;
+			struct mapent *sme;
 
-		cache_unlock(me->mc);
+			if (me->mapent)
+				cache_unlock(smc);
+			else {
+				cache_unlock(smc);
+				cache_writelock(smc);
+				sme = cache_lookup_distinct(smc, key);
+				/* Negative timeout expired for non-existent entry. */
+				if (sme && !sme->mapent)
+					cache_delete(smc, key);
+				cache_unlock(smc);
+			}
+		}
 	}
 
 	 /*