diff --git a/CHANGELOG b/CHANGELOG
index 93a4df5..8cfb220 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -3,6 +3,7 @@
 - code cleanup.
 - fix race for current map source.
 - cthon map parser corrections.
+- cthon multi-map locking fix and current race corrections.
 
 13/7/2006 autofs-5.0.1 rc1
 --------------------------
diff --git a/daemon/automount.c b/daemon/automount.c
index 95eba4b..9faf485 100644
--- a/daemon/automount.c
+++ b/daemon/automount.c
@@ -217,7 +217,7 @@ static int umount_offsets(struct autofs_
 	map = ap->entry->first;
 	while (map) {
 		mc = map->mc;
-		cache_writelock(mc);
+		cache_readlock(mc);
 		me = cache_lookup_distinct(mc, base);
 		if (!me)
 			me = cache_lookup_distinct(mc, ind_key);
@@ -226,7 +226,6 @@ static int umount_offsets(struct autofs_
 		cache_unlock(mc);
 		map = map->next;
 	}
-	ap->entry->current = map;
 	master_source_unlock(ap->entry);
 
 	if (!me)
@@ -268,12 +267,13 @@ static int umount_offsets(struct autofs_
 	}
 
 	if (!ret && me->multi == me) {
+		cache_multi_lock(mc);
 		status = cache_delete_offset_list(mc, me->key);
+		cache_multi_unlock(mc);
 		if (status != CHE_OK)
 			warn(ap->logopt, "couldn't delete offset list");
 	}
 	cache_unlock(mc);
-	ap->entry->current = NULL;
 
 	return ret;
 }
@@ -351,7 +351,6 @@ static int umount_ent(struct autofs_poin
 			     "mounted on this path.", path);
 			rv = -1;
 		}
-
 	}
 
 	status = pthread_mutex_unlock(&ap->state_mutex);
