Blame SOURCES/autofs-5.0.7-fix-fix-wildcard-multi-map-regression.patch

304803
autofs-5.0.7 - fix fix wildcard multi map regression
304803
304803
From: Ian Kent <raven@themaw.net>
304803
304803
A recent patch to fix a wildcard multi map mount regression has a
304803
side effect of causing a deadlock at startup when trying to re-connect
304803
to existing mounts.
304803
304803
The patch required the map entry cache write lock be taken so the cache
304803
could be updated. But when starting and trying to re-connect to existing
304803
mounts there's no need to update the cache.
304803
---
304803
 CHANGELOG                |    1 +
304803
 modules/lookup_file.c    |   25 ++++++++++++++++++++-----
304803
 modules/lookup_ldap.c    |   23 +++++++++++++++++++----
304803
 modules/lookup_nisplus.c |   26 +++++++++++++++++++++-----
304803
 modules/lookup_sss.c     |   22 ++++++++++++++++++----
304803
 modules/lookup_yp.c      |   23 +++++++++++++++++++----
304803
 6 files changed, 98 insertions(+), 22 deletions(-)
304803
304803
--- autofs-5.0.7.orig/CHANGELOG
304803
+++ autofs-5.0.7/CHANGELOG
304803
@@ -57,6 +57,7 @@
304803
 - fix a couple of compiler warnings.
304803
 - add after sssd dependency to unit file.
304803
 - fix syncronize handle_mounts() shutdown.
304803
+- fix fix wildcard multi map regression.
304803
 
304803
 25/07/2012 autofs-5.0.7
304803
 =======================
304803
--- autofs-5.0.7.orig/modules/lookup_file.c
304803
+++ autofs-5.0.7/modules/lookup_file.c
304803
@@ -1042,7 +1042,7 @@ int lookup_mount(struct autofs_point *ap
304803
 			return NSS_STATUS_UNAVAIL;
304803
 		}
304803
 
304803
-		cache_writelock(mc);
304803
+		cache_readlock(mc);
304803
 		me = cache_lookup_first(mc);
