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

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