diff --git a/CHANGELOG b/CHANGELOG
index 0c498fc..dbf557b 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -36,6 +36,7 @@
 - fix task cancelation at shutdown (more).
 - fix concurrent mount and expire race with nested submounts.
 - fix colon escape handling.
+- fix recusively referenced bind automounts.
 
 13/7/2006 autofs-5.0.1 rc1
 --------------------------
diff --git a/daemon/direct.c b/daemon/direct.c
index 9a1cd59..cfa13ad 100644
--- a/daemon/direct.c
+++ b/daemon/direct.c
@@ -273,8 +273,7 @@ static int unlink_mount_tree(struct auto
 			continue;
 
 		if (strcmp(mnt->fs_type, "autofs"))
-			rv = spawnll(log_debug,
-			     PATH_UMOUNT, PATH_UMOUNT, "-l", mnt->path, NULL);
+			rv = spawn_umount(log_debug, "-l", mnt->path, NULL);
 		else
 			rv = umount2(mnt->path, MNT_DETACH);
 		if (rv == -1) {
diff --git a/daemon/indirect.c b/daemon/indirect.c
index 38d0b7a..9ceb015 100644
--- a/daemon/indirect.c
+++ b/daemon/indirect.c
@@ -95,8 +95,7 @@ static int unlink_mount_tree(struct auto
 		}
 
 		if (strcmp(this->fs_type, "autofs"))
-			rv = spawnll(log_debug,
-			    PATH_UMOUNT, PATH_UMOUNT, "-l", this->path, NULL);
+			rv = spawn_umount(log_debug, "-l", this->path, NULL);
 		else
 			rv = umount2(this->path, MNT_DETACH);
 		if (rv == -1) {
diff --git a/daemon/spawn.c b/daemon/spawn.c
index 7dc4a81..84df3b9 100644
--- a/daemon/spawn.c
+++ b/daemon/spawn.c
@@ -20,6 +20,7 @@ #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
+#include <dirent.h>
 #include <unistd.h>
 #include <time.h>
 #include <sys/wait.h>
@@ -27,9 +28,11 @@ #include <sys/stat.h>
 
 #include "automount.h"
 
-#ifdef ENABLE_MOUNT_LOCKING
 static pthread_mutex_t spawn_mutex = PTHREAD_MUTEX_INITIALIZER;
-#endif
+
+#define SPAWN_OPT_NONE		0x0000
+#define SPAWN_OPT_LOCK		0x0001
+#define SPAWN_OPT_OPENDIR	0x0002
 
 inline void dump_core(void)
 {
@@ -83,26 +86,15 @@ void reset_signals(void)
 
 #define ERRBUFSIZ 2047		/* Max length of error string excl \0 */
 
-#ifdef ENABLE_MOUNT_LOCKING
-void spawn_unlock(void *arg)
-{
-	int *use_lock = (int *) arg;
-
-	if (*use_lock) {
-		if (pthread_mutex_unlock(&spawn_mutex))
-			warn(LOGOPT_NONE, "failed to unlock spawn_mutex");
-	}
-	return;
-}
-#endif
-
-static int do_spawn(logger *log, int use_lock, const char *prog, const char *const *argv)
+static int do_spawn(logger *log, unsigned int options, const char *prog, const char *const *argv)
 {
 	pid_t f;
 	int status, pipefd[2];
 	char errbuf[ERRBUFSIZ + 1], *p, *sp;
 	int errp, errn;
 	int cancel_state;
+	unsigned int use_lock = options & SPAWN_OPT_LOCK;
+	unsigned int use_opendir = options & SPAWN_OPT_OPENDIR;
 	sigset_t allsigs, tmpsig, oldsig;
 
 	if (pipe(pipefd))
@@ -113,16 +105,11 @@ static int do_spawn(logger *log, int use
 	sigfillset(&allsigs);
 	pthread_sigmask(SIG_BLOCK, &allsigs, &oldsig);
 
-#ifdef ENABLE_MOUNT_LOCKING
 	if (use_lock) {
-		if (pthread_mutex_lock(&spawn_mutex)) {
-			log(LOGOPT_ANY, "failed to lock spawn_mutex");
-			pthread_sigmask(SIG_SETMASK, &oldsig, NULL);
-			pthread_setcancelstate(cancel_state, NULL);
-			return -1;
-		}
+		status = pthread_mutex_lock(&spawn_mutex);
+		if (status)
+			fatal(status);
 	}
-#endif
 
 	f = fork();
 	if (f == 0) {
@@ -132,6 +119,26 @@ #endif
 		dup2(pipefd[1], STDERR_FILENO);
 		close(pipefd[1]);
 
+		/* Bind mount - check target exists */
+		if (use_opendir) {
+			char **pargv = (char **) argv;
+			int argc = 0;
+			pid_t pgrp = getpgrp();
+			DIR *dfd;
+
+			/* what to mount must always be second last */
+			while (*pargv++)
+				argc++;
+			argc -= 2;
+
+			/* Set non-autofs program group to trigger mount */
+			setpgrp();
+			if ((dfd = opendir(argv[argc])) == NULL)
+				_exit(errno);
+			closedir(dfd);
+			setpgid(0, pgrp);
+		}
+
 		execv(prog, (char *const *) argv);
 		_exit(255);	/* execv() failed */
 	} else {
@@ -144,10 +151,12 @@ #endif
 
 		if (f < 0) {
 			close(pipefd[0]);
+			if (use_lock) {
+				status = pthread_mutex_unlock(&spawn_mutex);
+				if (status)
+					fatal(status);
+			}
 			pthread_sigmask(SIG_SETMASK, &oldsig, NULL);
-#ifdef ENABLE_MOUNT_LOCKING
-			spawn_unlock(&use_lock);
-#endif
 			pthread_setcancelstate(cancel_state, NULL);
 			return -1;
 		}
@@ -193,10 +202,12 @@ #endif
 		if (waitpid(f, &status, 0) != f)
 			status = -1;	/* waitpid() failed */
 
+		if (use_lock) {
+			status = pthread_mutex_unlock(&spawn_mutex);
+			if (status)
+				fatal(status);
+		}
 		pthread_sigmask(SIG_SETMASK, &oldsig, NULL);
-#ifdef ENABLE_MOUNT_LOCKING
-		spawn_unlock(&use_lock);
-#endif
 		pthread_setcancelstate(cancel_state, NULL);
 
 		return status;
@@ -205,7 +216,7 @@ #endif
 
 int spawnv(logger *log, const char *prog, const char *const *argv)
 {
-	return do_spawn(log, 0, prog, argv);
+	return do_spawn(log, SPAWN_OPT_NONE, prog, argv);
 }
 
 int spawnl(logger *log, const char *prog, ...)
@@ -226,28 +237,114 @@ int spawnl(logger *log, const char *prog
 	while ((*p++ = va_arg(arg, char *)));
 	va_end(arg);
 
-	return do_spawn(log, 0, prog, (const char **) argv);
+	return do_spawn(log, SPAWN_OPT_NONE, prog, (const char **) argv);
 }
 
+int spawn_mount(logger *log, ...)
+{
+	va_list arg;
+	int argc;
+	char **argv, **p;
+	char prog[] = PATH_MOUNT;
+	char arg0[] = PATH_MOUNT;
+	unsigned int options;
+
+	/* If we use mount locking we can't validate the location */
 #ifdef ENABLE_MOUNT_LOCKING
-int spawnll(logger *log, const char *prog, ...)
+	options = SPAWN_OPT_LOCK;
+#else
+	options = SPAWN_OPT_NONE;
+#endif
+
+	va_start(arg, log);
+	for (argc = 1; va_arg(arg, char *); argc++);
+	va_end(arg);
+
+	if (!(argv = alloca(sizeof(char *) * argc + 1)))
+		return -1;
+
+	argv[0] = arg0;
+
+	va_start(arg, log);
+	p = argv + 1;
+	while ((*p++ = va_arg(arg, char *)));
+	va_end(arg);
+
+	return do_spawn(log, options, prog, (const char **) argv);
+}
+
+/*
+ * For bind mounts that depend on the target being mounted (possibly
+ * itself an automount) we attempt to mount the target using an opendir
+ * call. For this to work the location must be the second last arg.
+ *
+ * NOTE: If mount locking is enabled this type of recursive mount cannot
+ *	 work.
+ */
+int spawn_bind_mount(logger *log, ...)
 {
 	va_list arg;
 	int argc;
 	char **argv, **p;
+	char prog[] = PATH_MOUNT;
+	char arg0[] = PATH_MOUNT;
+	char bind[] = "--bind";
+	unsigned int options;
 
-	va_start(arg, prog);
+	/* If we use mount locking we can't validate the location */
+#ifdef ENABLE_MOUNT_LOCKING
+	options = SPAWN_OPT_LOCK;
+#else
+	options = SPAWN_OPT_OPENDIR;
+#endif
+
+	va_start(arg, log);
 	for (argc = 1; va_arg(arg, char *); argc++);
 	va_end(arg);
 
-	if (!(argv = alloca(sizeof(char *) * argc)))
+	if (!(argv = alloca(sizeof(char *) * argc + 2)))
 		return -1;
 
-	va_start(arg, prog);
-	p = argv;
+	argv[0] = arg0;
+	argv[1] = bind;
+
+	va_start(arg, log);
+	p = argv + 2;
 	while ((*p++ = va_arg(arg, char *)));
 	va_end(arg);
 
-	return do_spawn(log, 1, prog, (const char **) argv);
+	return do_spawn(log, options, prog, (const char **) argv);
 }
+
+int spawn_umount(logger *log, ...)
+{
+	va_list arg;
+	int argc;
+	char **argv, **p;
+	char prog[] = PATH_UMOUNT;
+	char arg0[] = PATH_UMOUNT;
+	unsigned int options;
+
+#ifdef ENABLE_MOUNT_LOCKING
+	options = SPAWN_OPT_LOCK;
+#else
+	options = SPAWN_OPT_NONE;
 #endif
+
+	va_start(arg, log);
+	for (argc = 1; va_arg(arg, char *); argc++);
+	va_end(arg);
+
+	if (!(argv = alloca(sizeof(char *) * argc + 1)))
+		return -1;
+
+	argv[0] = arg0;
+
+	va_start(arg, log);
+	p = argv + 1;
+	while ((*p++ = va_arg(arg, char *)));
+	va_end(arg);
+
+	return do_spawn(log, options, prog, (const char **) argv);
+}
+
diff --git a/include/automount.h b/include/automount.h
index 1f4fc6b..9c2de00 100644
--- a/include/automount.h
+++ b/include/automount.h
@@ -195,12 +195,10 @@ inline void dump_core(void);
 int aquire_lock(void);
 void release_lock(void);
 int spawnl(logger *log, const char *prog, ...);
-#ifdef ENABLE_MOUNT_LOCKING
-int spawnll(logger *log, const char *prog, ...);
-#else
-#define spawnll	spawnl
-#endif
 int spawnv(logger *log, const char *prog, const char *const *argv);
+int spawn_mount(logger *log, ...);
+int spawn_bind_mount(logger *log, ...);
+int spawn_umount(logger *log, ...);
 void reset_signals(void);
 int do_mount(struct autofs_point *ap, const char *root, const char *name,
 	     int name_len, const char *what, const char *fstype,
diff --git a/lib/parse_subs.c b/lib/parse_subs.c
index b584250..fbbc515 100644
--- a/lib/parse_subs.c
+++ b/lib/parse_subs.c
@@ -304,9 +304,9 @@ int umount_ent(struct autofs_point *ap, 
 	 * and EBADSLT relates to CD changer not responding.
 	 */
 	if (!status && (S_ISDIR(st.st_mode) && st.st_dev != ap->dev)) {
-		rv = spawnll(log_debug, PATH_UMOUNT, PATH_UMOUNT, path, NULL);
+		rv = spawn_umount(log_debug, path, NULL);
 	} else if (is_smbfs && (sav_errno == EIO || sav_errno == EBADSLT)) {
-		rv = spawnll(log_debug, PATH_UMOUNT, PATH_UMOUNT, path, NULL);
+		rv = spawn_umount(log_debug, path, NULL);
 	}
 
 	/* We are doing a forced shutcwdown down so unlink busy mounts */
@@ -324,7 +324,7 @@ int umount_ent(struct autofs_point *ap, 
 
 		if (ap->state == ST_SHUTDOWN_FORCE) {
 			msg("forcing umount of %s", path);
-			rv = spawnll(log_debug, PATH_UMOUNT, PATH_UMOUNT, "-l", path, NULL);
+			rv = spawn_umount(log_debug, "-l", path, NULL);
 		}
 
 		/*
diff --git a/modules/mount_bind.c b/modules/mount_bind.c
index 96ca29b..1cdb1c6 100644
--- a/modules/mount_bind.c
+++ b/modules/mount_bind.c
@@ -56,9 +56,7 @@ int mount_init(void **context)
 	if (lstat(tmp1, &st1) == -1)
 		goto out;
 
-	err = spawnl(log_debug,
-	    	     PATH_MOUNT, PATH_MOUNT, "-n", "--bind", tmp1, tmp2, NULL);
-
+	err = spawn_mount(log_debug, "-n", "--bind", tmp1, tmp2, NULL);
 	if (err == 0 &&
 	    lstat(tmp2, &st2) == 0 &&
 	    st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino) {
@@ -67,8 +65,7 @@ int mount_init(void **context)
 
 	debug(LOGOPT_NONE, MODPREFIX "bind_works = %d", bind_works);
 
-	spawnl(log_debug,
-	       PATH_UMOUNT, PATH_UMOUNT, "-n", tmp2, NULL);
+	spawn_umount(log_debug, "-n", tmp2, NULL);
 
       out:
 	rmdir(tmp2);
@@ -149,10 +146,8 @@ int mount_mount(struct autofs_point *ap,
 		      "calling mount --bind " SLOPPY " -o %s %s %s",
 		      options, what, fullpath);
 
-		err = spawnll(log_debug,
-			     PATH_MOUNT, PATH_MOUNT, "--bind",
-			     SLOPPYOPT "-o", options,
-			     what, fullpath, NULL);
+		err = spawn_bind_mount(log_debug,
+			     SLOPPYOPT "-o", options, what, fullpath, NULL);
 
 		if (err) {
 			if (ap->type != LKP_INDIRECT)
diff --git a/modules/mount_changer.c b/modules/mount_changer.c
index eb29c8c..b817d36 100644
--- a/modules/mount_changer.c
+++ b/modules/mount_changer.c
@@ -80,8 +80,7 @@ int mount_mount(struct autofs_point *ap,
 
 	debug(ap->logopt, MODPREFIX "calling umount %s", what);
 
-	err = spawnll(log_debug,
-		     PATH_UMOUNT, PATH_UMOUNT, what, NULL);
+	err = spawn_umount(log_debug, what, NULL);
 	if (err) {
 		error(ap->logopt,
 		      MODPREFIX
@@ -116,16 +115,14 @@ int mount_mount(struct autofs_point *ap,
 		      MODPREFIX "calling mount -t %s " SLOPPY "-o %s %s %s",
 		      fstype, options, what, fullpath);
 
-		err = spawnll(log_debug,
-			     PATH_MOUNT, PATH_MOUNT, "-t", fstype,
+		err = spawn_mount(log_debug, "-t", fstype,
 			     SLOPPYOPT "-o", options, what, fullpath, NULL);
 	} else {
 		debug(ap->logopt,
 		      MODPREFIX "calling mount -t %s %s %s",
 		      fstype, what, fullpath);
 
-		err = spawnll(log_debug, PATH_MOUNT, PATH_MOUNT,
-			     "-t", fstype, what, fullpath, NULL);
+		err = spawn_mount(log_debug, "-t", fstype, what, fullpath, NULL);
 	}
 
 	if (err) {
diff --git a/modules/mount_ext2.c b/modules/mount_ext2.c
index 7774adf..45f0615 100644
--- a/modules/mount_ext2.c
+++ b/modules/mount_ext2.c
@@ -132,16 +132,13 @@ #endif
 		debug(ap->logopt,
 		      MODPREFIX "calling mount -t %s " SLOPPY "-o %s %s %s",
 		      fstype, options, what, fullpath);
-		err = spawnll(log_debug,
-		             PATH_MOUNT, PATH_MOUNT, "-t", fstype,
+		err = spawn_mount(log_debug, "-t", fstype,
 			     SLOPPYOPT "-o", options, what, fullpath, NULL);
 	} else {
 		debug(ap->logopt,
 		      MODPREFIX "calling mount -t %s %s %s",
 		      fstype, what, fullpath);
-		err = spawnll(log_debug,
-			     PATH_MOUNT, PATH_MOUNT, "-t", fstype,
-			     what, fullpath, NULL);
+		err = spawn_mount(log_debug, "-t", fstype, what, fullpath, NULL);
 	}
 
 	if (err) {
diff --git a/modules/mount_generic.c b/modules/mount_generic.c
index ad726e7..1f43baa 100644
--- a/modules/mount_generic.c
+++ b/modules/mount_generic.c
@@ -93,15 +93,12 @@ int mount_mount(struct autofs_point *ap,
 		      MODPREFIX "calling mount -t %s " SLOPPY "-o %s %s %s",
 		      fstype, options, what, fullpath);
 
-		err = spawnll(log_debug,
-			     PATH_MOUNT, PATH_MOUNT, "-t", fstype,
+		err = spawn_mount(log_debug, "-t", fstype,
 			     SLOPPYOPT "-o", options, what, fullpath, NULL);
 	} else {
 		debug(ap->logopt, MODPREFIX "calling mount -t %s %s %s",
 		      fstype, what, fullpath);
-		err = spawnll(log_debug,
-			     PATH_MOUNT, PATH_MOUNT, "-t", fstype,
-			     what, fullpath, NULL);
+		err = spawn_mount(log_debug, "-t", fstype, what, fullpath, NULL);
 	}
 
 	if (err) {
diff --git a/modules/mount_nfs.c b/modules/mount_nfs.c
index 8b4ddac..55e4f98 100644
--- a/modules/mount_nfs.c
+++ b/modules/mount_nfs.c
@@ -225,17 +225,15 @@ int mount_mount(struct autofs_point *ap,
 			      MODPREFIX "calling mount -t nfs " SLOPPY 
 			      "-o %s %s %s", nfsoptions, loc, fullpath);
 
-			err = spawnll(log_debug,
-				     PATH_MOUNT, PATH_MOUNT, "-t",
-				     "nfs", SLOPPYOPT "-o", nfsoptions,
-				     loc, fullpath, NULL);
+			err = spawn_mount(log_debug,
+					  "-t", "nfs", SLOPPYOPT "-o",
+					  nfsoptions, loc, fullpath, NULL);
 		} else {
 			debug(ap->logopt,
 			      MODPREFIX "calling mount -t nfs %s %s",
 			      loc, fullpath);
-			err = spawnll(log_debug,
-				     PATH_MOUNT, PATH_MOUNT, "-t",
-				     "nfs", loc, fullpath, NULL);
+			err = spawn_mount(log_debug,
+					  "-t", "nfs", loc, fullpath, NULL);
 		}
 
 		if (!err) {
