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

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