diff --git a/CHANGELOG b/CHANGELOG
index b0a255a..3baff69 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -14,6 +14,7 @@
   with various combinations of submounts (still broken).
 - cthon fix expire of various forms of nested mounts.
 - cthon fix some shutdown races.
+- cthon corrections for above patch and fix shutdown expire.
 
 13/7/2006 autofs-5.0.1 rc1
 --------------------------
diff --git a/daemon/automount.c b/daemon/automount.c
index 35d443c..ff05ae2 100644
--- a/daemon/automount.c
+++ b/daemon/automount.c
@@ -198,8 +198,6 @@ 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]);
@@ -387,7 +385,7 @@ int umount_multi(struct autofs_point *ap
 
 		me = lookup_source_mapent(ap, ind_key);
 		if (!me) {
-			warn(ap->logopt, "no mounts found under %s", path);
+			warn(ap->logopt, "map entry not found for %s", path);
 			return 0;
 		}
 	}
@@ -421,7 +419,7 @@ int umount_multi(struct autofs_point *ap
 	}
 	cache_unlock(me->source->mc);
 
-	if (left || is_autofs_fs || ap->submount)
+	if (left || is_autofs_fs)
 		return left;
 
 	/*
@@ -1034,10 +1032,8 @@ static void handle_mounts_cleanup(void *
 	st_remove_tasks(ap);
 	umount_autofs(ap, 1);
 
-	if (submount)
-		master_signal_submount(ap, MASTER_SUBMNT_JOIN);
-	else
-		master_remove_mapent(ap->entry);
+	master_signal_submount(ap, MASTER_SUBMNT_JOIN);
+	master_remove_mapent(ap->entry);
 	master_free_mapent_sources(ap->entry, 1);
 	master_free_mapent(ap->entry);
 
@@ -1161,8 +1157,8 @@ void *handle_mounts(void *arg)
 	 * So, the solution is a recipe for disaster.
 	 * Hope we don't get a really busy system!
 	 */
-	sleep(1);
-	/* sched_yield(); */
+	/*sleep(1);*/
+	sched_yield();
 
 	return NULL;
 }
