Ian Kent cc58c1
autofs-5.0.6 - fix remount deadlock
Ian Kent cc58c1
Ian Kent cc58c1
From: Ian Kent <raven@themaw.net>
Ian Kent cc58c1
Ian Kent cc58c1
When reconstructing the mount tree upon restart a writelock to the map
Ian Kent cc58c1
entry cache cannot be taken when parsing a direct map entry because a
Ian Kent cc58c1
readlock is already held higher up in the call tree.
Ian Kent cc58c1
Ian Kent cc58c1
In the place this is done it isn't be necessary to alter the direct map
Ian Kent cc58c1
entries in the cache. Also, it shouldn't be necessary to delete existing
Ian Kent cc58c1
multi-mount cache entries to avoid a duplicate multi-mount entry error
Ian Kent cc58c1
return. The check for a duplicate can be done in the cache handling
Ian Kent cc58c1
functions.
Ian Kent cc58c1
---
Ian Kent cc58c1
Ian Kent cc58c1
 CHANGELOG           |    1 
Ian Kent cc58c1
 lib/cache.c         |    8 ++++--
Ian Kent cc58c1
 modules/parse_sun.c |   60 ++++++++++++++++++++++++++--------------------------
Ian Kent cc58c1
 3 files changed, 36 insertions(+), 33 deletions(-)
Ian Kent cc58c1
Ian Kent cc58c1
Ian Kent cc58c1
--- autofs-5.0.6.orig/CHANGELOG
Ian Kent cc58c1
+++ autofs-5.0.6/CHANGELOG
Ian Kent cc58c1
@@ -52,6 +52,7 @@
Ian Kent cc58c1
 - fix nfs4 contacts portmap.
Ian Kent cc58c1
 - make autofs wait longer for shutdown completion.
Ian Kent cc58c1
 - fix sss map age not updated.
Ian Kent cc58c1
+- fix remount deadlock.
Ian Kent cc58c1
 
Ian Kent cc58c1
 28/06/2011 autofs-5.0.6
Ian Kent cc58c1
 -----------------------
