diff --git a/CHANGELOG b/CHANGELOG
index 6fe9697..fe73ab8 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -24,6 +24,7 @@
 - review verbose message feedback and update.
 - correction for expire of multi-mounts.
 - spelling corrections to release notes (Jeff Moyer).
+- expire individual submounts.
 
 13/7/2006 autofs-5.0.1 rc1
 --------------------------
diff --git a/daemon/direct.c b/daemon/direct.c
index 4b6162b..b9c0f04 100644
--- a/daemon/direct.c
+++ b/daemon/direct.c
@@ -786,18 +786,23 @@ void *expire_proc_direct(void *arg)
 	if (status)
 		fatal(status);
 
-	master_notify_submounts(ap, ap->state);
-
 	/* Get a list of real mounts and expire them if possible */
 	mnts = get_mnt_list(_PROC_MOUNTS, "/", 0);
 	for (next = mnts; next; next = next->next) {
-		/* Skip submounts */
-		if (strstr(next->fs_type, "indirect"))
-			continue;
+		if (!strcmp(next->fs_type, "autofs")) {
+			/*
+			 * If we have submounts check if this path lives below
+			 * one of them and pass on state change.
+			 */
+			if (strstr(next->opts, "indirect")) {
+				master_notify_submount(ap, next->path, ap->state);
+				continue;
+			}
 
-		/* Skip offsets */
-		if (strstr(next->opts, "offset"))
-			continue;
+			/* Skip offsets */
+			if (strstr(next->opts, "offset"))
+				continue;
+		}
 
 		/*
 		 * All direct mounts must be present in the map
@@ -896,9 +901,10 @@ static void *do_expire_direct(void *arg)
 		send_fail(mt->ioctlfd, mt->wait_queue_token);
 	else {
 		struct mapent *me;
-		me = lookup_source_mapent(ap, mt->name, LKP_DISTINCT);
+		cache_readlock(mt->mc);
+		me = cache_lookup_distinct(mt->mc, mt->name);
 		me->ioctlfd = -1;
-		cache_unlock(me->source->mc);
+		cache_unlock(mt->mc);
 		send_ready(mt->ioctlfd, mt->wait_queue_token);
 		close(mt->ioctlfd);
 	}
@@ -1195,9 +1201,10 @@ cont:
 	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &state);
 	if (status) {
 		struct mapent *me;
-		me = lookup_source_mapent(ap, mt->name, LKP_DISTINCT);
+		cache_readlock(mt->mc);
+		me = cache_lookup_distinct(mt->mc, mt->name);
 		me->ioctlfd = mt->ioctlfd;
-		cache_unlock(me->source->mc);
+		cache_unlock(mt->mc);
 		send_ready(mt->ioctlfd, mt->wait_queue_token);
 		msg("mounted %s", mt->name);
 	} else {
diff --git a/daemon/indirect.c b/daemon/indirect.c
index 8748413..dadb9ee 100644
--- a/daemon/indirect.c
+++ b/daemon/indirect.c
@@ -430,16 +430,22 @@ void *expire_proc_indirect(void *arg)
 	if (status)
 		fatal(status);
 
-	master_notify_submounts(ap, ap->state);
-
 	/* Get a list of real mounts and expire them if possible */
 	mnts = get_mnt_list(_PROC_MOUNTS, ap->path, 0);
 	for (next = mnts; next; next = next->next) {
 		char *ind_key;
 		int ret;
 
-		if (!strcmp(next->fs_type, "autofs"))
+		if (!strcmp(next->fs_type, "autofs")) {
+			/*
+			 * If we have submounts check if this path lives below
+			 * one of them and pass on the state change.
+			 */
+			if (strstr(next->opts, "indirect"))
+				master_notify_submount(ap, next->path, ap->state);
+
 			continue;
+		}
 
 		/*
 		 * If the mount corresponds to an offset trigger then
@@ -458,7 +464,7 @@ void *expire_proc_indirect(void *arg)
 		 */
 		me = lookup_source_mapent(ap, next->path, LKP_DISTINCT);
 		if (!me && ind_key)
-			lookup_source_mapent(ap, ind_key, LKP_NORMAL);
+			me = lookup_source_mapent(ap, ind_key, LKP_NORMAL);
 		if (!me)
 			continue;
 
diff --git a/include/automount.h b/include/automount.h
index 90a9c7a..267c7d1 100644
--- a/include/automount.h
+++ b/include/automount.h
@@ -437,7 +437,6 @@ struct autofs_point {
 	pthread_t exp_thread;		/* Thread that is expiring */
 	pthread_t readmap_thread;	/* Thread that is reading maps */
 	pthread_mutex_t state_mutex;	/* Protect state changes */
-	struct list_head state_queue;	/* Pending state transitions */
 	enum states state;		/* Current state */
 	int state_pipe[2];		/* State change router pipe */
 	unsigned dir_created;		/* Directory created for this mount? */
diff --git a/include/master.h b/include/master.h
index ada18d4..e25626d 100644
--- a/include/master.h
+++ b/include/master.h
@@ -97,7 +97,8 @@ void master_free_mapent_sources(struct m
 void master_free_mapent(struct master_mapent *);
 struct master *master_new(const char *, unsigned int, unsigned int);
 int master_read_master(struct master *, time_t, int);
-void master_notify_submounts(struct autofs_point *, enum states);
+int master_submount_list_empty(struct autofs_point *ap);
+int master_notify_submount(struct autofs_point *, const char *path, enum states);
 void master_signal_submount(struct autofs_point *, unsigned int);
 void master_notify_state_change(struct master *, int);
 int master_mount_mounts(struct master *, time_t, int);
diff --git a/lib/master.c b/lib/master.c
index d76ffac..1d66542 100644
--- a/lib/master.c
+++ b/lib/master.c
@@ -95,7 +95,6 @@ int master_add_autofs_point(struct maste
 		free(ap);
 		return 0;
 	}
-	INIT_LIST_HEAD(&ap->state_queue);
 
 	status = pthread_mutex_init(&ap->mounts_mutex, NULL);
 	if (status) {
@@ -735,34 +734,68 @@ int master_read_master(struct master *ma
 	return 1;
 }
 
-void master_notify_submounts(struct autofs_point *ap, enum states state)
+int master_submount_list_empty(struct autofs_point *ap)
+{
+	int res = 0;
+
+	mounts_mutex_lock(ap);
+	if (list_empty(&ap->submounts))
+		res = 1;
+	mounts_mutex_unlock(ap);
+
+	return res;
+}
+
+int master_notify_submount(struct autofs_point *ap, const char *path, 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;
+	size_t plen = strlen(path);
+	int status, ret = 1;
 
 	mounts_mutex_lock(ap);
 
 	head = &ap->submounts;
-	p = head->next;
+	p = head->prev;
 	while (p != head) {
+		size_t len;
+
 		this = list_entry(p, struct autofs_point, mounts);
+		p = p->prev;
 
-		p = p->next;
+		if (!master_submount_list_empty(this)) {
+			if (!master_notify_submount(this, path, state)) {
+				ret = 0;
+				break;
+			}
+		}
+
+		len = strlen(this->path);
 
-		if (!list_empty(&this->submounts))
-			master_notify_submounts(this, state);
+		/* Initial path not the same */
+		if (strncmp(this->path, path, len))
+			continue;
+
+		/*
+		 * Part of submount tree?
+		 * We must wait till we get to submount itself.
+		 * If it is tell caller by returning true.
+		 */
+		if (plen > len) {
+			/* Not part of this directory tree */
+			if (path[len] != '/')
+				continue;
+			break;
+		}
+
+		/* Now we have a submount to expire */
 
 		state_mutex_lock(this);
 
 		if (this->state == ST_SHUTDOWN) {
 			state_mutex_unlock(this);
-			continue;
+			break;
 		}
 
 		nextstate(this->state_pipe[1], state);
@@ -775,17 +808,21 @@ void master_notify_submounts(struct auto
 			status = pthread_cond_wait(&ap->mounts_cond, &ap->mounts_mutex);
 			if (status)
 				fatal(status);
-			if (ap->mounts_signaled == MASTER_SUBMNT_JOIN) {
-				status = pthread_join(thid, NULL);
-				if (status)
-					fatal(status);
-			}
 		}
+
+		if (ap->mounts_signaled == MASTER_SUBMNT_JOIN) {
+			status = pthread_join(thid, NULL);
+			if (status)
+				fatal(status);
+		} else
+			ret = 0;
+
+		break;
 	}
 
 	mounts_mutex_unlock(ap);
 
-	return;
+	return ret;
 }
 
 void master_signal_submount(struct autofs_point *ap, unsigned int join)
@@ -797,13 +834,13 @@ void master_signal_submount(struct autof
 
 	mounts_mutex_lock(ap->parent);
 
-	if (join) {
+	ap->parent->mounts_signaled = join;
+
+	if (join == MASTER_SUBMNT_JOIN) {
 		/* We are finishing up */
 		ap->parent->submnt_count--;
 		list_del(&ap->mounts);
-		ap->parent->mounts_signaled = 1;
-	} else
-		ap->parent->mounts_signaled = 2;
+	}
 
 	status = pthread_cond_signal(&ap->parent->mounts_cond);
 	if (status)
diff --git a/lib/mounts.c b/lib/mounts.c
index f446a6a..46131cd 100644
--- a/lib/mounts.c
+++ b/lib/mounts.c
@@ -149,7 +149,7 @@ struct mnt_list *get_mnt_list(const char
 		mptr = list;
 		last = NULL;
 		while (mptr) {
-			if (len > strlen(mptr->path))
+			if (len >= strlen(mptr->path))
 				break;
 			last = mptr;
 			mptr = mptr->next;