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