autofs-5.0.5 - fix remount locking
From: Ian Kent <raven@themaw.net>
When autofs is restarted with active mounts it is possible, due
to possible recursion when mounting multi-mount map entries, that
a lookup module will take a write lock on the map entry cache
when a read lock is alreay held.
Since, during the re-mount, we are still essentially running
single threaded we need only take care to ensure we don't take
the write lock.
---
CHANGELOG | 1 +
modules/lookup_file.c | 27 +++++++++++++++++----------
modules/lookup_hosts.c | 24 +++++++++++++++---------
modules/lookup_ldap.c | 24 ++++++++++++++++--------
modules/lookup_nisplus.c | 29 ++++++++++++++++++-----------
modules/lookup_program.c | 29 +++++++++++++++++++++--------
modules/lookup_yp.c | 27 +++++++++++++++++----------
7 files changed, 105 insertions(+), 56 deletions(-)
--- autofs-5.0.5.orig/CHANGELOG
+++ autofs-5.0.5/CHANGELOG
@@ -33,6 +33,7 @@
- fix random selection for host on different network.
- make redhat init script more lsb compliant.
- don't hold lock for simple mounts.
+- fix remount locking.
03/09/2009 autofs-5.0.5
-----------------------
--- autofs-5.0.5.orig/modules/lookup_file.c
+++ autofs-5.0.5/modules/lookup_file.c
@@ -871,7 +871,6 @@ static int check_map_indirect(struct aut
if (ret == CHE_FAIL)
return NSS_STATUS_NOTFOUND;
- pthread_cleanup_push(cache_lock_cleanup, mc);
cache_writelock(mc);
exists = cache_lookup_distinct(mc, key);
/* Not found in the map but found in the cache */
@@ -882,7 +881,7 @@ static int check_map_indirect(struct aut
exists->status = 0;
}
}
- pthread_cleanup_pop(1);
+ cache_unlock(mc);
if (ret == CHE_MISSING) {
struct mapent *we;
@@ -896,7 +895,6 @@ static int check_map_indirect(struct aut
* Check for map change and update as needed for
* following cache lookup.
*/
- pthread_cleanup_push(cache_lock_cleanup, mc);
cache_writelock(mc);
we = cache_lookup_distinct(mc, "*");
if (we) {
@@ -904,7 +902,7 @@ static int check_map_indirect(struct aut
if (we->source == source && (wild & CHE_MISSING))
cache_delete(mc, "*");
}
- pthread_cleanup_pop(1);
+ cache_unlock(mc);
if (wild & (CHE_OK | CHE_UPDATED))
return NSS_STATUS_SUCCESS;
@@ -957,13 +955,22 @@ int lookup_mount(struct autofs_point *ap
if (me->status >= time(NULL)) {
cache_unlock(me->mc);
return NSS_STATUS_NOTFOUND;
+ } else {
+ struct mapent_cache *smc = me->mc;
+ struct mapent *sme;
+
+ if (me->mapent)
+ cache_unlock(smc);
+ else {
+ cache_unlock(smc);
+ cache_writelock(smc);
+ sme = cache_lookup_distinct(smc, key);
+ /* Negative timeout expired for non-existent entry. */
+ if (sme && !sme->mapent)
+ cache_delete(smc, key);
+ cache_unlock(smc);
+ }
}
-
- /* Negative timeout expired for non-existent entry. */
- if (!me->mapent)
- cache_delete(me->mc, key);
-
- cache_unlock(me->mc);
}
/*
--- autofs-5.0.5.orig/modules/lookup_hosts.c
+++ autofs-5.0.5/modules/lookup_hosts.c
@@ -146,19 +146,25 @@ int lookup_mount(struct autofs_point *ap
/* Check if we recorded a mount fail for this key anywhere */
me = lookup_source_mapent(ap, name, LKP_DISTINCT);
if (me) {
- struct mapent_cache *fmc = me->mc;
-
if (me->status >= time(NULL)) {
- cache_unlock(fmc);
+ cache_unlock(me->mc);
return NSS_STATUS_NOTFOUND;
- }
+ } else {
+ struct mapent_cache *smc = me->mc;
+ struct mapent *sme;
- if (!me->mapent) {
- cache_delete(fmc, name);
- me = NULL;
+ if (me->mapent)
+ cache_unlock(smc);
+ else {
+ cache_unlock(smc);
+ cache_writelock(smc);
+ sme = cache_lookup_distinct(smc, name);
+ /* Negative timeout expired for non-existent entry. */
+ if (sme && !sme->mapent)
+ cache_delete(smc, name);
+ cache_unlock(smc);
+ }
}
-
- cache_unlock(fmc);
}
cache_readlock(mc);
--- autofs-5.0.5.orig/modules/lookup_ldap.c
+++ autofs-5.0.5/modules/lookup_ldap.c
@@ -2681,7 +2681,6 @@ next:
unbind_ldap_connection(ap->logopt, ldap, ctxt);
/* Failed to find wild entry, update cache if needed */
- pthread_cleanup_push(cache_lock_cleanup, mc);
cache_writelock(mc);
we = cache_lookup_distinct(mc, "*");
if (we) {
@@ -2707,7 +2706,7 @@ next:
}
}
}
- pthread_cleanup_pop(1);
+ cache_unlock(mc);
free(query);
return ret;
@@ -2817,13 +2816,22 @@ int lookup_mount(struct autofs_point *ap
if (me->status >= time(NULL)) {
cache_unlock(me->mc);
return NSS_STATUS_NOTFOUND;
+ } else {
+ struct mapent_cache *smc = me->mc;
+ struct mapent *sme;
+
+ if (me->mapent)
+ cache_unlock(smc);
+ else {
+ cache_unlock(smc);
+ cache_writelock(smc);
+ sme = cache_lookup_distinct(smc, key);
+ /* Negative timeout expired for non-existent entry. */
+ if (sme && !sme->mapent)
+ cache_delete(smc, key);
+ cache_unlock(smc);
+ }
}
-
- /* Negative timeout expired for non-existent entry. */
- if (!me->mapent)
- cache_delete(me->mc, key);
-
- cache_unlock(me->mc);
}
/*
--- autofs-5.0.5.orig/modules/lookup_nisplus.c
+++ autofs-5.0.5/modules/lookup_nisplus.c
@@ -421,7 +421,6 @@ static int check_map_indirect(struct aut
return NSS_STATUS_UNAVAIL;
}
- pthread_cleanup_push(cache_lock_cleanup, mc);
cache_writelock(mc);
t_last_read = ap->exp_runfreq + 1;
me = cache_lookup_first(mc);
@@ -442,8 +441,8 @@ static int check_map_indirect(struct aut
exists->status = 0;
}
}
- pthread_cleanup_pop(1);
-
+ cache_unlock(mc);
+
if (t_last_read > ap->exp_runfreq && ret & CHE_UPDATED)
source->stale = 1;
@@ -459,7 +458,6 @@ static int check_map_indirect(struct aut
* Check for map change and update as needed for
* following cache lookup.
*/
- pthread_cleanup_push(cache_lock_cleanup, mc);
cache_writelock(mc);
we = cache_lookup_distinct(mc, "*");
if (we) {
@@ -473,7 +471,7 @@ static int check_map_indirect(struct aut
if (wild & (CHE_OK | CHE_UPDATED))
source->stale = 1;
}
- pthread_cleanup_pop(1);
+ cache_unlock(mc);
if (wild & (CHE_UPDATED | CHE_OK))
return NSS_STATUS_SUCCESS;
@@ -516,13 +514,22 @@ int lookup_mount(struct autofs_point *ap
if (me->status >= time(NULL)) {
cache_unlock(me->mc);
return NSS_STATUS_NOTFOUND;
- }
-
- /* Negative timeout expired for non-existent entry. */
- if (!me->mapent)
- cache_delete(me->mc, key);
+ } else {
+ struct mapent_cache *smc = me->mc;
+ struct mapent *sme;
- cache_unlock(me->mc);
+ if (me->mapent)
+ cache_unlock(smc);
+ else {
+ cache_unlock(smc);
+ cache_writelock(smc);
+ sme = cache_lookup_distinct(smc, key);
+ /* Negative timeout expired for non-existent entry. */
+ if (sme && !sme->mapent)
+ cache_delete(smc, key);
+ cache_unlock(smc);
+ }
+ }
}
/*
--- autofs-5.0.5.orig/modules/lookup_program.c
+++ autofs-5.0.5/modules/lookup_program.c
@@ -135,17 +135,26 @@ int lookup_mount(struct autofs_point *ap
if (me->status >= time(NULL)) {
cache_unlock(me->mc);
return NSS_STATUS_NOTFOUND;
- }
-
- /* Negative timeout expired for non-existent entry. */
- if (!me->mapent)
- cache_delete(me->mc, name);
+ } else {
+ struct mapent_cache *smc = me->mc;
+ struct mapent *sme;
- cache_unlock(me->mc);
+ if (me->mapent)
+ cache_unlock(smc);
+ else {
+ cache_unlock(smc);
+ cache_writelock(smc);
+ sme = cache_lookup_distinct(smc, name);
+ /* Negative timeout expired for non-existent entry. */
+ if (sme && !sme->mapent)
+ cache_delete(smc, name);
+ cache_unlock(smc);
+ }
+ }
}
/* Catch installed direct offset triggers */
- cache_writelock(mc);
+ cache_readlock(mc);
me = cache_lookup_distinct(mc, name);
if (!me) {
cache_unlock(mc);
@@ -191,7 +200,11 @@ int lookup_mount(struct autofs_point *ap
" key %s, returning fail", name);
return NSS_STATUS_UNAVAIL;
}
- cache_delete(mc, name);
+ cache_unlock(mc);
+ cache_writelock(mc);
+ me = cache_lookup_distinct(mc, name);
+ if (me)
+ cache_delete(mc, name);
cache_unlock(mc);
}
}
--- autofs-5.0.5.orig/modules/lookup_yp.c
+++ autofs-5.0.5/modules/lookup_yp.c
@@ -533,7 +533,6 @@ static int check_map_indirect(struct aut
source->stale = 1;
}
- pthread_cleanup_push(cache_lock_cleanup, mc);
cache_writelock(mc);
exists = cache_lookup_distinct(mc, key);
/* Not found in the map but found in the cache */
@@ -545,7 +544,7 @@ static int check_map_indirect(struct aut
exists->status = 0;
}
}
- pthread_cleanup_pop(1);
+ cache_unlock(mc);
if (ret == CHE_MISSING) {
struct mapent *we;
@@ -559,7 +558,6 @@ static int check_map_indirect(struct aut
* Check for map change and update as needed for
* following cache lookup.
*/
- pthread_cleanup_push(cache_lock_cleanup, mc);
cache_writelock(mc);
we = cache_lookup_distinct(mc, "*");
if (we) {
@@ -573,7 +571,7 @@ static int check_map_indirect(struct aut
if (wild & (CHE_OK | CHE_UPDATED))
source->stale = 1;
}
- pthread_cleanup_pop(1);
+ cache_unlock(mc);
if (wild & (CHE_OK | CHE_UPDATED))
return NSS_STATUS_SUCCESS;
@@ -616,13 +614,22 @@ int lookup_mount(struct autofs_point *ap
if (me->status >= time(NULL)) {
cache_unlock(me->mc);
return NSS_STATUS_NOTFOUND;
- }
-
- /* Negative timeout expired for non-existent entry. */
- if (!me->mapent)
- cache_delete(me->mc, key);
+ } else {
+ struct mapent_cache *smc = me->mc;
+ struct mapent *sme;
- cache_unlock(me->mc);
+ if (me->mapent)
+ cache_unlock(smc);
+ else {
+ cache_unlock(smc);
+ cache_writelock(smc);
+ sme = cache_lookup_distinct(smc, key);
+ /* Negative timeout expired for non-existent entry. */
+ if (sme && !sme->mapent)
+ cache_delete(smc, key);
+ cache_unlock(smc);
+ }
+ }
}
/*