Ian Kent cc58c1
--- autofs-5.0.6.orig/lib/cache.c
Ian Kent cc58c1
+++ autofs-5.0.6/lib/cache.c
Ian Kent cc58c1
@@ -658,10 +658,12 @@ int cache_add_offset(struct mapent_cache
Ian Kent cc58c1
 		return CHE_FAIL;
Ian Kent cc58c1
 
Ian Kent cc58c1
 	me = cache_lookup_distinct(mc, key);
Ian Kent cc58c1
-	if (me && me != owner)
Ian Kent cc58c1
-		return CHE_DUPLICATE;
Ian Kent cc58c1
+	if (me && me->age == age) {
Ian Kent cc58c1
+		if (me != owner)
Ian Kent cc58c1
+			return CHE_DUPLICATE;
Ian Kent cc58c1
+	}
Ian Kent cc58c1
 
Ian Kent cc58c1
-	ret = cache_add(mc, owner->source, key, mapent, age);
Ian Kent cc58c1
+	ret = cache_update(mc, owner->source, key, mapent, age);
Ian Kent cc58c1
 	if (ret == CHE_FAIL) {
Ian Kent cc58c1
 		warn(logopt, "failed to add key %s to cache", key);
Ian Kent cc58c1
 		return CHE_FAIL;
Ian Kent cc58c1
--- autofs-5.0.6.orig/modules/parse_sun.c
Ian Kent cc58c1
+++ autofs-5.0.6/modules/parse_sun.c
Ian Kent cc58c1
@@ -843,12 +843,17 @@ add_offset_entry(struct autofs_point *ap
Ian Kent cc58c1
 		strcpy(m_mapent, loc);
Ian Kent cc58c1
 
Ian Kent cc58c1
 	ret = cache_add_offset(mc, name, m_key, m_mapent, age);
Ian Kent cc58c1
-	if (ret == CHE_OK)
Ian Kent cc58c1
+	if (ret == CHE_DUPLICATE)
Ian Kent cc58c1
+		warn(ap->logopt, MODPREFIX
Ian Kent cc58c1
+		     "syntax error or duplicate offset %s -> %s", path, loc);
Ian Kent cc58c1
+	else if (ret == CHE_FAIL)
Ian Kent cc58c1
+		debug(ap->logopt, MODPREFIX
Ian Kent cc58c1
+		      "failed to add multi-mount offset %s -> %s", path, m_mapent);
Ian Kent cc58c1
+	else {
Ian Kent cc58c1
+		ret = CHE_OK;
Ian Kent cc58c1
 		debug(ap->logopt, MODPREFIX
Ian Kent cc58c1
 		      "added multi-mount offset %s -> %s", path, m_mapent);
Ian Kent cc58c1
-	else
Ian Kent cc58c1
-		warn(ap->logopt, MODPREFIX
Ian Kent cc58c1
-		      "syntax error or duplicate offset %s -> %s", path, loc);
Ian Kent cc58c1
+	}
Ian Kent cc58c1
 
Ian Kent cc58c1
 	return ret;
Ian Kent cc58c1
 }
Ian Kent cc58c1
@@ -1410,7 +1415,7 @@ int parse_mount(struct autofs_point *ap,
Ian Kent cc58c1
 	char buf[MAX_ERR_BUF];
Ian Kent cc58c1
 	struct map_source *source;
Ian Kent cc58c1
 	struct mapent_cache *mc;
Ian Kent cc58c1
-	struct mapent *me = NULL;
Ian Kent cc58c1
+	struct mapent *me;
Ian Kent cc58c1
 	char *pmapent, *options;
Ian Kent cc58c1
 	const char *p;
Ian Kent cc58c1
 	int mapent_len, rv = 0;
Ian Kent cc58c1
@@ -1561,33 +1566,28 @@ int parse_mount(struct autofs_point *ap,
Ian Kent cc58c1
 			strcat(m_root, name);
Ian Kent cc58c1
 		}
Ian Kent cc58c1
 
Ian Kent cc58c1
-		cache_writelock(mc);
Ian Kent cc58c1
-		me = cache_lookup_distinct(mc, name);
Ian Kent cc58c1
-		if (!me) {
Ian Kent cc58c1
-			int ret;
Ian Kent cc58c1
-			/*
Ian Kent cc58c1
-			 * Not in the cache, perhaps it's a program map
Ian Kent cc58c1
-			 * or one that doesn't support enumeration
Ian Kent cc58c1
-			 */
Ian Kent cc58c1
-			ret = cache_add(mc, source, name, mapent, time(NULL));
Ian Kent cc58c1
-			if (ret == CHE_FAIL) {
Ian Kent cc58c1
-				cache_unlock(mc);
Ian Kent cc58c1
-				free(options);
Ian Kent cc58c1
-				return 1;
Ian Kent cc58c1
+		/*
Ian Kent cc58c1
+		 * Can't take the write lock for direct mount entries here
Ian Kent cc58c1
+		 * but they should always be present in the map entry cache.
Ian Kent cc58c1
+		 */
Ian Kent cc58c1
+		if (ap->type == LKP_INDIRECT) {
Ian Kent cc58c1
+			cache_writelock(mc);
Ian Kent cc58c1
+			me = cache_lookup_distinct(mc, name);
Ian Kent cc58c1
+			if (!me) {
Ian Kent cc58c1
+				int ret;
Ian Kent cc58c1
+				/*
Ian Kent cc58c1
+				 * Not in the cache, perhaps it's a program map
Ian Kent cc58c1
+				 * or one that doesn't support enumeration.
Ian Kent cc58c1
+				 */
Ian Kent cc58c1
+				ret = cache_add(mc, source, name, mapent, age);
Ian Kent cc58c1
+				if (ret == CHE_FAIL) {
Ian Kent cc58c1
+					cache_unlock(mc);
Ian Kent cc58c1
+					free(options);
Ian Kent cc58c1
+					return 1;
Ian Kent cc58c1
+				}
Ian Kent cc58c1
 			}
Ian Kent cc58c1
-		} else {
Ian Kent cc58c1
-			/*
Ian Kent cc58c1
-			 * If the entry exists it must not have any existing
Ian Kent cc58c1
-			 * multi-mount subordinate entries since we are
Ian Kent cc58c1
-			 * mounting this afresh. We need to do this to allow
Ian Kent cc58c1
-			 * us to fail on the check for duplicate offsets in
Ian Kent cc58c1
-			 * we don't know when submounts go away.
Ian Kent cc58c1
-			 */
Ian Kent cc58c1
-			cache_multi_writelock(me);
Ian Kent cc58c1
-			cache_delete_offset_list(mc, name);
Ian Kent cc58c1
-			cache_multi_unlock(me);
Ian Kent cc58c1
+			cache_unlock(mc);
Ian Kent cc58c1
 		}
Ian Kent cc58c1
-		cache_unlock(mc);
Ian Kent cc58c1
 
Ian Kent cc58c1
 		cache_readlock(mc);
Ian Kent cc58c1
 		me = cache_lookup_distinct(mc, name);