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

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