@@ -383,6 +382,8 @@ static int walk_tree(const char *base, i
 			while (n--) {
 				int ret, size;
 
+				sched_yield();
+
 				if (strcmp(de[n]->d_name, ".") == 0 ||
 				    strcmp(de[n]->d_name, "..") == 0) {
 					free(de[n]);
@@ -413,6 +414,7 @@ static int walk_tree(const char *base, i
 static int rm_unwanted_fn(const char *file, const struct stat *st, int when, void *arg)
 {
 	dev_t dev = *(int *) arg;
+	char buf[MAX_ERR_BUF];
 	struct stat newst;
 
 	if (when == 0) {
@@ -437,8 +439,9 @@ static int rm_unwanted_fn(const char *fi
 	if (S_ISDIR(newst.st_mode)) {
 		debug(LOGOPT_ANY, "removing directory %s", file);
 		if (rmdir(file)) {
+			char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
 			error(LOGOPT_ANY,
-			      "unable to remove directory %s", file);
+			      "unable to remove directory %s: %s", file, estr);
 			return 0;
 		}
 	} else if (S_ISREG(newst.st_mode)) {
@@ -1217,6 +1220,8 @@ static void handle_mounts_cleanup(void *
 	if (master_list_empty(master_list))
 		kill(getpid(), SIGTERM);
 
+	sched_yield();
+
 	if (clean) {
 		if (rmdir(path) == -1) {
 			char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
@@ -1337,7 +1342,7 @@ void *handle_mounts(void *arg)
 				fatal(status);
 		}
 	}
-/*
+
 	status = pthread_mutex_lock(&ap->mounts_mutex);
 	if (status)
 		fatal(status);
@@ -1351,7 +1356,7 @@ void *handle_mounts(void *arg)
 	status = pthread_mutex_unlock(&ap->mounts_mutex);
 	if (status)
 		fatal(status);
-*/
+
 	pthread_cleanup_pop(1);
 
 	/*
diff --git a/daemon/direct.c b/daemon/direct.c
index 93af751..4ee8a03 100644
--- a/daemon/direct.c
+++ b/daemon/direct.c
@@ -197,7 +197,6 @@ int umount_autofs_direct(struct autofs_p
 	master_source_readlock(ap->entry);
 	map = ap->entry->first;
 	while (map) {
-		ap->entry->current = map;
 		mc = map->mc;
 		pthread_cleanup_push(cache_lock_cleanup, mc);
 		cache_readlock(mc);
@@ -213,7 +212,6 @@ int umount_autofs_direct(struct autofs_p
 	}
 	pthread_cleanup_pop(1);
 	tree_free_mnt_tree(mnts);
-	ap->entry->current = NULL;
 
 	return 0;
 }
@@ -264,7 +262,6 @@ static int unlink_mount_tree(struct auto
 
 int do_mount_autofs_direct(struct autofs_point *ap, struct mnt_list *mnts, struct mapent *me)
 {
-	struct map_source *map = ap->entry->current;
 	struct mnt_params *mp;
 	time_t timeout = ap->exp_timeout;
 	struct stat st;
@@ -382,7 +379,7 @@ got_version:
 		      "failed to stat direct mount trigger %s", me->key);
 		goto out_close;
 	}
-	cache_set_ino_index(map->mc, me->key, st.st_dev, st.st_ino);
+	cache_set_ino_index(me->source->mc, me->key, st.st_dev, st.st_ino);
 
 	close(me->ioctlfd);
 	me->ioctlfd = -1;
@@ -442,7 +439,6 @@ int mount_autofs_direct(struct autofs_po
 			continue;
 		}
 
-		ap->entry->current = map;
 		mc = map->mc;
 		pthread_cleanup_push(cache_lock_cleanup, mc);
 		cache_readlock(mc);
diff --git a/include/automount.h b/include/automount.h
index 8a5b800..a71606e 100644
--- a/include/automount.h
+++ b/include/automount.h
@@ -123,6 +123,7 @@ #define NEGATIVE_TIMEOUT	10
 
 struct mapent_cache {
 	pthread_rwlock_t rwlock;
+	pthread_mutex_t multi_mutex;
 	unsigned int size;
 	struct list_head *ino_index;
 	struct mapent **hash;
@@ -170,6 +171,8 @@ int cache_add_offset(struct mapent_cache
 int cache_update(struct mapent_cache *mc, struct map_source *source,
 			const char *key, const char *mapent, time_t age);
 int cache_delete(struct mapent_cache *mc, const char *key);
+void cache_multi_lock(struct mapent_cache *mc);
+void cache_multi_unlock(struct mapent_cache *mc);
 int cache_delete_offset_list(struct mapent_cache *mc, const char *key);
 void cache_release(struct map_source *map);
 struct mapent *cache_enumerate(struct mapent_cache *mc, struct mapent *me);
diff --git a/lib/cache.c b/lib/cache.c
index ffc4c9b..4d0b196 100644
--- a/lib/cache.c
+++ b/lib/cache.c
@@ -98,6 +98,29 @@ void cache_lock_cleanup(void *arg)
 	cache_unlock(mc);
 }
 
+void cache_multi_lock(struct mapent_cache *mc)
+{
+	int status;
+
+	status = pthread_mutex_lock(&mc->multi_mutex);
+	if (status) {
+		error(LOGOPT_ANY, "mapent cache multi mutex lock failed");
+		fatal(status);
+	}
+	return;
+}
+
+void cache_multi_unlock(struct mapent_cache *mc)
+{
+	int status;
+
+	status = pthread_mutex_unlock(&mc->multi_mutex);
+	if (status) {
+		error(LOGOPT_ANY, "mapent cache multi mutex unlock failed");
+		fatal(status);
+	}
+	return;
+}
 struct mapent_cache *cache_init(struct map_source *map)
 {
 	struct mapent_cache *mc;
@@ -130,6 +153,10 @@ struct mapent_cache *cache_init(struct m
 	if (status)
 		fatal(status);
 
+	status = pthread_mutex_init(&mc->multi_mutex, NULL);
+	if (status)
+		fatal(status);
+
 	cache_writelock(mc);
 
 	for (i = 0; i < mc->size; i++) {
@@ -675,6 +702,10 @@ void cache_release(struct map_source *ma
 	if (status)
 		fatal(status);
 
+	status = pthread_mutex_destroy(&mc->multi_mutex);
+	if (status)
+		fatal(status);
+
 	free(mc->hash);
 	free(mc->ino_index);
 	free(mc);
diff --git a/lib/master.c b/lib/master.c
index 3cf0428..ea213ad 100644
--- a/lib/master.c
+++ b/lib/master.c
@@ -1142,3 +1142,13 @@ int master_kill(struct master *master)
 	return 1;
 }
 
+void dump_master(struct master *master)
+{
+	struct list_head *p, *head;
+
+	head = &master->mounts;
+	list_for_each(p, head) {
+		struct master_mapent *this = list_entry(p, struct master_mapent, list);
+		debug(LOGOPT_ANY, "path %s", this->path);
+	}
+}
diff --git a/modules/lookup_hosts.c b/modules/lookup_hosts.c
index 0e5152e..16fd1bd 100644
--- a/modules/lookup_hosts.c
+++ b/modules/lookup_hosts.c
@@ -76,11 +76,17 @@ int lookup_read_master(struct master *ma
 
 int lookup_read_map(struct autofs_point *ap, time_t age, void *context)
 {
-	struct map_source *source = ap->entry->current;
-	struct mapent_cache *mc = source->mc;
+	struct map_source *source;
+	struct mapent_cache *mc;
 	struct hostent *host;
 	int status;
 
+	source = ap->entry->current;
+	ap->entry->current = NULL;
+	master_source_current_signal(ap->entry);
+
+	mc = source->mc;
+
 	status = pthread_mutex_lock(&hostent_mutex);
 	if (status) {
 		error(LOGOPT_ANY, MODPREFIX "failed to lock hostent mutex");
@@ -107,8 +113,8 @@ int lookup_read_map(struct autofs_point 
 int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *context)
 {
 	struct lookup_context *ctxt = (struct lookup_context *) context;
-	struct map_source *source = ap->entry->current;
-	struct mapent_cache *mc = source->mc;
+	struct map_source *source;
+	struct mapent_cache *mc;
 	struct mapent *me;
 	char buf[MAX_ERR_BUF];
 	char *mapent = NULL;
@@ -118,6 +124,12 @@ int lookup_mount(struct autofs_point *ap
 	int status = NSS_STATUS_UNKNOWN;
 	int ret;
 
+	source = ap->entry->current;
+	ap->entry->current = NULL;
+	master_source_current_signal(ap->entry);
+
+	mc = source->mc;
+
 	cache_readlock(mc);
 	me = cache_lookup_distinct(mc, name);
 	if (!me) {
@@ -168,6 +180,9 @@ done:
 		return status;
 
 	if (mapent) {
+		master_source_current_wait(ap->entry);
+		ap->entry->current = source;
+
 		debug(ap->logopt, MODPREFIX "%s -> %s", name, me->mapent);
 		ret = ctxt->parse->parse_mount(ap, name, name_len,
 				 mapent, ctxt->parse->context);
@@ -238,6 +253,9 @@ done:
 	cache_update(mc, source, name, mapent, now);
 	cache_unlock(mc);
 
+	master_source_current_wait(ap->entry);
+	ap->entry->current = source;
+
 	ret = ctxt->parse->parse_mount(ap, name, name_len,
 				 mapent, ctxt->parse->context);
 	free(mapent);
diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
index 7986d3b..0bcd249 100644
--- a/modules/lookup_ldap.c
+++ b/modules/lookup_ldap.c
@@ -1541,7 +1541,7 @@ static int check_map_indirect(struct aut
 	if (ap->ghost && need_map) {
 		int status;
 
-		ap->entry->current->stale = 1;
+		source->stale = 1;
 
 		status = pthread_mutex_lock(&ap->state_mutex);
 		if (status)
diff --git a/modules/lookup_nisplus.c b/modules/lookup_nisplus.c
index 4049f1b..4bc8820 100644
--- a/modules/lookup_nisplus.c
+++ b/modules/lookup_nisplus.c
@@ -422,7 +422,7 @@ static int check_map_indirect(struct aut
 	if (ap->ghost && need_map) {
 		int status;
 
-		ap->entry->current->stale = 1;
+		source->stale = 1;
 
 		status = pthread_mutex_lock(&ap->state_mutex);
 		if (status)
diff --git a/modules/lookup_program.c b/modules/lookup_program.c
index c7c2418..9c69b6f 100644
--- a/modules/lookup_program.c
+++ b/modules/lookup_program.c
@@ -105,8 +105,8 @@ int lookup_read_map(struct autofs_point 
 int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *context)
 {
 	struct lookup_context *ctxt = (struct lookup_context *) context;
-	struct map_source *source = ap->entry->current;
-	struct mapent_cache *mc = source->mc;
+	struct map_source *source;
+	struct mapent_cache *mc;
 	char *mapent = NULL, *mapp, *tmp;
 	struct mapent *me;
 	char buf[MAX_ERR_BUF];
@@ -124,6 +124,12 @@ int lookup_mount(struct autofs_point *ap
 	int distance;
 	int alloci = 1;
 
+	source = ap->entry->current;
+	ap->entry->current = NULL;
+	master_source_current_signal(ap->entry);
+
+	mc = source->mc;
+
 	/* Catch installed direct offset triggers */
 	cache_readlock(mc);
 	me = cache_lookup_distinct(mc, name);
@@ -143,6 +149,9 @@ int lookup_mount(struct autofs_point *ap
 		/* Otherwise we found a valid offset so try mount it */
 		debug(ap->logopt, MODPREFIX "%s -> %s", name, me->mapent);
 
+		master_source_current_wait(ap->entry);
+		ap->entry->current = source;
+
 		ret = ctxt->parse->parse_mount(ap, name, name_len,
 				      me->mapent, ctxt->parse->context);
 		goto out_free;
@@ -336,6 +345,9 @@ int lookup_mount(struct autofs_point *ap
 
 	debug(ap->logopt, MODPREFIX "%s -> %s", name, mapent);
 
+	master_source_current_wait(ap->entry);
+	ap->entry->current = source;
+
 	ret = ctxt->parse->parse_mount(ap, name, name_len,
 				       mapent, ctxt->parse->context);
 out_free:
diff --git a/modules/lookup_yp.c b/modules/lookup_yp.c
index 741e6ec..fcee26b 100644
--- a/modules/lookup_yp.c
+++ b/modules/lookup_yp.c
@@ -526,7 +526,7 @@ static int check_map_indirect(struct aut
 	if (ap->ghost && need_map) {
 		int status;
 
-		ap->entry->current->stale = 1;
+		source->stale = 1;
 
 		status = pthread_mutex_lock(&ap->state_mutex);
 		if (status)
diff --git a/modules/parse_sun.c b/modules/parse_sun.c
index 929698f..ca80bad 100644
--- a/modules/parse_sun.c
+++ b/modules/parse_sun.c
@@ -666,8 +666,10 @@ add_offset_entry(struct autofs_point *ap
 	} else
 		strcpy(m_mapent, loc);
 
-	cache_writelock(mc);
+	cache_readlock(mc);
+	cache_multi_lock(mc);
 	ret = cache_add_offset(mc, name, m_key, m_mapent, age);
+	cache_multi_unlock(mc);
 	cache_unlock(mc);
 
 	if (ret == CHE_OK)
@@ -1088,8 +1090,10 @@ int parse_mount(struct autofs_point *ap,
 
 			if (!path) {
 				error(ap->logopt, MODPREFIX "out of memory");
-				cache_writelock(mc);
+				cache_readlock(mc);
+				cache_multi_lock(mc);
 				cache_delete_offset_list(mc, name);
+				cache_multi_unlock(mc);
 				cache_unlock(mc);
 				free(options);
 				return 1;
@@ -1097,8 +1101,10 @@ int parse_mount(struct autofs_point *ap,
 
 			if (!*path) {
 				error(ap->logopt, MODPREFIX "invalid path");
-				cache_writelock(mc);
+				cache_readlock(mc);
+				cache_multi_lock(mc);
 				cache_delete_offset_list(mc, name);
+				cache_multi_unlock(mc);
 				cache_unlock(mc);
 				free(path);
 				free(options);
@@ -1110,8 +1116,10 @@ int parse_mount(struct autofs_point *ap,
 
 			l = parse_mapent(p, options, &myoptions, &loc, ap->logopt);
 			if (!l) {
-				cache_writelock(mc);
+				cache_readlock(mc);
+				cache_multi_lock(mc);
 				cache_delete_offset_list(mc, name);
+				cache_multi_unlock(mc);
 				cache_unlock(mc);
 				free(path);
 				free(options);
@@ -1130,8 +1138,10 @@ int parse_mount(struct autofs_point *ap,
 
 			if (status != CHE_OK) {
 				error(ap->logopt, MODPREFIX "error adding multi-mount");
-				cache_writelock(mc);
+				cache_readlock(mc);
+				cache_multi_lock(mc);
 				cache_delete_offset_list(mc, name);
+				cache_multi_unlock(mc);
 				cache_unlock(mc);
 				free(path);
 				free(options);
@@ -1145,8 +1155,20 @@ int parse_mount(struct autofs_point *ap,
 			free(myoptions);
 		} while (*p == '/');
 
-		/* Mount root offset if it exists */
 		cache_readlock(mc);
+		if (!me) {
+			error(ap->logopt,
+			      MODPREFIX
+			      "failed to find cache entry for %s", name);
+			cache_multi_lock(mc);
+			cache_delete_offset_list(mc, name);
+			cache_multi_unlock(mc);
+			cache_unlock(mc);
+			free(options);
+			return 1;
+		}
+
+		/* Mount root offset if it exists */
 		ro = cache_lookup_offset("/", "/", strlen(m_root), &me->multi_list);
 		if (ro) {
 			char *myoptions, *loc;
@@ -1154,11 +1176,11 @@ int parse_mount(struct autofs_point *ap,
 			rv = parse_mapent(ro->mapent,
 				options, &myoptions, &loc, ap->logopt);
 			if (!rv) {
-				cache_unlock(mc);
 				error(ap->logopt,
 				      MODPREFIX "mount of root offset failed");
-				cache_writelock(mc);
+				cache_multi_lock(mc);
 				cache_delete_offset_list(mc, name);
+				cache_multi_unlock(mc);
 				cache_unlock(mc);
 				free(options);
 				return 1;
@@ -1171,12 +1193,12 @@ int parse_mount(struct autofs_point *ap,
 			free(loc);
 
 			if (rv < 0) {
-				cache_unlock(mc);
 				error(ap->logopt,
 				      MODPREFIX
 				      "mount multi-mount root %s failed", name);
-				cache_writelock(mc);
+				cache_multi_lock(mc);
 				cache_delete_offset_list(mc, name);
+				cache_multi_unlock(mc);
 				cache_unlock(mc);
 				free(options);
 				return rv;
@@ -1184,12 +1206,8 @@ int parse_mount(struct autofs_point *ap,
 		}
 
 		if (!mount_multi_triggers(ap, m_root, me, "/")) {
-			cache_unlock(mc);
 			error(ap->logopt,
 			      MODPREFIX "failed to mount offset triggers");
-			cache_writelock(mc);
-			cache_delete_offset_list(mc, name);
-			cache_unlock(mc);
 			free(options);
 			return 1;
 		}
@@ -1340,11 +1358,13 @@ int parse_mount(struct autofs_point *ap,
 
 			base = &me->key[start];
 
+			cache_multi_lock(mc);
 			if (!mount_multi_triggers(ap, m_root, me->multi, base)) {
 				error(ap->logopt,
 				      MODPREFIX "failed to mount offset triggers");
 				rv = 1;
 			}
+			cache_multi_unlock(mc);
 		}
 		cache_unlock(mc);
 	}