304803
 		if (me && st.st_mtime <= me->age) {
304803
 			/*
304803
@@ -1084,7 +1084,18 @@ int lookup_mount(struct autofs_point *ap
304803
 		}
304803
 	}
304803
 
304803
-	cache_writelock(mc);
304803
+	/*
304803
+	 * We can't take the writelock for direct mounts. If we're
304803
+	 * starting up or trying to re-connect to an existing direct
304803
+	 * mount we could be iterating through the map entries with
304803
+	 * the readlock held. But we don't need to update the cache
304803
+	 * when we're starting up so just take the readlock in that
304803
+	 * case.
304803
+	 */
304803
+	if (ap->flags & MOUNT_FLAG_REMOUNT)
304803
+		cache_readlock(mc);
304803
+	else
304803
+		cache_writelock(mc);
304803
 do_cache_lookup:
304803
 	me = cache_lookup(mc, key);
304803
 	/*
304803
@@ -1102,10 +1113,11 @@ do_cache_lookup:
304803
 	}
304803
 	if (me && me->mapent) {
304803
 		/*
304803
-		 * Add wildcard match for later validation checks and
304803
-		 * negative cache lookups.
304803
+		 * If this is a lookup add wildcard match for later validation
304803
+		 * checks and negative cache lookups.
304803
 		 */
304803
-		if (ap->type == LKP_INDIRECT && *me->key == '*') {
304803
+		if (!(ap->flags & MOUNT_FLAG_REMOUNT) &&
304803
+		    ap->type == LKP_INDIRECT && *me->key == '*') {
304803
 			ret = cache_update(mc, source, key, me->mapent, me->age);
304803
 			if (!(ret & (CHE_OK | CHE_UPDATED)))
304803
 				me = NULL;
304803
@@ -1130,6 +1142,9 @@ do_cache_lookup:
304803
 	ret = ctxt->parse->parse_mount(ap, key, key_len,
304803
 				       mapent, ctxt->parse->context);
304803
 	if (ret) {
304803
+		/* Don't update negative cache when re-connecting */
304803
+		if (ap->flags & MOUNT_FLAG_REMOUNT)
304803
+			return NSS_STATUS_TRYAGAIN;
304803
 		cache_writelock(mc);
304803
 		cache_update_negative(mc, source, key, ap->negative_timeout);
304803
 		cache_unlock(mc);
304803
--- autofs-5.0.7.orig/modules/lookup_ldap.c
304803
+++ autofs-5.0.7/modules/lookup_ldap.c
304803
@@ -2975,7 +2975,18 @@ int lookup_mount(struct autofs_point *ap
304803
 			return status;
304803
 	}
304803
 
304803
-	cache_writelock(mc);
304803
+	/*
304803
+	 * We can't take the writelock for direct mounts. If we're
304803
+	 * starting up or trying to re-connect to an existing direct
304803
+	 * mount we could be iterating through the map entries with
304803
+	 * the readlock held. But we don't need to update the cache
304803
+	 * when we're starting up so just take the readlock in that
304803
+	 * case.
304803
+	 */
304803
+	if (ap->flags & MOUNT_FLAG_REMOUNT)
304803
+		cache_readlock(mc);
304803
+	else
304803
+		cache_writelock(mc);
304803
 	me = cache_lookup(mc, key);
304803
 	/* Stale mapent => check for entry in alternate source or wildcard */
304803
 	if (me && !me->mapent) {
304803
@@ -2987,10 +2998,11 @@ int lookup_mount(struct autofs_point *ap
304803
 	}
304803
 	if (me && me->mapent) {
304803
 		/*
304803
-		 * Add wildcard match for later validation checks and
304803
-		 * negative cache lookups.
304803
+		 * If this is a lookup add wildcard match for later validation
304803
+		 * checks and negative cache lookups.
304803
 		 */
304803
-		if (ap->type == LKP_INDIRECT && *me->key == '*') {
304803
+		if (!(ap->flags & MOUNT_FLAG_REMOUNT) &&
304803
+		    ap->type == LKP_INDIRECT && *me->key == '*') {
304803
 			ret = cache_update(mc, source, key, me->mapent, me->age);
304803
 			if (!(ret & (CHE_OK | CHE_UPDATED)))
304803
 				me = NULL;
304803
@@ -3012,6 +3024,9 @@ int lookup_mount(struct autofs_point *ap
304803
 	ret = ctxt->parse->parse_mount(ap, key, key_len,
304803
 				       mapent, ctxt->parse->context);
304803
 	if (ret) {
304803
+		/* Don't update negative cache when re-connecting */
304803
+		if (ap->flags & MOUNT_FLAG_REMOUNT)
304803
+			return NSS_STATUS_TRYAGAIN;
304803
 		cache_writelock(mc);
304803
 		cache_update_negative(mc, source, key, ap->negative_timeout);
304803
 		cache_unlock(mc);
304803
--- autofs-5.0.7.orig/modules/lookup_nisplus.c
304803
+++ autofs-5.0.7/modules/lookup_nisplus.c
304803
@@ -561,7 +561,18 @@ int lookup_mount(struct autofs_point *ap
304803
 			return status;
304803
 	}
304803
 
304803
-	cache_writelock(mc);
304803
+	/*
304803
+	 * We can't take the writelock for direct mounts. If we're
304803
+	 * starting up or trying to re-connect to an existing direct
304803
+	 * mount we could be iterating through the map entries with
304803
+	 * the readlock held. But we don't need to update the cache
304803
+	 * when we're starting up so just take the readlock in that
304803
+	 * case.
304803
+	 */
304803
+	if (ap->flags & MOUNT_FLAG_REMOUNT)
304803
+		cache_readlock(mc);
304803
+	else
304803
+		cache_writelock(mc);
304803
 	me = cache_lookup(mc, key);
304803
 	/* Stale mapent => check for entry in alternate source or wildcard */
304803
 	if (me && !me->mapent) {
304803
@@ -573,10 +584,11 @@ int lookup_mount(struct autofs_point *ap
304803
 	}
304803
 	if (me && me->mapent) {
304803
 		/*
304803
-		 * Add wildcard match for later validation checks and
304803
-		 * negative cache lookups.
304803
+		 * If this is a lookup add wildcard match for later validation
304803
+		 * checks and negative cache lookups.
304803
 		 */
304803
-		if (ap->type == LKP_INDIRECT && *me->key == '*') {
304803
+		if (!(ap->flags & MOUNT_FLAG_REMOUNT) &&
304803
+		    ap->type == LKP_INDIRECT && *me->key == '*') {
304803
 			ret = cache_update(mc, source, key, me->mapent, me->age);
304803
 			if (!(ret & (CHE_OK | CHE_UPDATED)))
304803
 				me = NULL;
304803
@@ -603,6 +615,11 @@ int lookup_mount(struct autofs_point *ap
304803
 		time_t now = time(NULL);
304803
 		int rv = CHE_OK;
304803
 
304803
+		free(mapent);
304803
+
304803
+		/* Don't update negative cache when re-connecting */
304803
+		if (ap->flags & MOUNT_FLAG_REMOUNT)
304803
+			return NSS_STATUS_TRYAGAIN;
304803
 		cache_writelock(mc);
304803
 		me = cache_lookup_distinct(mc, key);
304803
 		if (!me)
304803
@@ -612,7 +629,6 @@ int lookup_mount(struct autofs_point *ap
304803
 			me->status = time(NULL) + ap->negative_timeout;
304803
 		}
304803
 		cache_unlock(mc);
304803
-		free(mapent);
304803
 		return NSS_STATUS_TRYAGAIN;
304803
 	}
304803
 	free(mapent);
304803
--- autofs-5.0.7.orig/modules/lookup_sss.c
304803
+++ autofs-5.0.7/modules/lookup_sss.c
304803
@@ -635,7 +635,17 @@ int lookup_mount(struct autofs_point *ap
304803
 			return status;
304803
 	}
304803
 
304803
-	cache_readlock(mc);
304803
+	/*
304803
+	 * We can't take the writelock for direct mounts. If we're
304803
+	 * starting up or trying to re-connect to an existing direct
304803
+	 * mount we could be iterating through the map entries with
304803
+	 * the readlock held. But we don't need to update the cache
304803
+	 * when we're starting up so just take the readlock in that
304803
+	 */
304803
+	if (ap->flags & MOUNT_FLAG_REMOUNT)
304803
+		cache_writelock(mc);
304803
+	else
304803
+		cache_readlock(mc);
304803
 	me = cache_lookup(mc, key);
304803
 	/* Stale mapent => check for entry in alternate source or wildcard */
304803
 	if (me && !me->mapent) {
304803
@@ -647,10 +657,11 @@ int lookup_mount(struct autofs_point *ap
304803
 	}
304803
 	if (me && me->mapent) {
304803
 		/*
304803
-		 * Add wildcard match for later validation checks and
304803
-		 * negative cache lookups.
304803
+		 * If this is a lookup add wildcard match for later validation
304803
+		 * checks and negative cache lookups.
304803
 		 */
304803
-		if (ap->type == LKP_INDIRECT && *me->key == '*') {
304803
+		if (ap->type == LKP_INDIRECT && *me->key == '*' &&
304803
+		   !(ap->flags & MOUNT_FLAG_REMOUNT)) {
304803
 			ret = cache_update(mc, source, key, me->mapent, me->age);
304803
 			if (!(ret & (CHE_OK | CHE_UPDATED)))
304803
 				me = NULL;
304803
@@ -672,6 +683,9 @@ int lookup_mount(struct autofs_point *ap
304803
 	ret = ctxt->parse->parse_mount(ap, key, key_len,
304803
 				       mapent, ctxt->parse->context);
304803
 	if (ret) {
304803
+		/* Don't update negative cache when re-connecting */
304803
+		if (ap->flags & MOUNT_FLAG_REMOUNT)
304803
+			return NSS_STATUS_TRYAGAIN;
304803
 		cache_writelock(mc);
304803
 		cache_update_negative(mc, source, key, ap->negative_timeout);
304803
 		cache_unlock(mc);
304803
--- autofs-5.0.7.orig/modules/lookup_yp.c
304803
+++ autofs-5.0.7/modules/lookup_yp.c
304803
@@ -662,7 +662,18 @@ int lookup_mount(struct autofs_point *ap
304803
 			return status;
304803
 	}
304803
 
304803
-	cache_writelock(mc);
304803
+	/*
304803
+	 * We can't take the writelock for direct mounts. If we're
304803
+	 * starting up or trying to re-connect to an existing direct
304803
+	 * mount we could be iterating through the map entries with
304803
+	 * the readlock held. But we don't need to update the cache
304803
+	 * when we're starting up so just take the readlock in that
304803
+	 * case.
304803
+	 */
304803
+	if (ap->flags & MOUNT_FLAG_REMOUNT)
304803
+		cache_readlock(mc);
304803
+	else
304803
+		cache_writelock(mc);
304803
 	me = cache_lookup(mc, key);
304803
 	/* Stale mapent => check for entry in alternate source or wildcard */
304803
 	if (me && !me->mapent) {
304803
@@ -674,10 +685,11 @@ int lookup_mount(struct autofs_point *ap
304803
 	}
304803
 	if (me && me->mapent) {
304803
 		/*
304803
-		 * Add wildcard match for later validation checks and
304803
-		 * negative cache lookups.
304803
+		 * If this is a lookup add wildcard match for later validation
304803
+		 * checks and negative cache lookups.
304803
 		 */
304803
-		if (ap->type == LKP_INDIRECT && *me->key == '*') {
304803
+		if (ap->type == LKP_INDIRECT && *me->key == '*' &&
304803
+		   !(ap->flags & MOUNT_FLAG_REMOUNT)) {
304803
 			ret = cache_update(mc, source, key, me->mapent, me->age);
304803
 			if (!(ret & (CHE_OK | CHE_UPDATED)))
304803
 				me = NULL;
304803
@@ -698,6 +710,9 @@ int lookup_mount(struct autofs_point *ap
304803
 		ret = ctxt->parse->parse_mount(ap, key, key_len,
304803
 					       mapent, ctxt->parse->context);
304803
 		if (ret) {
304803
+			/* Don't update negative cache when re-connecting */
304803
+			if (ap->flags & MOUNT_FLAG_REMOUNT)
304803
+				return NSS_STATUS_TRYAGAIN;
304803
 			cache_writelock(mc);
304803
 			cache_update_negative(mc, source, key, ap->negative_timeout);
304803
 			cache_unlock(mc);