142 lines
4.2 KiB
Diff
142 lines
4.2 KiB
Diff
autofs-5.1.8 - fix deadlock in lookups
|
|
|
|
From: Ian Kent <raven@themaw.net>
|
|
|
|
After adding locking to fix a crash during lookups we're seeing a
|
|
deadlock becuase of recursive calls.
|
|
|
|
But once the lookup is open we shouldn't need to open it again during
|
|
the recursive call, fix it based on that.
|
|
|
|
Signed-off-by: Ian Kent <raven@themaw.net>
|
|
---
|
|
CHANGELOG | 1
|
|
daemon/lookup.c | 62 +++++++++++++++++++++++++++++++++-------------------
|
|
daemon/master.c | 8 ++++++
|
|
include/master.h | 1
|
|
modules/parse_amd.c | 2 -
|
|
5 files changed, 51 insertions(+), 23 deletions(-)
|
|
|
|
--- autofs-5.1.4.orig/CHANGELOG
|
|
+++ autofs-5.1.4/CHANGELOG
|
|
@@ -110,6 +110,7 @@
|
|
- don't immediately call function when waiting.
|
|
- fix return status of mount_autofs().
|
|
- don't close lookup at umount.
|
|
+- fix deadlock in lookups.
|
|
|
|
xx/xx/2018 autofs-5.1.5
|
|
- fix flag file permission.
|
|
--- autofs-5.1.4.orig/daemon/lookup.c
|
|
+++ autofs-5.1.4/daemon/lookup.c
|
|
@@ -318,31 +318,49 @@ static int do_read_map(struct autofs_poi
|
|
struct lookup_mod *lookup;
|
|
int status;
|
|
|
|
- pthread_cleanup_push(map_module_lock_cleanup, map);
|
|
- map_module_writelock(map);
|
|
- if (!map->lookup) {
|
|
- status = open_lookup(map->type, "", map->format,
|
|
- map->argc, map->argv, &lookup);
|
|
- if (status == NSS_STATUS_SUCCESS)
|
|
- map->lookup = lookup;
|
|
- else
|
|
- debug(ap->logopt,
|
|
- "lookup module %s open failed", map->type);
|
|
- } else {
|
|
- status = map->lookup->lookup_reinit(map->format,
|
|
- map->argc, map->argv,
|
|
- &map->lookup->context);
|
|
- if (status)
|
|
- warn(ap->logopt,
|
|
- "lookup module %s reinit failed", map->type);
|
|
- }
|
|
- pthread_cleanup_pop(1);
|
|
- if (status != NSS_STATUS_SUCCESS)
|
|
- return status;
|
|
-
|
|
if (!map->stale)
|
|
return NSS_STATUS_SUCCESS;
|
|
|
|
+ /* If this readmap is the result of trying to mount a submount
|
|
+ * the readlock may already be held if the map is the same as
|
|
+ * that of the caller. In that case the map has already been
|
|
+ * read so just skip the map open/reinit.
|
|
+ */
|
|
+ status = map_module_try_writelock(map);
|
|
+ if (status) {
|
|
+ if (!map->lookup) {
|
|
+ error(ap->logopt, "map module lock not held as expected");
|
|
+ return NSS_STATUS_UNAVAIL;
|
|
+ }
|
|
+ } else {
|
|
+ if (!map->lookup) {
|
|
+ pthread_cleanup_push(map_module_lock_cleanup, map);
|
|
+ status = open_lookup(map->type, "", map->format,
|
|
+ map->argc, map->argv, &lookup);
|
|
+ pthread_cleanup_pop(0);
|
|
+ if (status != NSS_STATUS_SUCCESS) {
|
|
+ map_module_unlock(map);
|
|
+ debug(ap->logopt,
|
|
+ "lookup module %s open failed", map->type);
|
|
+ return status;
|
|
+ }
|
|
+ map->lookup = lookup;
|
|
+ } else {
|
|
+ pthread_cleanup_push(map_module_lock_cleanup, map);
|
|
+ status = map->lookup->lookup_reinit(map->format,
|
|
+ map->argc, map->argv,
|
|
+ &map->lookup->context);
|
|
+ pthread_cleanup_pop(0);
|
|
+ if (status) {
|
|
+ map_module_unlock(map);
|
|
+ warn(ap->logopt,
|
|
+ "lookup module %s reinit failed", map->type);
|
|
+ return status;
|
|
+ }
|
|
+ }
|
|
+ map_module_unlock(map);
|
|
+ }
|
|
+
|
|
master_source_current_wait(ap->entry);
|
|
ap->entry->current = map;
|
|
|
|
--- autofs-5.1.4.orig/daemon/master.c
|
|
+++ autofs-5.1.4/daemon/master.c
|
|
@@ -72,6 +72,14 @@ void map_module_writelock(struct map_sou
|
|
fatal(status);
|
|
}
|
|
|
|
+int map_module_try_writelock(struct map_source *map)
|
|
+{
|
|
+ int status = pthread_rwlock_trywrlock(&map->module_lock);
|
|
+ if (status && status != EBUSY && status != EDEADLK)
|
|
+ fatal(status);
|
|
+ return status;
|
|
+}
|
|
+
|
|
void map_module_readlock(struct map_source *map)
|
|
{
|
|
int status = pthread_rwlock_rdlock(&map->module_lock);
|
|
--- autofs-5.1.4.orig/include/master.h
|
|
+++ autofs-5.1.4/include/master.h
|
|
@@ -128,6 +128,7 @@ int master_list_empty(struct master *);
|
|
int master_done(struct master *);
|
|
int master_kill(struct master *);
|
|
void map_module_writelock(struct map_source *map);
|
|
+int map_module_try_writelock(struct map_source *map);
|
|
void map_module_readlock(struct map_source *map);
|
|
void map_module_unlock(struct map_source *map);
|
|
void map_module_lock_cleanup(void *arg);
|
|
--- autofs-5.1.4.orig/modules/parse_amd.c
|
|
+++ autofs-5.1.4/modules/parse_amd.c
|
|
@@ -1391,7 +1391,7 @@ static int do_host_mount(struct autofs_p
|
|
cache_unlock(source->mc);
|
|
|
|
master_source_current_wait(ap->entry);
|
|
- ap->entry->current = source;
|
|
+ ap->entry->current = instance;
|
|
|
|
map_module_readlock(instance);
|
|
lookup = instance->lookup;
|