diff --git a/daemon/direct.c b/daemon/direct.c
index a2aea9c..c155617 100644
--- a/daemon/direct.c
+++ b/daemon/direct.c
@@ -112,13 +112,13 @@ static int autofs_init_direct(struct aut
 int do_umount_autofs_direct(struct autofs_point *ap, struct mnt_list *mnts, struct mapent *me)
 {
 	char buf[MAX_ERR_BUF];
-	int ioctlfd, rv, left;
+	int ioctlfd, rv, left, retries;
 
 	left = umount_multi(ap, me->key, 1);
 	if (left) {
 		warn(ap->logopt, "could not unmount %d dirs under %s",
 		     left, me->key);
-		return -1;
+		return 1;
 	}
 
 	if (me->ioctlfd != -1) {
@@ -161,9 +161,19 @@ int do_umount_autofs_direct(struct autof
 		error(ap->logopt,
 		      "couldn't get ioctl fd for offset %s", me->key);
 		debug(ap->logopt, "open: %s", estr);
+		return 1;
+	}
+
+	sched_yield();
+
+	retries = UMOUNT_RETRIES;
+	while ((rv = umount(me->key)) == -1 && retries--) {
+		struct timespec tm = {0, 100000000};
+		if (errno != EBUSY)
+			break;
+		nanosleep(&tm, NULL);
 	}
 
-	rv = umount(me->key);
 	if (rv == -1) {
 		switch (errno) {
 		case ENOENT:
@@ -230,7 +240,6 @@ int umount_autofs_direct(struct autofs_p
 		cache_readlock(mc);
 		me = cache_enumerate(mc, NULL);
 		while (me) {
-			sched_yield();
 			/* TODO: check return, locking me */
 			do_umount_autofs_direct(ap, mnts, me);
 			me = cache_enumerate(mc, me);
@@ -491,7 +500,7 @@ int mount_autofs_direct(struct autofs_po
 int umount_autofs_offset(struct autofs_point *ap, struct mapent *me)
 {
 	char buf[MAX_ERR_BUF];
-	int ioctlfd, rv = 1;
+	int ioctlfd, rv = 1, retries;
 
 	if (me->ioctlfd != -1) {
 		if (is_mounted(_PATH_MOUNTED, me->key, MNTS_REAL)) {
@@ -543,7 +552,16 @@ int umount_autofs_offset(struct autofs_p
 		goto force_umount;
 	}
 
-	rv = umount(me->key);
+	sched_yield();
+
+	retries = UMOUNT_RETRIES;
+	while ((rv = umount(me->key)) == -1 && retries--) {
+		struct timespec tm = {0, 100000000};
+		if (errno != EBUSY)
+			break;
+		nanosleep(&tm, NULL);
+	}
+
 	if (rv == -1) {
 		switch (errno) {
 		case ENOENT:
@@ -703,6 +721,49 @@ out_err:
 	return -1;
 }
 
+static int expire_direct(int ioctlfd, const char *path, unsigned int when, int count, unsigned int logopt)
+{
+	char *estr, buf[MAX_ERR_BUF];
+	int ret, retries = count;
+
+	while (retries--) {
+		struct timespec tm = {0, 100000000};
+		int busy = 0;
+
+		ret = ioctl(ioctlfd, AUTOFS_IOC_ASKUMOUNT, &busy);
+		if (ret == -1) {
+			/* Mount has gone away */
+			if (errno == EBADF)
+				return 1;
+
+			estr = strerror_r(errno, buf, MAX_ERR_BUF);
+			error(logopt, "ioctl failed: %s", estr);
+			return 0;
+		}
+
+		/* No need to go further */
+		if (busy)
+			return 0;
+
+		sched_yield();
+
+		/* Ggenerate expire message for the mount. */
+		ret = ioctl(ioctlfd, AUTOFS_IOC_EXPIRE_DIRECT, &when);
+		if (ret == -1) {
+			/* Mount has gone away */
+			if (errno == EBADF)
+				return 1;
+
+			/* Need to wait for the kernel ? */
+			if (errno != EAGAIN)
+				return 0;
+		}
+		nanosleep(&tm, NULL);
+	}
+
+	return 1;
+}
+
 void *expire_proc_direct(void *arg)
 {
 	struct map_source *map;
@@ -710,7 +771,7 @@ void *expire_proc_direct(void *arg)
 	struct expire_args *ea;
 	struct autofs_point *ap;
 	struct mapent_cache *mc = NULL;
-	struct mapent *ro, *me = NULL;
+	struct mapent *me = NULL;
 	unsigned int now;
 	int ioctlfd = -1;
 	int status, ret;
@@ -751,11 +812,9 @@ void *expire_proc_direct(void *arg)
 			continue;
 
 		/* Skip offsets */
-		if (strstr(next->opts, "offsets"))
+		if (strstr(next->opts, "offset"))
 			continue;
 
-		sched_yield();
-
 		/*
 		 * All direct mounts must be present in the map
 		 * entry cache.
@@ -787,48 +846,16 @@ void *expire_proc_direct(void *arg)
 
 		debug(ap->logopt, "send expire to trigger %s", next->path);
 
-		/* Finally generate an expire message for the direct mount. */
-		ret = ioctl(ioctlfd, AUTOFS_IOC_EXPIRE_DIRECT, &now);
-		if (ret < 0 && errno != EAGAIN) {
+		ret = expire_direct(ioctlfd, next->path,
+				    now, EXPIRE_RETRIES, ap->logopt);
+		if (!ret) {
 			debug(ap->logopt,
-			      "failed to expire mount %s", next->path);
-			ea->status = 1;
+			     "failed to expire mount %s", next->path);
+			ea->status++;
 		}
 	}
 	free_mnt_list(mnts);
 
-	pthread_cleanup_push(master_source_lock_cleanup, ap->entry);
-	master_source_readlock(ap->entry);
-	map = ap->entry->first;
-	while (map) {
-		mc = map->mc;
-		pthread_cleanup_push(cache_lock_cleanup, mc);
-		cache_readlock(mc);
-		me = cache_enumerate(mc, NULL);
-		while (me) {
-			sched_yield();
-
-			if (me->ioctlfd >= 0)
-				/* Real mounts have an open ioctl fd */
-				ioctlfd = me->ioctlfd;
-			else {
-				me = cache_enumerate(mc, me);
-				continue;
-			}
-
-			if (!ioctl(ioctlfd, AUTOFS_IOC_ASKUMOUNT, &ret)) {
-				if (!ret) {
-					ea->status = 1;
-					break;
-				}
-			}
-			me = cache_enumerate(mc, me);
-		}
-		pthread_cleanup_pop(1);
-		map = map->next;
-	}
-
-	pthread_cleanup_pop(1);
 	pthread_cleanup_pop(1);
 
 	return NULL;
diff --git a/daemon/indirect.c b/daemon/indirect.c
index 406bf72..af84629 100644
--- a/daemon/indirect.c
+++ b/daemon/indirect.c
@@ -281,8 +281,7 @@ int mount_autofs_indirect(struct autofs_
 int umount_autofs_indirect(struct autofs_point *ap)
 {
 	char buf[MAX_ERR_BUF];
-	struct stat st;
-	int ret, rv;
+	int ret, rv, retries;
 
 	/*
 	 * Since submounts look after themselves the parent never knows
@@ -318,7 +317,16 @@ int umount_autofs_indirect(struct autofs
 	if (ap->kpipefd >= 0)
 		close(ap->kpipefd);
 
-	rv = umount(ap->path);
+	sched_yield();
+
+	retries = UMOUNT_RETRIES;
+	while ((rv = umount(ap->path)) == -1 && retries--) {
+		struct timespec tm = {0, 100000000};
+		if (errno != EBUSY)
+			break;
+		nanosleep(&tm, NULL);
+	}
+
 	if (rv == -1) {
 		switch (errno) {
 		case ENOENT:
@@ -356,6 +364,50 @@ force_umount:
 	return rv;
 }
 
+static int expire_indirect(int ioctlfd, const char *path, unsigned int when, int count, unsigned int logopt)
+{
+	char *estr, buf[MAX_ERR_BUF];
+	int ret, retries = count;
+
+	while (retries--) {
+		struct timespec tm = {0, 100000000};
+		int busy = 0;
+
+		ret = ioctl(ioctlfd, AUTOFS_IOC_ASKUMOUNT, &busy);
+		if (ret == -1) {
+			/* Mount has gone away */
+			if (errno == EBADF)
+				return 1;
+
+			estr = strerror_r(errno, buf, MAX_ERR_BUF);
+			error(logopt, "ioctl failed: %s", estr);
+			return 0;
+		}
+
+		/* No need to go further */
+		if (busy)
+			return 0;
+
+		sched_yield();
+
+		/* Ggenerate expire message for the mount. */
+		ret = ioctl(ioctlfd, AUTOFS_IOC_EXPIRE_DIRECT, &when);
+		if (ret == -1) {
+			/* Mount has gone away */
+			if (errno == EBADF)
+				return 1;
+
+			/* Need to wait for the kernel ? */
+			if (errno != EAGAIN)
+				return 0;
+		}
+
+		nanosleep(&tm, NULL);
+	}
+
+	return 1;
+}
+
 void *expire_proc_indirect(void *arg)
 {
 	struct map_source *map;
@@ -368,7 +420,6 @@ void *expire_proc_indirect(void *arg)
 	int offsets, submnts, count;
 	int ioctlfd, limit;
 	int status, ret;
-	char buf[MAX_ERR_BUF];
 
 	ea = (struct expire_args *) arg;
 
@@ -407,8 +458,6 @@ void *expire_proc_indirect(void *arg)
 		if (!strcmp(next->fs_type, "autofs"))
 			continue;
 
-		sched_yield();
-
 		/*
 		 * If the mount corresponds to an offset trigger then
 		 * the key is the path, otherwise it's the last component.
@@ -452,14 +501,13 @@ void *expire_proc_indirect(void *arg)
 
 		debug(ap->logopt, "expire %s", next->path);
 
-		ret = ioctl(ioctlfd, AUTOFS_IOC_EXPIRE_MULTI, &now);
-		if (ret < 0 && errno != EAGAIN) {
-			char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-			warn(ap->logopt,
-			     "failed to expire mount %s:", next->path, estr);
-			ea->status = 1;
+		ret = expire_indirect(ioctlfd, next->path,
+				      now, EXPIRE_RETRIES, ap->logopt);
+		if (!ret) {
+			debug(ap->logopt,
+			      "failed to expire mount %s", next->path);
+			ea->status++;
 		}
-
 	}
 	free_mnt_list(mnts);
 
@@ -469,17 +517,11 @@ void *expire_proc_indirect(void *arg)
 	 * umount them here.
 	 */
 	limit = count_mounts(ap, ap->path);
-	while (limit--) {
-		ret = ioctl(ap->ioctlfd, AUTOFS_IOC_EXPIRE_MULTI, &now);
-		if (ret < 0) {
-			if (errno == EAGAIN)
-				break;
-			warn(ap->logopt,
-			      "failed to expire offsets under %s",
-			      ap->path);
-			ea->status = 1;
-			break;
-		}
+	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++;
 	}
 
 	count = offsets = submnts = 0;
diff --git a/include/automount.h b/include/automount.h
index 4c4d507..800e7b0 100644
--- a/include/automount.h
+++ b/include/automount.h
@@ -123,6 +123,8 @@ #define CHE_DUPLICATE	0x0020
 
 #define HASHSIZE		77
 #define NEGATIVE_TIMEOUT	10
+#define UMOUNT_RETRIES		25
+#define EXPIRE_RETRIES		15
 
 struct mapent_cache {
 	pthread_rwlock_t rwlock;
diff --git a/lib/master.c b/lib/master.c
index bcda72a..d76ffac 100644
--- a/lib/master.c
+++ b/lib/master.c
@@ -131,13 +131,6 @@ void master_free_autofs_point(struct aut
 	if (!ap)
 		return;
 
-	if (ap->submount) {
-		mounts_mutex_lock(ap);
-		ap->parent->submnt_count--;
-		list_del(&ap->mounts);
-		mounts_mutex_unlock(ap);
-	}
-
 	status = pthread_mutex_destroy(&ap->state_mutex);
 	if (status)
 		fatal(status);
@@ -631,6 +624,9 @@ void master_add_mapent(struct master *ma
 
 void master_remove_mapent(struct master_mapent *entry)
 {
+	if (entry->ap->submount)
+		return;
+
 	master_mutex_lock();
 	if (!list_empty(&entry->list))
 		list_del_init(&entry->list);
@@ -739,13 +735,17 @@ int master_read_master(struct master *ma
 	return 1;
 }
 
-static void notify_submounts(struct autofs_point *ap, enum states state)
+void master_notify_submounts(struct autofs_point *ap, enum states state)
 {
 	struct list_head *head, *p;
 	struct autofs_point *this;
 	pthread_t thid;
 	int status;
 
+	/* Initiate from master entries only */
+	if (ap->submount || list_empty(&ap->submounts))
+		return;
+
 	mounts_mutex_lock(ap);
 
 	head = &ap->submounts;
@@ -756,7 +756,7 @@ static void notify_submounts(struct auto
 		p = p->next;
 
 		if (!list_empty(&this->submounts))
-			notify_submounts(this, state);
+			master_notify_submounts(this, state);
 
 		state_mutex_lock(this);
 
@@ -776,11 +776,9 @@ static void notify_submounts(struct auto
 			if (status)
 				fatal(status);
 			if (ap->mounts_signaled == MASTER_SUBMNT_JOIN) {
-				mounts_mutex_unlock(ap);
 				status = pthread_join(thid, NULL);
 				if (status)
 					fatal(status);
-				mounts_mutex_lock(ap);
 			}
 		}
 	}
@@ -790,30 +788,23 @@ static void notify_submounts(struct auto
 	return;
 }
 
-void master_notify_submounts(struct autofs_point *ap, enum states state)
-{
-	/* Initiate from master entries only */
-	if (ap->submount || list_empty(&ap->submounts))
-		return;
-	master_mutex_lock();
-	notify_submounts(ap, state);
-	master_mutex_unlock();
-	return;
-}
-
 void master_signal_submount(struct autofs_point *ap, unsigned int join)
 {
 	int status;
 
-	if (!ap->parent)
+	if (!ap->parent || !ap->submount)
 		return;
 
 	mounts_mutex_lock(ap->parent);
 
-	if (join)
+	if (join) {
+		/* We are finishing up */
+		ap->parent->submnt_count--;
+		list_del(&ap->mounts);
 		ap->parent->mounts_signaled = 1;
-	else
+	} else
 		ap->parent->mounts_signaled = 2;
+
 	status = pthread_cond_signal(&ap->parent->mounts_cond);
 	if (status)
 		fatal(status);