diff --git a/CHANGELOG b/CHANGELOG
index fc939ad..1969912 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -27,6 +27,7 @@
 - expire individual submounts.
 - add ino_index locking.
 - fix nested submount expiring away when pwd is base of submount.
+- more expire re-work to cope better with shutdown following cthon tests.
 
 13/7/2006 autofs-5.0.1 rc1
 --------------------------
diff --git a/daemon/automount.c b/daemon/automount.c
index cc6e9e0..446c184 100644
--- a/daemon/automount.c
+++ b/daemon/automount.c
@@ -304,12 +304,12 @@ static int counter_fn(const char *file, 
 }
 
 /* Count mounted filesystems and symlinks */
-int count_mounts(struct autofs_point *ap, const char *path)
+int count_mounts(const char *path, dev_t dev)
 {
 	struct counter_args counter;
 
 	counter.count = 0;
-	counter.dev = ap->dev;
+	counter.dev = dev;
 	
 	if (walk_tree(path, counter_fn, 0, &counter) == -1)
 		return -1;
@@ -366,26 +366,12 @@ static void update_map_cache(struct auto
 	return;
 }
 
-/* umount all filesystems mounted under path.  If incl is true, then
-   it also tries to umount path itself */
-int umount_multi(struct autofs_point *ap, const char *path, int incl)
+static int umount_subtree_mounts(struct autofs_point *ap, const char *path, unsigned int is_autofs_fs)
 {
 	struct mapent_cache *mc;
 	struct mapent *me;
-	struct statfs fs;
-	int is_autofs_fs;
-	int ret, left;
 	unsigned int is_mm_root;
-
-	debug(ap->logopt, "path %s incl %d", path, incl);
-
-	ret = statfs(path, &fs);
-	if (ret == -1) {
-		error(ap->logopt, "could not stat fs of %s", path);
-		return 1;
-	}
-
-	is_autofs_fs = fs.f_type == AUTOFS_SUPER_MAGIC ? 1 : 0;
+	int left;
 
 	me = lookup_source_mapent(ap, path, LKP_DISTINCT);
 	if (!me) {
@@ -395,74 +381,104 @@ int umount_multi(struct autofs_point *ap
 		if (ind_key)
 			ind_key++;
 
-		me = lookup_source_mapent(ap, ind_key, LKP_DISTINCT);
-		if (!me) {
-			warn(ap->logopt, "map entry not found for %s", path);
+		me = lookup_source_mapent(ap, ind_key, LKP_NORMAL);
+		if (!me)
 			return 0;
-		}
 	}
 
-	cache_multi_lock(me->parent);
-
 	mc = me->source->mc;
 	is_mm_root = (me->multi == me);
 
 	left = 0;
 
 	if (me->multi) {
-		struct autofs_point *oap = ap;
 		char *root, *base;
+		size_t ap_len;
 
-		if (ap->submount)
-			oap = ap->parent;
+		ap_len = strlen(ap->path);
 
-		if (is_mm_root && !strchr(me->key, '/')) {
+		if (!strchr(me->multi->key, '/')) {
 			/* Indirect multi-mount root */
-			root = alloca(strlen(ap->path) + strlen(me->key) + 2);
+			root = alloca(ap_len + strlen(me->multi->key) + 2);
 			strcpy(root, ap->path);
 			strcat(root, "/");
-			strcat(root, me->key);
-			base = NULL;
-		} else {
+			strcat(root, me->multi->key);
+		} else
 			root = me->multi->key;
+
+		if (is_mm_root)
+			base = NULL;
+		else
 			base = me->key + strlen(root);
-		}
 
-		if (umount_multi_triggers(oap, root, me, base)) {
+		/* Lock the closest parent nesting point for umount */
+		cache_multi_lock(me->parent);
+		if (umount_multi_triggers(ap, root, me, base)) {
 			warn(ap->logopt,
 			     "could not umount some offsets under %s", path);
 			left++;
 		}
+		cache_multi_unlock(me->parent);
 	}
 
-	if (left || is_autofs_fs) {
-		cache_multi_unlock(me->parent);
-		cache_unlock(mc);
+	cache_unlock(mc);
+
+	if (left || is_autofs_fs)
 		return left;
-	}
 
 	/*
 	 * If this is the root of a multi-mount we've had to umount
-	 * it already to ensure it's ok to remove any offset triggers
+	 * it already to ensure it's ok to remove any offset triggers.
 	 */
-	if (!is_mm_root) {
+	if (!is_mm_root && is_mounted(_PATH_MOUNTED, path, MNTS_REAL)) {
 		msg("unmounting dir = %s", path);
-
 		if (umount_ent(ap, path)) {
 			warn(ap->logopt, "could not umount dir %s", path);
 			left++;
 		}
 	}
 
+	return left;
+}
+
+/* umount all filesystems mounted under path.  If incl is true, then
+   it also tries to umount path itself */
+int umount_multi(struct autofs_point *ap, const char *path, int incl)
+{
+	struct statfs fs;
+	int is_autofs_fs;
+	int ret, left;
+
+	debug(ap->logopt, "path %s incl %d", path, incl);
+
+	ret = statfs(path, &fs);
+	if (ret == -1) {
+		error(ap->logopt, "could not stat fs of %s", path);
+		return 1;
+	}
+
+	is_autofs_fs = fs.f_type == AUTOFS_SUPER_MAGIC ? 1 : 0;
+
+	left = 0;
+
+	/*
+	 * If we are a submount we need to umount any offsets our
+	 * parent may have mounted over top of us.
+	 */
+	/*if (ap->submount)
+		left += umount_subtree_mounts(ap->parent, path, is_autofs_fs);*/
+
+	left += umount_subtree_mounts(ap, path, is_autofs_fs);
+
+	if (left || is_autofs_fs)
+		return left;
+
 	/* Delete detritus like unwanted mountpoints and symlinks */
 	if (left == 0) {
 		update_map_cache(ap, path);
 		check_rm_dirs(ap, path, incl);
 	}
 
-	cache_multi_unlock(me->parent);
-	cache_unlock(mc);
-
 	return left;
 }
 
diff --git a/daemon/direct.c b/daemon/direct.c
index b9c0f04..18b56fe 100644
--- a/daemon/direct.c
+++ b/daemon/direct.c
@@ -33,6 +33,7 @@ #include <sys/stat.h>
 #include <sys/time.h>
 #include <sys/poll.h>
 #include <sys/mount.h>
+#include <sys/vfs.h>
 #include <sched.h>
 #include <pwd.h>
 #include <grp.h>
@@ -114,7 +115,7 @@ int do_umount_autofs_direct(struct autof
 	char buf[MAX_ERR_BUF];
 	int ioctlfd, rv, left, retries;
 
-	left = umount_multi(ap, me->key, 1);
+	left = umount_multi(ap, me->key, 0);
 	if (left) {
 		warn(ap->logopt, "could not unmount %d dirs under %s",
 		     left, me->key);
@@ -258,9 +259,9 @@ static int unlink_mount_tree(struct auto
 	struct list_head *p;
 	int rv, ret;
 	pid_t pgrp = getpgrp();
-	char spgrp[10];
+	char spgrp[20];
 
-	sprintf(spgrp, "%d", pgrp);
+	sprintf(spgrp, "pgrp=%d", pgrp);
 
 	ret = 1;
 	list_for_each(p, list) {
@@ -727,7 +728,17 @@ out_err:
 
 static int expire_direct(int ioctlfd, const char *path, unsigned int when, unsigned int logopt)
 {
-	int ret, retries = EXPIRE_RETRIES;
+	char buf[MAX_ERR_BUF];
+	int ret, retries;
+	struct stat st;
+
+	if (fstat(ioctlfd, &st) == -1) {
+		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+		error(logopt, "fstat failed: %s", estr);
+		return 0;
+	}
+
+	retries = (count_mounts(path, st.st_dev) + 1) * EXPIRE_RETRIES;
 
 	while (retries--) {
 		struct timespec tm = {0, 100000000};
@@ -747,7 +758,7 @@ static int expire_direct(int ioctlfd, co
 		nanosleep(&tm, NULL);
 	}
 
-	return 1;
+	return (retries >= 0);
 }
 
 void *expire_proc_direct(void *arg)
@@ -824,10 +835,8 @@ void *expire_proc_direct(void *arg)
 		debug(ap->logopt, "send expire to trigger %s", next->path);
 
 		ret = expire_direct(ioctlfd, next->path, now, ap->logopt);
-		if (!ret) {
-			msg("mount apparently busy %s", next->path);
+		if (!ret)
 			ea->status++;
-		}
 	}
 	free_mnt_list(mnts);
 
diff --git a/daemon/indirect.c b/daemon/indirect.c
index dadb9ee..e04f164 100644
--- a/daemon/indirect.c
+++ b/daemon/indirect.c
@@ -82,9 +82,9 @@ static int unlink_mount_tree(struct auto
 	struct mnt_list *this;
 	int rv, ret;
 	pid_t pgrp = getpgrp();
-	char spgrp[10];
+	char spgrp[20];
 
-	sprintf(spgrp, "%d", pgrp);
+	sprintf(spgrp, "pgrp=%d", pgrp);
 
 	ret = 1;
 	this = mnts;
@@ -367,9 +367,19 @@ force_umount:
 	return rv;
 }
 
-static int expire_indirect(int ioctlfd, const char *path, unsigned int when, unsigned int count, unsigned int logopt)
+static int expire_indirect(struct autofs_point *ap, int ioctlfd, const char *path, unsigned int when)
 {
-	int ret, retries = count;
+	char buf[MAX_ERR_BUF];
+	int ret, retries;
+	struct stat st;
+
+	if (fstat(ioctlfd, &st) == -1) {
+		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+		error(ap->logopt, "fstat failed: %s", estr);
+		return 0;
+	}
+
+	retries = (count_mounts(path, st.st_dev) + 1) * EXPIRE_RETRIES;
 
 	while (retries--) {
 		struct timespec tm = {0, 100000000};
@@ -389,7 +399,7 @@ static int expire_indirect(int ioctlfd, 
 		nanosleep(&tm, NULL);
 	}
 
-	return 1;
+	return (retries >= 0);
 }
 
 void *expire_proc_indirect(void *arg)
@@ -400,9 +410,8 @@ void *expire_proc_indirect(void *arg)
 	struct expire_args *ea;
 	unsigned int now;
 	int offsets, submnts, count;
-	int ioctlfd, limit;
+	int ioctlfd;
 	int status, ret;
-	unsigned int retries = EXPIRE_RETRIES;
 
 	ea = (struct expire_args *) arg;
 
@@ -477,11 +486,9 @@ void *expire_proc_indirect(void *arg)
 
 		debug(ap->logopt, "expire %s", next->path);
 
-		ret = expire_indirect(ioctlfd, next->path, now, retries, ap->logopt);
-		if (!ret) {
-			msg("mount apparently busy %s", next->path);
+		ret = expire_indirect(ap, ioctlfd, next->path, now);
+		if (!ret)
 			ea->status++;
-		}
 	}
 	free_mnt_list(mnts);
 
@@ -490,12 +497,10 @@ void *expire_proc_indirect(void *arg)
 	 * have some offset mounts with no '/' offset so we need to
 	 * umount them here.
 	 */
-	limit = count_mounts(ap, ap->path) * 2;
-	ret = expire_indirect(ap->ioctlfd, ap->path, now, limit, ap->logopt);
-	if (!ret) {
-		debug(ap->logopt,
-		      "failed to expire offsets under %s", ap->path);
-		ea->status++;
+	if (mnts) {
+		ret = expire_indirect(ap, ap->ioctlfd, ap->path, now);
+		if (!ret)
+			ea->status++;
 	}
 
 	count = offsets = submnts = 0;
@@ -527,7 +532,7 @@ void *expire_proc_indirect(void *arg)
 	/* If we are trying to shutdown make sure we can umount */
 	if (!ioctl(ap->ioctlfd, AUTOFS_IOC_ASKUMOUNT, &ret)) {
 		if (!ret) {
-			warn(ap->logopt, "mount still busy %s", ap->path);
+			msg("mount still busy %s", ap->path);
 			ea->status++;
 		}
 	}
diff --git a/daemon/lookup.c b/daemon/lookup.c
index aeda909..dd620cf 100644
--- a/daemon/lookup.c
+++ b/daemon/lookup.c
@@ -969,7 +969,7 @@ next:
 }
 
 /* Return with cache readlock held */
-struct mapent *lookup_source_mapent(struct autofs_point *ap, const char *key, unsigned int type)
+struct mapent *lookup_source_valid_mapent(struct autofs_point *ap, const char *key, unsigned int type)
 {
 	struct master_mapent *entry = ap->entry;
 	struct map_source *map;
@@ -980,12 +980,49 @@ struct mapent *lookup_source_mapent(stru
 	master_source_readlock(entry);
 	map = entry->first;
 	while (map) {
+		/*
+		 * Only consider map sources that have been read since
+		 * the map entry was last updated.
+		 */
+		if (ap->entry->age > map->age) {
+			map = map->next;
+			continue;
+		}
+
 		mc = map->mc;
 		cache_readlock(mc);
 		if (type == LKP_DISTINCT)
 			me = cache_lookup_distinct(mc, key);
 		else
+			me = cache_lookup(mc, key);
+		if (me)
+			break;
+		cache_unlock(mc);
+		map = map->next;
+	}
+	pthread_cleanup_pop(1);
+
+	return me;
+}
+
+/* Return with cache readlock held */
+struct mapent *lookup_source_mapent(struct autofs_point *ap, const char *key, unsigned int type)
+{
+	struct master_mapent *entry = ap->entry;
+	struct map_source *map;
+	struct mapent_cache *mc;
+	struct mapent *me = NULL;
+
+	pthread_cleanup_push(master_source_lock_cleanup, entry);
+	master_source_readlock(entry);
+	map = entry->first;
+	while (map) {
+		mc = map->mc;
+		cache_readlock(mc);
+		if (type == LKP_DISTINCT)
 			me = cache_lookup_distinct(mc, key);
+		else
+			me = cache_lookup(mc, key);
 		if (me)
 			break;
 		cache_unlock(mc);
@@ -1012,8 +1049,10 @@ int lookup_source_close_ioctlfd(struct a
 		cache_readlock(mc);
 		me = cache_lookup_distinct(mc, key);
 		if (me) {
-			close(me->ioctlfd);
-			me->ioctlfd = -1;
+			if (me->ioctlfd != -1) {
+				close(me->ioctlfd);
+				me->ioctlfd = -1;
+			}
 			cache_unlock(mc);
 			ret = 1;
 			break;
diff --git a/include/automount.h b/include/automount.h
index 3192c92..e3ecc75 100644
--- a/include/automount.h
+++ b/include/automount.h
@@ -123,8 +123,8 @@ #define CHE_DUPLICATE	0x0020
 
 #define HASHSIZE		77
 #define NEGATIVE_TIMEOUT	10
-#define UMOUNT_RETRIES		50
-#define EXPIRE_RETRIES		25
+#define UMOUNT_RETRIES		6
+#define EXPIRE_RETRIES		3
 
 struct mapent_cache {
 	pthread_rwlock_t rwlock;
@@ -229,6 +229,7 @@ int lookup_ghost(struct autofs_point *ap
 int lookup_nss_mount(struct autofs_point *ap, const char *name, int name_len);
 void lookup_close_lookup(struct autofs_point *ap);
 int lookup_prune_cache(struct autofs_point *ap, time_t age);
+struct mapent *lookup_source_valid_mapent(struct autofs_point *ap, const char *key, unsigned int type);
 struct mapent *lookup_source_mapent(struct autofs_point *ap, const char *key, unsigned int type);
 int lookup_source_close_ioctlfd(struct autofs_point *ap, const char *key);
 
@@ -475,7 +476,7 @@ int handle_packet_expire_direct(struct a
 int handle_packet_missing_indirect(struct autofs_point *ap, autofs_packet_missing_indirect_t *pkt);
 int handle_packet_missing_direct(struct autofs_point *ap, autofs_packet_missing_direct_t *pkt);
 void rm_unwanted(const char *path, int incl, dev_t dev);
-int count_mounts(struct autofs_point *ap, const char *path);
+int count_mounts(const char *path, dev_t dev);
 
 #define state_mutex_lock(ap) \
 do { \
diff --git a/lib/alarm.c b/lib/alarm.c
index 8124796..89c9bc8 100755
--- a/lib/alarm.c
+++ b/lib/alarm.c
@@ -236,9 +236,9 @@ static void *alarm_handler(void *arg)
 			list_del(&current->list);
 			free(current);
 
-			alarm_unlock();
-			st_add_task(ap, ST_EXPIRE);
-			alarm_lock();
+			state_mutex_lock(ap);
+			nextstate(ap->state_pipe[1], ST_EXPIRE);
+			state_mutex_unlock(ap);
 
 			break;
 		}
diff --git a/modules/parse_sun.c b/modules/parse_sun.c
index 3f489ed..08fd34d 100644
--- a/modules/parse_sun.c
+++ b/modules/parse_sun.c
@@ -810,6 +810,54 @@ static int parse_mapent(const char *ent,
 	return (p - ent);
 }
 
+static int mount_subtree_offsets(struct autofs_point *ap, struct mapent_cache *mc, struct mapent *me)
+{
+	struct mapent *mm;
+	char *m_key;
+	int start;
+	char *base, *m_root;
+	char buf[MAX_ERR_BUF];
+
+	mm = me->multi;
+
+	if (!mm)
+		return 1;
+
+	cache_multi_lock(me->parent);
+
+	m_key = mm->key;
+
+	if (*m_key == '/') {
+		m_root = m_key;
+		start = strlen(m_key);
+	} else {
+		start = strlen(ap->path) + strlen(m_key) + 1;
+		m_root = alloca(start + 1);
+		if (!m_root) {
+			char *estr;
+			cache_multi_unlock(me->parent);
+			estr = strerror_r(errno, buf, MAX_ERR_BUF);
+			error(ap->logopt, MODPREFIX "alloca: %s", estr);
+			return 0;
+		}
+		strcpy(m_root, ap->path);
+		strcat(m_root, "/");
+		strcat(m_root, m_key);
+	}
+
+	base = &me->key[start];
+
+	if (!mount_multi_triggers(ap, m_root, me->multi, base)) {
+		cache_multi_unlock(me->parent);
+		error(ap->logopt, MODPREFIX "failed to mount offset triggers");
+		return 0;
+	}
+
+	cache_multi_unlock(me->parent);
+
+	return 1;
+}
+
 /*
  * syntax is:
  *	[-options] location [location] ...
@@ -1085,6 +1133,7 @@ int parse_mount(struct autofs_point *ap,
 			free(options);
 			return 1;
 		}
+
 		cache_multi_unlock(me);
 		cache_unlock(mc);
 
@@ -1093,7 +1142,6 @@ int parse_mount(struct autofs_point *ap,
 		return rv;
 	} else {
 		/* Normal (and non-root multi-mount) entries */
-		struct autofs_point *oap = ap;
 		char *loc;
 		int loclen;
 		int l;
@@ -1197,58 +1245,12 @@ int parse_mount(struct autofs_point *ap,
 		 * If it's a multi-mount insert the triggers
 		 * These are always direct mount triggers so root = ""
 		 */
-		if (ap->submount)
-			oap = ap->parent;
-
-		me = lookup_source_mapent(oap, name, LKP_DISTINCT);
+		cache_readlock(mc);
+		me = cache_lookup_distinct(mc, name);
 		if (me) {
-			struct mapent *mm;
-			char *m_key;
-			int start;
-			char *base, *m_root;
-
-			mc = me->source->mc;
-			mm = me->multi;
-
-			if (!me->multi) {
-				cache_unlock(mc);
-				return rv;
-			}
-
-			m_key = me->multi->key;
-
-			if (*m_key == '/') {
-				m_root = m_key;
-				start = strlen(m_key);
-			} else {
-				start = strlen(ap->path) + strlen(m_key) + 1;
-				pthread_cleanup_push(cache_lock_cleanup, mc);
-				m_root = alloca(start + 1);
-				pthread_cleanup_pop(0);
-				if (!m_root) {
-					char *estr;
-					cache_unlock(mc);
-					estr = strerror_r(errno, buf, MAX_ERR_BUF);
-					error(ap->logopt,
-					      MODPREFIX "alloca: %s", estr);
-					return 1;
-				}
-				strcpy(m_root, ap->path);
-				strcat(m_root, "/");
-				strcat(m_root, m_key);
-			}
-
-			base = &me->key[start];
-
-			cache_multi_lock(mm);
-			if (!mount_multi_triggers(oap, m_root, me->multi, base)) {
-				error(ap->logopt,
-				      MODPREFIX "failed to mount offset triggers");
-				rv = 1;
-			}
-			cache_multi_unlock(mm);
-			cache_unlock(mc);
+			mount_subtree_offsets(ap, mc, me);
 		}
+		cache_unlock(mc);
 	}
 	return rv;
 }
