autofs-5.1.8 - serialise lookup module open and reinit From: Ian Kent Add a map source lock to serialise map setting and use of module structure fields such as the context. Signed-off-by: Ian Kent --- CHANGELOG | 1 + daemon/lookup.c | 35 +++++++++++++++++++++-------------- daemon/master.c | 43 +++++++++++++++++++++++++++++++++++++++++++ include/master.h | 5 +++++ modules/parse_amd.c | 26 +++++++++++++++----------- 5 files changed, 85 insertions(+), 25 deletions(-) --- autofs-5.1.4.orig/CHANGELOG +++ autofs-5.1.4/CHANGELOG @@ -97,6 +97,7 @@ - dont use initgroups() at spawn. - fix invalid tsv access. - fix parse module instance mutex naming. +- serialise lookup module open and reinit. 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,28 +318,27 @@ static int do_read_map(struct autofs_poi struct lookup_mod *lookup; int status; - lookup = NULL; - master_source_writelock(ap->entry); + 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) { - master_source_unlock(ap->entry); + if (status == NSS_STATUS_SUCCESS) + map->lookup = lookup; + else debug(ap->logopt, "lookup module %s open failed", map->type); - return status; - } - map->lookup = lookup; } else { - lookup = map->lookup; - status = lookup->lookup_reinit(map->format, - map->argc, map->argv, - &lookup->context); + 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); } - master_source_unlock(ap->entry); + pthread_cleanup_pop(1); + if (status != NSS_STATUS_SUCCESS) + return status; if (!map->stale) return NSS_STATUS_SUCCESS; @@ -347,7 +346,11 @@ static int do_read_map(struct autofs_poi master_source_current_wait(ap->entry); ap->entry->current = map; + pthread_cleanup_push(map_module_lock_cleanup, map); + map_module_readlock(map); + lookup = map->lookup; status = lookup->lookup_read_map(ap, age, lookup->context); + pthread_cleanup_pop(1); if (status != NSS_STATUS_SUCCESS) map->stale = 0; @@ -812,23 +815,27 @@ int do_lookup_mount(struct autofs_point struct lookup_mod *lookup; int status; + 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_module_unlock(map); debug(ap->logopt, "lookup module %s open failed", map->type); return status; } map->lookup = lookup; } - - lookup = map->lookup; + map_module_unlock(map); master_source_current_wait(ap->entry); ap->entry->current = map; + map_module_readlock(map); + lookup = map->lookup; status = lookup->lookup_mount(ap, name, name_len, lookup->context); + map_module_unlock(map); return status; } --- autofs-5.1.4.orig/daemon/master.c +++ autofs-5.1.4/daemon/master.c @@ -65,6 +65,34 @@ void master_mutex_lock_cleanup(void *arg return; } +void map_module_writelock(struct map_source *map) +{ + int status = pthread_rwlock_wrlock(&map->module_lock); + if (status) + fatal(status); +} + +void map_module_readlock(struct map_source *map) +{ + int status = pthread_rwlock_rdlock(&map->module_lock); + if (status) + fatal(status); +} + +void map_module_unlock(struct map_source *map) +{ + int status = pthread_rwlock_unlock(&map->module_lock); + if (status) + fatal(status); +} + +void map_module_lock_cleanup(void *arg) +{ + struct map_source *map = (struct map_source *) arg; + + map_module_unlock(map); +} + int master_add_autofs_point(struct master_mapent *entry, unsigned logopt, unsigned nobind, unsigned ghost, int submount) { @@ -155,6 +183,7 @@ master_add_map_source(struct master_mape struct map_source *source; char *ntype, *nformat; const char **tmpargv; + int status; source = malloc(sizeof(struct map_source)); if (!source) @@ -241,6 +270,10 @@ master_add_map_source(struct master_mape master_source_unlock(entry); + status = pthread_rwlock_init(&source->module_lock, NULL); + if (status) + fatal(status); + return source; } @@ -330,6 +363,8 @@ master_get_map_source(struct master_mape static void __master_free_map_source(struct map_source *source, unsigned int free_cache) { + int status; + /* instance map sources are not ref counted */ if (source->ref && --source->ref) return; @@ -365,6 +400,10 @@ static void __master_free_map_source(str } } + status = pthread_rwlock_destroy(&source->module_lock); + if (status) + fatal(status); + free(source); return; @@ -496,6 +535,10 @@ master_add_source_instance(struct map_so if (status) fatal(status); + status = pthread_rwlock_init(&new->module_lock, NULL); + if (status) + fatal(status); + return new; } --- autofs-5.1.4.orig/include/master.h +++ autofs-5.1.4/include/master.h @@ -35,6 +35,7 @@ struct map_source { unsigned int stale; unsigned int recurse; unsigned int depth; + pthread_rwlock_t module_lock; struct lookup_mod *lookup; int argc; const char **argv; @@ -126,5 +127,9 @@ int __master_list_empty(struct master *) int master_list_empty(struct master *); int master_done(struct master *); int master_kill(struct master *); +void map_module_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); #endif --- autofs-5.1.4.orig/modules/parse_amd.c +++ autofs-5.1.4/modules/parse_amd.c @@ -1358,14 +1358,6 @@ static int do_host_mount(struct autofs_p argc = 1; } - parse_instance_mutex_lock(); - status = open_lookup("hosts", MODPREFIX, NULL, argc, pargv, &lookup); - if (status != NSS_STATUS_SUCCESS) { - debug(ap->logopt, "open lookup module hosts failed"); - parse_instance_mutex_unlock(); - goto out; - } - instance = master_find_source_instance(source, "hosts", "sun", argc, pargv); if (!instance) { @@ -1374,13 +1366,22 @@ static int do_host_mount(struct autofs_p if (!instance) { error(ap->logopt, MODPREFIX "failed to create source instance for hosts map"); - parse_instance_mutex_unlock(); close_lookup(lookup); goto out; } } - instance->lookup = lookup; - parse_instance_mutex_unlock(); + + map_module_writelock(instance); + if (!instance->lookup) { + status = open_lookup("hosts", MODPREFIX, NULL, argc, pargv, &lookup); + if (status != NSS_STATUS_SUCCESS) { + map_module_unlock(instance); + debug(ap->logopt, "open lookup module hosts failed"); + goto out; + } + instance->lookup = lookup; + } + map_module_unlock(instance); cache_writelock(source->mc); me = cache_lookup_distinct(source->mc, name); @@ -1391,8 +1392,11 @@ static int do_host_mount(struct autofs_p master_source_current_wait(ap->entry); ap->entry->current = source; + map_module_readlock(instance); + lookup = instance->lookup; ret = lookup->lookup_mount(ap, entry->rhost, strlen(entry->rhost), lookup->context); + map_module_unlock(instance); if (!strcmp(name, entry->rhost)) goto out;