Blob Blame History Raw
diff -up autofs-5.0.3/daemon/indirect.c.active-restart autofs-5.0.3/daemon/indirect.c
--- autofs-5.0.3/daemon/indirect.c.active-restart	2008-02-25 09:16:05.000000000 +0900
+++ autofs-5.0.3/daemon/indirect.c	2008-02-25 09:16:46.000000000 +0900
@@ -20,6 +20,7 @@
  * ----------------------------------------------------------------------- */
 
 #include <dirent.h>
+#include <libgen.h>
 #include <fcntl.h>
 #include <signal.h>
 #include <stdio.h>
@@ -32,9 +33,8 @@
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <sys/mount.h>
+#include <sys/vfs.h>
 #include <sched.h>
-#include <pwd.h>
-#include <grp.h>
 
 #include "automount.h"
 
@@ -43,8 +43,6 @@ extern pthread_attr_t thread_attr;
 static pthread_mutex_t ma_mutex = PTHREAD_MUTEX_INITIALIZER;
 static pthread_mutex_t ea_mutex = PTHREAD_MUTEX_INITIALIZER;
 
-static const unsigned int indirect = AUTOFS_TYPE_INDIRECT;
-
 static int unlink_mount_tree(struct autofs_point *ap, struct mnt_list *mnts)
 {
 	struct mnt_list *this;
@@ -90,6 +88,7 @@ static int unlink_mount_tree(struct auto
 
 static int do_mount_autofs_indirect(struct autofs_point *ap)
 {
+	const char *str_indirect = mount_type_str(indirect);
 	struct ioctl_ops *ops = get_ioctl_ops();
 	time_t timeout = ap->exp_timeout;
 	char *options = NULL;
@@ -98,8 +97,58 @@ static int do_mount_autofs_indirect(stru
 	struct mnt_list *mnts;
 	int ret;
 
-	mnts = get_mnt_list(_PROC_MOUNTS, ap->path, 1);
-	if (mnts) {
+	ap->exp_runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO;
+
+	if (ops->version) {
+		char device[AUTOFS_DEVID_LEN];
+		struct statfs fst;
+		int ioctlfd;
+		dev_t devid;
+		char *tmp;
+
+		if (!find_mnt_devid(_PROC_MOUNTS, ap->path, device, indirect))
+			goto cont;
+
+		devid = strtoul(device, NULL, 0);
+
+		ret = remount_active_mount(ap, NULL, ap->path, devid, indirect, &ioctlfd);
+
+		/*
+		 * The directory must exist since we found a device
+		 * number for the mount above but we can't know if we
+		 * created it or not. However, if we're mounted on an
+		 * autofs fs then we need to cleanup the path anyway.
+		 */
+		ap->dir_created = 0;
+		tmp = strdup(ap->path);
+		if (tmp) {
+			if (statfs(dirname(tmp), &fst) != -1)
+				if (fst.f_type == AUTOFS_SUPER_MAGIC)
+					ap->dir_created = 1;
+			free(tmp);
+		}
+
+		/*
+		 * Either we opened the mount or we're re-reading the map.
+		 * If we opened the mount and ioctlfd is not -1 we have
+		 * a descriptor for the indirect mount so we need to
+		 * record that in the mount point struct. Otherwise we're
+		 * re-reading the map.
+		*/
+		if (ret == REMOUNT_SUCCESS || ret == REMOUNT_READ_MAP) {
+			if (ioctlfd != -1)
+				ap->ioctlfd = ioctlfd;
+			return 0;
+		}
+		/*
+		 * Since we got the device number above a mount exists so
+		 * any other failure warrants a failure return here.
+		 */
+		return -1;
+	} else {
+		mnts = get_mnt_list(_PROC_MOUNTS, ap->path, 1);
+		if (!mnts)
+			goto cont;
 		ret = unlink_mount_tree(ap, mnts);
 		free_mnt_list(mnts);
 		if (!ret) {
@@ -109,7 +158,7 @@ static int do_mount_autofs_indirect(stru
 			goto out_err;
 		}
 	}
-
+cont:
 	options = make_options_string(ap->path, ap->kpipefd, NULL);
 	if (!options) {
 		error(ap->logopt, "options string error");
@@ -152,29 +201,21 @@ static int do_mount_autofs_indirect(stru
 
 	options = NULL;
 
-	if (ops->open(ap->logopt, &ap->ioctlfd, -1, ap->path, indirect)) {
+	if (stat(ap->path, &st) == -1) {
+		error(ap->logopt,
+		      "failed to stat mount %s", ap->path);
+		goto out_umount;
+	}
+	ap->dev = st.st_dev;
+
+	if (ops->open(ap->logopt, &ap->ioctlfd, ap->dev, ap->path, indirect)) {
 		crit(ap->logopt,
 		     "failed to create ioctl fd for autofs path %s", ap->path);
 		goto out_umount;
 	}
 
-	ap->exp_runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO;
-
 	ops->timeout(ap->logopt, ap->ioctlfd, &timeout);
-
-	if (ap->exp_timeout)
-		info(ap->logopt,
-		    "mounted indirect mount on %s "
-		    "with timeout %u, freq %u seconds", ap->path,
-	 	    (unsigned int) ap->exp_timeout,
-		    (unsigned int) ap->exp_runfreq);
-	else
-		info(ap->logopt,
-		    "mounted indirect mount on %s with timeouts disabled",
-		    ap->path);
-
-	fstat(ap->ioctlfd, &st);
-	ap->dev = st.st_dev;	/* Device number for mount point checks */
+	notify_mount_result(ap, ap->path, str_indirect);
 
 	return 0;
 
@@ -636,15 +677,7 @@ static void *do_mount_indirect(void *arg
 	struct autofs_point *ap;
 	char buf[PATH_MAX + 1];
 	struct stat st;
-	struct passwd pw;
-	struct passwd *ppw = &pw;
-	struct passwd **pppw = &ppw;
-	struct group gr;
-	struct group *pgr;
-	struct group **ppgr;
-	char *pw_tmp, *gr_tmp;
-	struct thread_stdenv_vars *tsv;
-	int len, tmplen, grplen, status, state;
+	int len, status, state;
 
 	mt = (struct pending_args *) arg;
 
@@ -687,125 +720,8 @@ static void *do_mount_indirect(void *arg
 
 	info(ap->logopt, "attempting to mount entry %s", buf);
 
-	/*
-	 * Setup thread specific data values for macro
-	 * substution in map entries during the mount.
-	 * Best effort only as it must go ahead.
-	 */
+	set_tsd_user_vars(ap->logopt, mt->uid, mt->gid);
 
-	tsv = malloc(sizeof(struct thread_stdenv_vars));
-	if (!tsv) 
-		goto cont;
-
-	tsv->uid = mt->uid;
-	tsv->gid = mt->gid;
-
-	/* Try to get passwd info */
-
-	tmplen = sysconf(_SC_GETPW_R_SIZE_MAX);
-	if (tmplen < 0) {
-		error(ap->logopt, "failed to get buffer size for getpwuid_r");
-		free(tsv);
-		goto cont;
-	}
-
-	pw_tmp = malloc(tmplen + 1);
-	if (!pw_tmp) {
-		error(ap->logopt, "failed to malloc buffer for getpwuid_r");
-		free(tsv);
-		goto cont;
-	}
-
-	status = getpwuid_r(mt->uid, ppw, pw_tmp, tmplen, pppw);
-	if (status || !ppw) {
-		error(ap->logopt, "failed to get passwd info from getpwuid_r");
-		free(tsv);
-		free(pw_tmp);
-		goto cont;
-	}
-
-	tsv->user = strdup(pw.pw_name);
-	if (!tsv->user) {
-		error(ap->logopt, "failed to malloc buffer for user");
-		free(tsv);
-		free(pw_tmp);
-		goto cont;
-	}
-
-	tsv->home = strdup(pw.pw_dir);
-	if (!tsv->user) {
-		error(ap->logopt, "failed to malloc buffer for home");
-		free(pw_tmp);
-		free(tsv->user);
-		free(tsv);
-		goto cont;
-	}
-
-	free(pw_tmp);
-
-	/* Try to get group info */
-
-	grplen = sysconf(_SC_GETGR_R_SIZE_MAX);
-	if (tmplen < 0) {
-		error(ap->logopt, "failed to get buffer size for getgrgid_r");
-		free(tsv->user);
-		free(tsv->home);
-		free(tsv);
-		goto cont;
-	}
-
-	gr_tmp = NULL;
-	tmplen = grplen;
-	while (1) {
-		char *tmp = realloc(gr_tmp, tmplen + 1);
-		if (!tmp) {
-			error(ap->logopt, "failed to malloc buffer for getgrgid_r");
-			if (gr_tmp)
-				free(gr_tmp);
-			free(tsv->user);
-			free(tsv->home);
-			free(tsv);
-			goto cont;
-		}
-		gr_tmp = tmp;
-		pgr = &gr;
-		ppgr = &pgr;
-		status = getgrgid_r(mt->gid, pgr, gr_tmp, tmplen, ppgr);
-		if (status != ERANGE)
-			break;
-		tmplen += grplen;
-	}
-
-	if (status || !pgr) {
-		error(ap->logopt, "failed to get group info from getgrgid_r");
-		free(tsv->user);
-		free(tsv->home);
-		free(tsv);
-		free(gr_tmp);
-		goto cont;
-	}
-
-	tsv->group = strdup(gr.gr_name);
-	if (!tsv->group) {
-		error(ap->logopt, "failed to malloc buffer for group");
-		free(tsv->user);
-		free(tsv->home);
-		free(tsv);
-		free(gr_tmp);
-		goto cont;
-	}
-
-	free(gr_tmp);
-
-	status = pthread_setspecific(key_thread_stdenv_vars, tsv);
-	if (status) {
-		error(ap->logopt, "failed to set stdenv thread var");
-		free(tsv->group);
-		free(tsv->user);
-		free(tsv->home);
-		free(tsv);
-	}
-cont:
 	status = lookup_nss_mount(ap, NULL, mt->name, mt->len);
 	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &state);
 	if (status) {
diff -up autofs-5.0.3/daemon/automount.c.active-restart autofs-5.0.3/daemon/automount.c
--- autofs-5.0.3/daemon/automount.c.active-restart	2008-02-25 09:16:05.000000000 +0900
+++ autofs-5.0.3/daemon/automount.c	2008-02-25 09:16:46.000000000 +0900
@@ -466,7 +466,7 @@ static int umount_subtree_mounts(struct 
 
 		pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
 		/* Lock the closest parent nesting point for umount */
-		cache_multi_lock(me->parent);
+		cache_multi_writelock(me->parent);
 		if (umount_multi_triggers(ap, root, me, base)) {
 			warn(ap->logopt,
 			     "some offset mounts still present under %s", path);
@@ -1412,6 +1412,55 @@ static void mutex_operation_wait(pthread
 	return;
 }
 
+int handle_mounts_startup_cond_init(struct startup_cond *suc)
+{
+	int status;
+
+	status = pthread_mutex_init(&suc->mutex, NULL);
+	if (status)
+		return status;
+
+	status = pthread_cond_init(&suc->cond, NULL);
+	if (status) {
+		status = pthread_mutex_destroy(&suc->mutex);
+		if (status)
+			fatal(status);
+		return status;
+	}
+
+	status = pthread_mutex_lock(&suc->mutex);
+	if (status) {
+		status = pthread_mutex_destroy(&suc->mutex);
+		if (status)
+			fatal(status);
+		status = pthread_cond_destroy(&suc->cond);
+		if (status)
+			fatal(status);
+	}
+
+	return 0;
+}
+
+void handle_mounts_startup_cond_destroy(void *arg)
+{
+	struct startup_cond *suc = (struct startup_cond *) arg;
+	int status;
+
+	status = pthread_mutex_unlock(&suc->mutex);
+	if (status)
+		fatal(status);
+
+	status = pthread_mutex_destroy(&suc->mutex);
+	if (status)
+		fatal(status);
+
+	status = pthread_cond_destroy(&suc->cond);
+	if (status)
+		fatal(status);
+
+	return;
+}
+
 static void handle_mounts_cleanup(void *arg)
 {
 	struct autofs_point *ap;
@@ -1463,17 +1512,20 @@ static void handle_mounts_cleanup(void *
 
 void *handle_mounts(void *arg)
 {
+	struct startup_cond *suc;
 	struct autofs_point *ap;
 	int cancel_state, status = 0;
 
-	ap = (struct autofs_point *) arg;
+	suc = (struct startup_cond *) arg;
+
+	ap = suc->ap;
 
-	pthread_cleanup_push(return_start_status, &suc);
+	pthread_cleanup_push(return_start_status, suc);
 	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancel_state);
 
 	state_mutex_lock(ap);
 
-	status = pthread_mutex_lock(&suc.mutex);
+	status = pthread_mutex_lock(&suc->mutex);
 	if (status) {
 		logerr("failed to lock startup condition mutex!");
 		fatal(status);
@@ -1481,7 +1533,7 @@ void *handle_mounts(void *arg)
 
 	if (mount_autofs(ap) < 0) {
 		crit(ap->logopt, "mount of %s failed!", ap->path);
-		suc.status = 1;
+		suc->status = 1;
 		state_mutex_unlock(ap);
 		umount_autofs(ap, 1);
 		pthread_setcancelstate(cancel_state, NULL);
@@ -1491,7 +1543,7 @@ void *handle_mounts(void *arg)
 	if (ap->ghost && ap->type != LKP_DIRECT)
 		info(ap->logopt, "ghosting enabled");
 
-	suc.status = 0;
+	suc->status = 0;
 	pthread_cleanup_pop(1);
 
 	/* We often start several automounters at the same time.  Add some
@@ -1948,7 +2000,9 @@ int main(int argc, char *argv[])
 
 	if (!query_kproto_ver() || get_kver_major() < 5) {
 		fprintf(stderr,
-			"%s: kernel protocol version 5.00 or above required.\n",
+			"%s: test mount forbidden or "
+			"incorrect kernel protocol version, "
+			"kernel protocol version 5.00 or above required.\n",
 			program);
 		exit(1);
 	}
diff -up autofs-5.0.3/daemon/direct.c.active-restart autofs-5.0.3/daemon/direct.c
--- autofs-5.0.3/daemon/direct.c.active-restart	2008-02-25 09:16:05.000000000 +0900
+++ autofs-5.0.3/daemon/direct.c	2008-02-25 09:16:46.000000000 +0900
@@ -20,6 +20,7 @@
  * ----------------------------------------------------------------------- */
 
 #include <dirent.h>
+#include <libgen.h>
 #include <fcntl.h>
 #include <signal.h>
 #include <stdio.h>
@@ -35,16 +36,11 @@
 #include <sys/mount.h>
 #include <sys/vfs.h>
 #include <sched.h>
-#include <pwd.h>
-#include <grp.h>
 
 #include "automount.h"
 
 extern pthread_attr_t thread_attr;
 
-static const unsigned int direct = AUTOFS_TYPE_DIRECT;
-static const unsigned int offset = AUTOFS_TYPE_OFFSET;
-
 struct mnt_params {
 	char *options;
 };
@@ -287,15 +283,11 @@ static int unlink_mount_tree(struct auto
 	return ret;
 }
 
-int do_mount_autofs_direct(struct autofs_point *ap, struct mnt_list *mnts, struct mapent *me)
+static int unlink_active_mounts(struct autofs_point *ap,
+				struct mnt_list *mnts, struct mapent *me)
 {
 	struct ioctl_ops *ops = get_ioctl_ops();
-	struct mnt_params *mp;
-	time_t timeout = ap->exp_timeout;
-	struct stat st;
-	int status, ret, ioctlfd;
 	struct list_head list;
-	const char *map_name;
 
 	INIT_LIST_HEAD(&list);
 
@@ -313,7 +305,7 @@ int do_mount_autofs_direct(struct autofs
 				error(ap->logopt,
 				     "failed to create ioctl fd for %s",
 				     me->key);
-				return 0;
+				return 1;
 			}
 
 			ops->timeout(ap->logopt, ioctlfd, &tout);
@@ -321,22 +313,99 @@ int do_mount_autofs_direct(struct autofs
 			if (save_ioctlfd == -1)
 				ops->close(ap->logopt, ioctlfd);
 
-			return 0;
+			return 1;
 		}
 
 		if (!unlink_mount_tree(ap, &list)) {
 			debug(ap->logopt,
 			      "already mounted as other than autofs "
 			      "or failed to unlink entry in tree");
-			return -1;
+			return 0;
 		}
 	}
+	return 1;
+}
 
-	if (me->ioctlfd != -1) {
-		error(ap->logopt, "active direct mount %s", me->key);
-		return -1;
-	}
+int do_mount_autofs_direct(struct autofs_point *ap, struct mnt_list *mnts, struct mapent *me)
+{
+	const char *str_direct = mount_type_str(direct);
+	struct ioctl_ops *ops = get_ioctl_ops();
+	struct mnt_params *mp;
+	time_t timeout = ap->exp_timeout;
+	struct stat st;
+	int status, ret, ioctlfd;
+	const char *map_name;
+
+	/* Calculate the timeouts */
+	ap->exp_runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO;
+
+	if (ops->version) {
+		char device[AUTOFS_DEVID_LEN];
+		struct statfs fst;
+		dev_t devid;
+		char *tmp;
+
+		/* Mount in mount table */
+		if (!tree_find_mnt_devid(mnts, me->key, device, direct))
+			goto cont;
+
+		devid = strtoul(device, NULL, 0);
+
+		ret = remount_active_mount(ap, me->mc,
+					   me->key, devid, direct,
+					   &ioctlfd);
+
+		/*
+		 * The directory must exist since we found a device
+		 * number for the mount above but we can't know if we
+		 * created it or not. However, if we're mounted on an
+		 * autofs fs then we need to cleanup the path anyway.
+		 */
+		me->dir_created = 0;
+		tmp = strdup(me->key);
+		if (tmp) {
+			if (statfs(dirname(tmp), &fst) != -1)
+				if (fst.f_type == AUTOFS_SUPER_MAGIC)
+					me->dir_created = 1;
+			free(tmp);
+		}
+
+		/*
+		 * Either we opened the mount or we're re-reading the map.
+		 * If we opened the mount and ioctlfd is not -1 we have an
+		 * active mount so we need to record the descriptor in the
+		 * cache entry. Otherwise there is no active mount or we're
+		 * re-reading the map.
+		*/
+		if (ret == REMOUNT_SUCCESS || ret == REMOUNT_READ_MAP) {
+			if (ioctlfd != -1)
+				me->ioctlfd = ioctlfd;
+			return 0;
+		}
+
+		/*
+		 * Since we got the device number above a mount exists so
+		 * any other failure warrants a failure return here.
+		 */
+		goto out_err;
+	} else {
+		/*
+		 * A return of 1 indicates we're re-reading the map
+		 * or we successfully unlinked the mount tree if it
+		 * there was one. A return of zero inducates we
+		 * failed to unlink the mount tree so we have to
+		 * return a failure.
+		 */
+		ret = unlink_active_mounts(ap, mnts, me);
+		if (ret == 0)
+			return -1;
 
+		if (me->ioctlfd != -1) {
+			error(ap->logopt, "active direct mount %s", me->key);
+			return -1;
+		}
+	}
+cont:
 	status = pthread_once(&key_mnt_params_once, key_mnt_params_init);
 	if (status)
 		fatal(status);
@@ -388,44 +457,27 @@ int do_mount_autofs_direct(struct autofs
 		goto out_err;
 	}
 
-	ops->open(ap->logopt, &ioctlfd, -1, me->key, direct);
+	if (stat(me->key, &st) == -1) {
+		error(ap->logopt,
+		      "failed to stat direct mount trigger %s", me->key);
+		goto out_umount;
+	}
+
+	ops->open(ap->logopt, &ioctlfd, st.st_dev, me->key, direct);
 	if (ioctlfd < 0) {
 		crit(ap->logopt, "failed to create ioctl fd for %s", me->key);
 		goto out_umount;
 	}
 
-	/* Calculate the timeouts */
-	ap->exp_runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO;
-
 	ops->timeout(ap->logopt, ioctlfd, &timeout);
-
-	if (ap->exp_timeout)
-		info(ap->logopt,
-		    "mounted direct mount on %s "
-		    "with timeout %u, freq %u seconds", me->key,
-		    (unsigned int) ap->exp_timeout,
-		    (unsigned int) ap->exp_runfreq);
-	else
-		info(ap->logopt,
-		     "mounted direct mount on %s with timeouts disabled",
-		     me->key);
-
-	ret = fstat(ioctlfd, &st);
-	if (ret == -1) {
-		error(ap->logopt,
-		      "failed to stat direct mount trigger %s", me->key);
-		goto out_close;
-	}
+	notify_mount_result(ap, me->key, str_direct);
 	cache_set_ino_index(me->mc, me->key, st.st_dev, st.st_ino);
-
 	ops->close(ap->logopt, ioctlfd);
 
 	debug(ap->logopt, "mounted trigger %s", me->key);
 
 	return 0;
 
-out_close:
-	ops->close(ap->logopt, ioctlfd);
 out_umount:
 	/* TODO: maybe force umount (-l) */
 	umount(me->key);
@@ -462,8 +514,6 @@ int mount_autofs_direct(struct autofs_po
 	pthread_cleanup_push(master_source_lock_cleanup, ap->entry);
 	master_source_readlock(ap->entry);
 	nc = ap->entry->master->nc;
-	cache_readlock(nc);
-	pthread_cleanup_push(cache_lock_cleanup, nc);
 	map = ap->entry->maps;
 	while (map) {
 		/*
@@ -476,8 +526,6 @@ int mount_autofs_direct(struct autofs_po
 		}
 
 		mc = map->mc;
-		pthread_cleanup_push(cache_lock_cleanup, mc);
-		cache_readlock(mc);
 		me = cache_enumerate(mc, NULL);
 		while (me) {
 			ne = cache_lookup_distinct(nc, me->key);
@@ -505,12 +553,10 @@ int mount_autofs_direct(struct autofs_po
 
 			me = cache_enumerate(mc, me);
 		}
-		pthread_cleanup_pop(1);
 		map = map->next;
 	}
 	pthread_cleanup_pop(1);
 	pthread_cleanup_pop(1);
-	pthread_cleanup_pop(1);
 
 	return 0;
 }
@@ -627,6 +673,7 @@ force_umount:
 
 int mount_autofs_offset(struct autofs_point *ap, struct mapent *me)
 {
+	const char *str_offset = mount_type_str(offset);
 	struct ioctl_ops *ops = get_ioctl_ops();
 	char buf[MAX_ERR_BUF];
 	struct mnt_params *mp;
@@ -635,18 +682,68 @@ int mount_autofs_offset(struct autofs_po
 	int ioctlfd, status, ret;
 	const char *type, *map_name = NULL;
 
-	if (is_mounted(_PROC_MOUNTS, me->key, MNTS_AUTOFS)) {
-		if (ap->state != ST_READMAP)
-			warn(ap->logopt,
-			      "trigger %s already mounted", me->key);
-		return 0;
-	}
+	if (ops->version) {
+		char device[AUTOFS_DEVID_LEN];
+		struct statfs fst;
+		dev_t devid;
+		char *tmp;
 
-	if (me->ioctlfd != -1) {
-		error(ap->logopt, "active offset mount %s", me->key);
-		return -1;
-	}
+		/* If we can find it it's mounted */
+		if (!find_mnt_devid(_PROC_MOUNTS, me->key, device, offset))
+			goto cont;
+
+		devid = strtoul(device, NULL, 0);
+
+		ret = remount_active_mount(ap, me->mc,
+					   me->key, devid, offset,
+					   &ioctlfd);
+
+		/*
+		 * The directory must exist since we found a device
+		 * number for the mount above but we can't know if we
+		 * created it or not. However, if we're mounted on an
+		 * autofs fs then we need to cleanup the path anyway.
+		 */
+		me->dir_created = 0;
+		tmp = strdup(me->key);
+		if (tmp) {
+			if (statfs(dirname(tmp), &fst) != -1)
+				if (fst.f_type == AUTOFS_SUPER_MAGIC)
+					me->dir_created = 1;
+			free(tmp);
+		}
+
+		/*
+		 * Either we opened the mount or we're re-reading the map.
+		 * If we opened the mount and ioctlfd is not -1 we have an
+		 * active mount so we need to record the descriptor in the
+		 * cache entry. Otherwise there is no active mount or we're
+		 * re-reading the map.
+		*/
+		if (ret == REMOUNT_SUCCESS || ret == REMOUNT_READ_MAP) {
+			if (ioctlfd != -1)
+				me->ioctlfd = ioctlfd;
+			return 0;
+		}
+		/*
+		 * Since we got the device number above a mount exists so
+		 * any other failure warrants a failure return here.
+		 */
+		goto out_err;
+	} else {
+		if (is_mounted(_PROC_MOUNTS, me->key, MNTS_AUTOFS)) {
+			if (ap->state != ST_READMAP)
+				warn(ap->logopt,
+				     "trigger %s already mounted", me->key);
+			return 0;
+		}
 
+		if (me->ioctlfd != -1) {
+			error(ap->logopt, "active offset mount %s", me->key);
+			return -1;
+		}
+	}
+cont:
 	status = pthread_once(&key_mnt_params_once, key_mnt_params_init);
 	if (status)
 		fatal(status);
@@ -670,7 +767,7 @@ int mount_autofs_offset(struct autofs_po
 	}
 
 	if (!mp->options) {
-		mp->options = make_options_string(ap->path, ap->kpipefd, "offset");
+		mp->options = make_options_string(ap->path, ap->kpipefd, str_offset);
 		if (!mp->options)
 			return 0;
 	}
@@ -724,34 +821,28 @@ int mount_autofs_offset(struct autofs_po
 		map_name = me->mc->map->argv[0];
 
 	ret = mount(map_name, me->key, "autofs", MS_MGC_VAL, mp->options);
-	if (ret) {
-		crit(ap->logopt, "failed to mount autofs path %s", me->key);
-		goto out_err;
-	}
-
 	if (ret != 0) {
 		crit(ap->logopt,
 		     "failed to mount autofs offset trigger %s", me->key);
 		goto out_err;
 	}
 
-	ops->open(ap->logopt, &ioctlfd, -1, me->key, offset);
-	if (ioctlfd < 0) {
-		crit(ap->logopt, "failed to create ioctl fd for %s", me->key);
-		goto out_umount;
-	}
-
-	ops->timeout(ap->logopt, ioctlfd, &timeout);
-
-	ret = fstat(ioctlfd, &st);
+	ret = stat(me->key, &st);
 	if (ret == -1) {
 		error(ap->logopt,
 		     "failed to stat direct mount trigger %s", me->key);
 		goto out_close;
 	}
 
-	cache_set_ino_index(me->mc, me->key, st.st_dev, st.st_ino);
+	ops->open(ap->logopt, &ioctlfd, st.st_dev, me->key, offset);
+	if (ioctlfd < 0) {
+		crit(ap->logopt, "failed to create ioctl fd for %s", me->key);
+		goto out_umount;
+	}
 
+	ops->timeout(ap->logopt, ioctlfd, &timeout);
+	notify_mount_result(ap, me->key, str_offset);
+	cache_set_ino_index(me->mc, me->key, st.st_dev, st.st_ino);
 	ops->close(ap->logopt, ioctlfd);
 
 	debug(ap->logopt, "mounted trigger %s", me->key);
@@ -1072,7 +1163,6 @@ int handle_packet_expire_direct(struct a
 		return 1;
 	}
 
-
 	mt = malloc(sizeof(struct pending_args));
 	if (!mt) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
@@ -1155,15 +1245,6 @@ static void *do_mount_direct(void *arg)
 	struct ioctl_ops *ops = get_ioctl_ops();
 	struct pending_args *mt;
 	struct autofs_point *ap;
-	struct passwd pw;
-	struct passwd *ppw = &pw;
-	struct passwd **pppw = &ppw;
-	struct group gr;
-	struct group *pgr;
-	struct group **ppgr;
-	char *pw_tmp, *gr_tmp;
-	struct thread_stdenv_vars *tsv;
-	int tmplen, grplen;
 	struct stat st;
 	int status, state;
 
@@ -1209,126 +1290,8 @@ static void *do_mount_direct(void *arg)
 
 	info(ap->logopt, "attempting to mount entry %s", mt->name);
 
-	/*
-	 * Setup thread specific data values for macro
-	 * substution in map entries during the mount.
-	 * Best effort only as it must go ahead.
-	 */
+	set_tsd_user_vars(ap->logopt, mt->uid, mt->gid);
 
-	tsv = malloc(sizeof(struct thread_stdenv_vars));
-	if (!tsv) 
-		goto cont;
-
-	tsv->uid = mt->uid;
-	tsv->gid = mt->gid;
-
-	/* Try to get passwd info */
-
-	tmplen = sysconf(_SC_GETPW_R_SIZE_MAX);
-	if (tmplen < 0) {
-		error(ap->logopt, "failed to get buffer size for getpwuid_r");
-		free(tsv);
-		goto cont;
-	}
-
-	pw_tmp = malloc(tmplen + 1);
-	if (!pw_tmp) {
-		error(ap->logopt, "failed to malloc buffer for getpwuid_r");
-		free(tsv);
-		goto cont;
-	}
-
-	status = getpwuid_r(mt->uid, ppw, pw_tmp, tmplen, pppw);
-	if (status || !ppw) {
-		error(ap->logopt, "failed to get passwd info from getpwuid_r");
-		free(tsv);
-		free(pw_tmp);
-		goto cont;
-	}
-
-	tsv->user = strdup(pw.pw_name);
-	if (!tsv->user) {
-		error(ap->logopt, "failed to malloc buffer for user");
-		free(tsv);
-		free(pw_tmp);
-		goto cont;
-	}
-
-	tsv->home = strdup(pw.pw_dir);
-	if (!tsv->user) {
-		error(ap->logopt, "failed to malloc buffer for home");
-		free(pw_tmp);
-		free(tsv->user);
-		free(tsv);
-		goto cont;
-	}
-
-	free(pw_tmp);
-
-	/* Try to get group info */
-
-	grplen = sysconf(_SC_GETGR_R_SIZE_MAX);
-	if (tmplen < 0) {
-		error(ap->logopt, "failed to get buffer size for getgrgid_r");
-		free(tsv->user);
-		free(tsv->home);
-		free(tsv);
-		goto cont;
-	}
-
-	gr_tmp = NULL;
-	tmplen = grplen;
-	while (1) {
-		char *tmp = realloc(gr_tmp, tmplen + 1);
-		if (!tmp) {
-			error(ap->logopt, "failed to malloc buffer for getgrgid_r");
-			if (gr_tmp)
-				free(gr_tmp);
-			free(tsv->user);
-			free(tsv->home);
-			free(tsv);
-			goto cont;
-		}
-		gr_tmp = tmp;
-		pgr = &gr;
-		ppgr = &pgr;
-		status = getgrgid_r(mt->gid, pgr, gr_tmp, tmplen, ppgr);
-		if (status != ERANGE)
-			break;
-		tmplen += grplen;
-	}
-
-	if (status || !pgr) {
-		error(ap->logopt, "failed to get group info from getgrgid_r");
-		free(tsv->user);
-		free(tsv->home);
-		free(tsv);
-		free(gr_tmp);
-		goto cont;
-	}
-
-	tsv->group = strdup(gr.gr_name);
-	if (!tsv->group) {
-		error(ap->logopt, "failed to malloc buffer for group");
-		free(tsv->user);
-		free(tsv->home);
-		free(tsv);
-		free(gr_tmp);
-		goto cont;
-	}
-
-	free(gr_tmp);
-
-	status = pthread_setspecific(key_thread_stdenv_vars, tsv);
-	if (status) {
-		error(ap->logopt, "failed to set stdenv thread var");
-		free(tsv->group);
-		free(tsv->user);
-		free(tsv->home);
-		free(tsv);
-	}
-
-cont:
 	status = lookup_nss_mount(ap, NULL, mt->name, strlen(mt->name));
 	/*
 	 * Direct mounts are always a single mount. If it fails there's
diff -up autofs-5.0.3/daemon/lookup.c.active-restart autofs-5.0.3/daemon/lookup.c
--- autofs-5.0.3/daemon/lookup.c.active-restart	2008-02-25 09:16:05.000000000 +0900
+++ autofs-5.0.3/daemon/lookup.c	2008-02-25 09:16:46.000000000 +0900
@@ -898,7 +898,8 @@ int lookup_nss_mount(struct autofs_point
 
 		map = map->next;
 	}
-	send_map_update_request(ap);
+	if (ap->state != ST_INIT)
+		send_map_update_request(ap);
 	pthread_cleanup_pop(1);
 
 	return !result;
diff -up autofs-5.0.3/include/parse_subs.h.active-restart autofs-5.0.3/include/parse_subs.h
--- autofs-5.0.3/include/parse_subs.h.active-restart	2008-01-14 13:39:16.000000000 +0900
+++ autofs-5.0.3/include/parse_subs.h	2008-02-25 09:16:46.000000000 +0900
@@ -27,8 +27,5 @@ int strmcmp(const char *, const char *, 
 char *dequote(const char *, int, unsigned int);
 int span_space(const char *, unsigned int);
 char *sanitize_path(const char *, int, unsigned int, unsigned int);
-int umount_ent(struct autofs_point *, const char *);
-int mount_multi_triggers(struct autofs_point *, char *, struct mapent *, const char *);
-int umount_multi_triggers(struct autofs_point *, char *, struct mapent *, const char *);
 
 #endif
diff -up autofs-5.0.3/include/automount.h.active-restart autofs-5.0.3/include/automount.h
--- autofs-5.0.3/include/automount.h.active-restart	2008-02-25 09:16:05.000000000 +0900
+++ autofs-5.0.3/include/automount.h	2008-02-25 09:16:46.000000000 +0900
@@ -29,6 +29,7 @@
 #include "log.h"
 #include "rpc_subs.h"
 #include "parse_subs.h"
+#include "mounts.h"
 #include "dev-ioctl-lib.h"
 
 #ifdef WITH_DMALLOC
@@ -71,10 +72,6 @@ int load_autofs4_module(void);
 #define SMB_SUPER_MAGIC    0x0000517BL
 #define CIFS_MAGIC_NUMBER  0xFF534D42L
 
-#define AUTOFS_TYPE_INDIRECT     0x0001
-#define AUTOFS_TYPE_DIRECT       0x0002
-#define AUTOFS_TYPE_OFFSET       0x0004
-
 /* This sould be enough for at least 20 host aliases */
 #define HOST_ENT_BUF_SIZE	2048
 
@@ -146,7 +143,7 @@ struct mapent_cache {
 struct mapent {
 	struct mapent *next;
 	struct list_head ino_index;
-	pthread_mutex_t multi_mutex;
+	pthread_rwlock_t multi_rwlock;
 	struct list_head multi_list;
 	struct mapent_cache *mc;
 	struct map_source *source;
@@ -189,7 +186,8 @@ int cache_add_offset(struct mapent_cache
 int cache_set_parents(struct mapent *mm);
 int cache_update(struct mapent_cache *mc, struct map_source *ms, 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 *me);
+void cache_multi_readlock(struct mapent *me);
+void cache_multi_writelock(struct mapent *me);
 void cache_multi_unlock(struct mapent *me);
 int cache_delete_offset_list(struct mapent_cache *mc, const char *key);
 void cache_release(struct map_source *map);
@@ -328,62 +326,6 @@ int cat_path(char *buf, size_t len, cons
 int ncat_path(char *buf, size_t len,
               const char *dir, const char *base, size_t blen);
 
-/* mount table utilities */
-
-#define MNTS_ALL	0x0001
-#define MNTS_REAL	0x0002
-#define MNTS_AUTOFS	0x0004
-
-struct mnt_list {
-	char *path;
-	char *fs_name;
-	char *fs_type;
-	char *opts;
-	pid_t owner;
-	/*
-	 * List operations ie. get_mnt_list.
-	 */
-	struct mnt_list *next;
-	/*
-	 * Tree operations ie. tree_make_tree,
-	 * tree_get_mnt_list etc.
-	 */
-	struct mnt_list *left;
-	struct mnt_list *right;
-	struct list_head self;
-	struct list_head list;
-	struct list_head entries;
-	struct list_head sublist;
-	/*
-	 * Offset mount handling ie. add_ordered_list
-	 * and get_offset.
-	 */
-	struct list_head ordered;
-};
-
-unsigned int query_kproto_ver(void);
-unsigned int get_kver_major(void);
-unsigned int get_kver_minor(void);
-char *make_options_string(char *path, int kernel_pipefd, char *extra);
-char *make_mnt_name_string(char *path);
-struct mnt_list *get_mnt_list(const char *table, const char *path, int include);
-struct mnt_list *reverse_mnt_list(struct mnt_list *list);
-void free_mnt_list(struct mnt_list *list);
-int contained_in_local_fs(const char *path);
-int is_mounted(const char *table, const char *path, unsigned int type);
-int has_fstab_option(const char *opt);
-int find_mnt_devid(const char *table, const char *path, char *devid, unsigned int type);
-char *get_offset(const char *prefix, char *offset,
-                 struct list_head *head, struct list_head **pos);
-void add_ordered_list(struct mnt_list *ent, struct list_head *head);
-void tree_free_mnt_tree(struct mnt_list *tree);
-struct mnt_list *tree_make_mnt_tree(const char *table, const char *path);
-int tree_get_mnt_list(struct mnt_list *mnts, struct list_head *list, const char *path, int include);
-int tree_get_mnt_sublist(struct mnt_list *mnts, struct list_head *list, const char *path, int include);
-int tree_find_mnt_ents(struct mnt_list *mnts, struct list_head *list, const char *path);
-int tree_is_mounted(struct mnt_list *mnts, const char *path, unsigned int type);
-int tree_find_mnt_devid(struct mnt_list *mnts, const char *path, char *devid, unsigned int type);
-
 /* Core automount definitions */
 
 #define MNT_DETACH	0x00000002	/* Just detach from the tree */
@@ -391,10 +333,14 @@ int tree_find_mnt_devid(struct mnt_list 
 struct startup_cond {
 	pthread_mutex_t mutex;
 	pthread_cond_t  cond;
+	struct autofs_point *ap;
 	unsigned int done;
 	unsigned int status;
 };
 
+int handle_mounts_startup_cond_init(struct startup_cond *suc);
+void handle_mounts_startup_cond_destroy(void *arg);
+
 struct master_readmap_cond {
 	pthread_mutex_t mutex;
 	pthread_cond_t  cond;
diff -up autofs-5.0.3/modules/mount_ext2.c.active-restart autofs-5.0.3/modules/mount_ext2.c
--- autofs-5.0.3/modules/mount_ext2.c.active-restart	2008-01-14 13:39:16.000000000 +0900
+++ autofs-5.0.3/modules/mount_ext2.c	2008-02-25 09:16:46.000000000 +0900
@@ -84,8 +84,9 @@ int mount_mount(struct autofs_point *ap,
 		existed = 0;
 
 	if (is_mounted(_PATH_MOUNTED, fullpath, MNTS_REAL)) {
-		error(ap->logopt,
-		      MODPREFIX "warning: %s is already mounted", fullpath);
+		info(ap->logopt, MODPREFIX
+		     "%s is already mounted or is bieng re-mounted",
+		     fullpath);
 		return 0;
 	}
 
diff -up autofs-5.0.3/modules/mount_generic.c.active-restart autofs-5.0.3/modules/mount_generic.c
--- autofs-5.0.3/modules/mount_generic.c.active-restart	2008-01-14 13:39:16.000000000 +0900
+++ autofs-5.0.3/modules/mount_generic.c	2008-02-25 09:16:46.000000000 +0900
@@ -83,8 +83,9 @@ int mount_mount(struct autofs_point *ap,
 		existed = 0;
 
 	if (is_mounted(_PATH_MOUNTED, fullpath, MNTS_REAL)) {
-		error(ap->logopt,
-		      MODPREFIX "warning: %s is already mounted", fullpath);
+		info(ap->logopt, MODPREFIX
+		     "%s is already mounted or is being re-mounted",
+		     fullpath);
 		return 0;
 	}
 
diff -up autofs-5.0.3/modules/mount_autofs.c.active-restart autofs-5.0.3/modules/mount_autofs.c
--- autofs-5.0.3/modules/mount_autofs.c.active-restart	2008-01-14 13:39:16.000000000 +0900
+++ autofs-5.0.3/modules/mount_autofs.c	2008-02-25 09:16:46.000000000 +0900
@@ -46,6 +46,7 @@ int mount_mount(struct autofs_point *ap,
 		int name_len, const char *what, const char *fstype,
 		const char *c_options, void *context)
 {
+	struct startup_cond suc;
 	pthread_t thid;
 	char *fullpath;
 	const char **argv;
@@ -216,27 +217,26 @@ int mount_mount(struct autofs_point *ap,
 
 	mounts_mutex_lock(ap);
 
-	status = pthread_mutex_lock(&suc.mutex);
-	if (status) {
-		crit(ap->logopt,
-		     MODPREFIX "failed to lock startup condition mutex!");
+	if (handle_mounts_startup_cond_init(&suc)) {
+		crit(ap->logopt, MODPREFIX
+		     "failed to init startup cond for mount %s", entry->path);
+		mounts_mutex_unlock(ap);
 		cache_release(source);
 		master_free_mapent(entry);
 		return 1;
 	}
 
+	suc.ap = nap;
 	suc.done = 0;
 	suc.status = 0;
 
-	if (pthread_create(&thid, NULL, handle_mounts, nap)) {
+	if (pthread_create(&thid, NULL, handle_mounts, &suc)) {
 		crit(ap->logopt,
 		     MODPREFIX
 		     "failed to create mount handler thread for %s",
 		     fullpath);
 		mounts_mutex_unlock(ap);
-		status = pthread_mutex_unlock(&suc.mutex);
-		if (status)
-			fatal(status);
+		handle_mounts_startup_cond_destroy(&suc);
 		cache_release(source);
 		master_free_mapent(entry);
 		return 1;
@@ -247,7 +247,7 @@ int mount_mount(struct autofs_point *ap,
 		status = pthread_cond_wait(&suc.cond, &suc.mutex);
 		if (status) {
 			mounts_mutex_unlock(ap);
-			pthread_mutex_unlock(&suc.mutex);
+			handle_mounts_startup_cond_destroy(&suc);
 			fatal(status);
 		}
 	}
@@ -256,9 +256,7 @@ int mount_mount(struct autofs_point *ap,
 		crit(ap->logopt,
 		     MODPREFIX "failed to create submount for %s", fullpath);
 		mounts_mutex_unlock(ap);
-		status = pthread_mutex_unlock(&suc.mutex);
-		if (status)
-			fatal(status);
+		handle_mounts_startup_cond_destroy(&suc);
 		master_free_mapent(entry);
 		return 1;
 	}
@@ -266,12 +264,9 @@ int mount_mount(struct autofs_point *ap,
 	ap->submnt_count++;
 	list_add(&nap->mounts, &ap->submounts);
 
+	handle_mounts_startup_cond_destroy(&suc);
 	mounts_mutex_unlock(ap);
 
-	status = pthread_mutex_unlock(&suc.mutex);
-	if (status)
-		fatal(status);
-
 	return 0;
 }
 
diff -up autofs-5.0.3/modules/mount_nfs.c.active-restart autofs-5.0.3/modules/mount_nfs.c
--- autofs-5.0.3/modules/mount_nfs.c.active-restart	2008-02-25 09:16:05.000000000 +0900
+++ autofs-5.0.3/modules/mount_nfs.c	2008-02-25 09:16:46.000000000 +0900
@@ -198,10 +198,10 @@ int mount_mount(struct autofs_point *ap,
 		char *loc, *port_opt = NULL;
 
 		if (is_mounted(_PATH_MOUNTED, fullpath, MNTS_REAL)) {
-			error(ap->logopt,
-			      MODPREFIX
-			      "warning: %s is already mounted", fullpath);
-			break;
+			info(ap->logopt, MODPREFIX
+			     "%s is already mounted or is being re-mounted", fullpath);
+			free_host_list(&hosts);
+			return 0;
 		}
 
 		/*
diff -up autofs-5.0.3/modules/parse_sun.c.active-restart autofs-5.0.3/modules/parse_sun.c
--- autofs-5.0.3/modules/parse_sun.c.active-restart	2008-01-14 13:39:16.000000000 +0900
+++ autofs-5.0.3/modules/parse_sun.c	2008-02-25 09:16:46.000000000 +0900
@@ -968,8 +968,6 @@ static int mount_subtree_offsets(struct 
 	if (!mm)
 		return 0;
 
-	cache_multi_lock(me->parent);
-
 	m_key = mm->key;
 
 	if (*m_key == '/') {
@@ -999,8 +997,6 @@ static int mount_subtree_offsets(struct 
 		return -1;
 	}
 
-	cache_multi_unlock(me->parent);
-
 	return ret;
 }
 
@@ -1197,7 +1193,7 @@ int parse_mount(struct autofs_point *ap,
 			 * us to fail on the check for duplicate offsets in
 			 * we don't know when submounts go away.
 			 */
-			cache_multi_lock(me);
+			cache_multi_writelock(me);
 			cache_delete_offset_list(mc, name);
 			cache_multi_unlock(me);
 		}
@@ -1220,7 +1216,7 @@ int parse_mount(struct autofs_point *ap,
 		}
 
 		pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
-		cache_multi_lock(me);
+		cache_multi_writelock(me);
 		/* It's a multi-mount; deal with it */
 		do {
 			char *path, *myoptions, *loc;
@@ -1296,6 +1292,10 @@ int parse_mount(struct autofs_point *ap,
 		 */
 		cache_set_parents(me);
 
+		/* Added multi-mount cache entries, down grade lock */ 
+		cache_multi_unlock(me);
+		cache_multi_readlock(me);
+
 		/* Mount root offset if it exists */
 		ro = cache_lookup_offset("/", "/", strlen(m_root), &me->multi_list);
 		if (ro) {
@@ -1468,10 +1468,14 @@ mount_it:
 		cache_readlock(mc);
 		me = cache_lookup_distinct(mc, name);
 		if (me) {
-			int ret = mount_subtree_offsets(ap, mc, me);
+			int ret;
+
+			cache_multi_readlock(me->parent);
+			ret = mount_subtree_offsets(ap, mc, me);
 			/* Convert fail on nonstrict, non-empty multi-mount to success */
 			if (rv < 0 && ret > 0)
 				rv = 0;
+			cache_multi_unlock(me->parent);
 		}
 		cache_unlock(mc);
 		pthread_setcancelstate(cur_state, NULL);
diff -up autofs-5.0.3/modules/mount_bind.c.active-restart autofs-5.0.3/modules/mount_bind.c
--- autofs-5.0.3/modules/mount_bind.c.active-restart	2008-01-14 13:39:16.000000000 +0900
+++ autofs-5.0.3/modules/mount_bind.c	2008-02-25 09:16:46.000000000 +0900
@@ -126,8 +126,8 @@ int mount_mount(struct autofs_point *ap,
 			existed = 0;
 
 		if (is_mounted(_PATH_MOUNTED, fullpath, MNTS_REAL)) {
-			error(ap->logopt,
-			      MODPREFIX "warning: %s is already mounted",
+			info(ap->logopt, MODPREFIX
+			     "%s is already mounted or is being re-mounted",
 			      fullpath);
 			return 0;
 		}
diff -up autofs-5.0.3/lib/parse_subs.c.active-restart autofs-5.0.3/lib/parse_subs.c
--- autofs-5.0.3/lib/parse_subs.c.active-restart	2008-01-14 13:39:16.000000000 +0900
+++ autofs-5.0.3/lib/parse_subs.c	2008-02-25 09:16:46.000000000 +0900
@@ -18,10 +18,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
-#include <sys/types.h>
-#include <sys/stat.h>
 #include <unistd.h>
-#include <sys/vfs.h>
 #include "automount.h"
 
 /*
@@ -304,220 +301,3 @@ char *sanitize_path(const char *path, in
 	return s_path;
 }
 
-int umount_ent(struct autofs_point *ap, const char *path)
-{
-	struct stat st;
-	struct statfs fs;
-	int sav_errno;
-	int status, is_smbfs = 0;
-	int ret, rv = 1;
-
-	ret = statfs(path, &fs);
-	if (ret == -1) {
-		warn(ap->logopt, "could not stat fs of %s", path);
-		is_smbfs = 0;
-	} else {
-		int cifsfs = fs.f_type == (__SWORD_TYPE) CIFS_MAGIC_NUMBER;
-		int smbfs = fs.f_type == (__SWORD_TYPE) SMB_SUPER_MAGIC;
-		is_smbfs = (cifsfs | smbfs) ? 1 : 0;
-	}
-
-	status = lstat(path, &st);
-	sav_errno = errno;
-
-	if (status < 0)
-		warn(ap->logopt, "lstat of %s failed with %d", path, status);
-
-	/*
-	 * lstat failed and we're an smbfs fs returning an error that is not
-	 * EIO or EBADSLT or the lstat failed so it's a bad path. Return
-	 * a fail.
-	 *
-	 * EIO appears to correspond to an smb mount that has gone away
-	 * and EBADSLT relates to CD changer not responding.
-	 */
-	if (!status && (S_ISDIR(st.st_mode) && st.st_dev != ap->dev)) {
-		rv = spawn_umount(ap->logopt, path, NULL);
-	} else if (is_smbfs && (sav_errno == EIO || sav_errno == EBADSLT)) {
-		rv = spawn_umount(ap->logopt, path, NULL);
-	}
-
-	/* We are doing a forced shutcwdown down so unlink busy mounts */
-	if (rv && (ap->state == ST_SHUTDOWN_FORCE || ap->state == ST_SHUTDOWN)) {
-		ret = stat(path, &st);
-		if (ret == -1 && errno == ENOENT) {
-			warn(ap->logopt, "mount point does not exist");
-			return 0;
-		}
-
-		if (ret == 0 && !S_ISDIR(st.st_mode)) {
-			warn(ap->logopt, "mount point is not a directory");
-			return 0;
-		}
-
-		if (ap->state == ST_SHUTDOWN_FORCE) {
-			info(ap->logopt, "forcing umount of %s", path);
-			rv = spawn_umount(ap->logopt, "-l", path, NULL);
-		}
-
-		/*
-		 * Verify that we actually unmounted the thing.  This is a
-		 * belt and suspenders approach to not eating user data.
-		 * We have seen cases where umount succeeds, but there is
-		 * still a file system mounted on the mount point.  How
-		 * this happens has not yet been determined, but we want to
-		 * make sure to return failure here, if that is the case,
-		 * so that we do not try to call rmdir_path on the
-		 * directory.
-		 */
-		if (!rv && is_mounted(_PATH_MOUNTED, path, MNTS_REAL)) {
-			crit(ap->logopt,
-			     "the umount binary reported that %s was "
-			     "unmounted, but there is still something "
-			     "mounted on this path.", path);
-			rv = -1;
-		}
-	}
-
-	return rv;
-}
-
-int mount_multi_triggers(struct autofs_point *ap, char *root, struct mapent *me, const char *base)
-{
-	char path[PATH_MAX + 1];
-	char *offset = path;
-	struct mapent *oe;
-	struct list_head *pos = NULL;
-	unsigned int fs_path_len;
-	unsigned int mounted;
-	int start;
-
-	fs_path_len = strlen(root) + strlen(base);
-	if (fs_path_len > PATH_MAX)
-		return -1;
-
-	strcpy(path, root);
-	strcat(path, base);
-
-	mounted = 0;
-	start = strlen(root);
-	offset = cache_get_offset(base, offset, start, &me->multi_list, &pos);
-	while (offset) {
-		int plen = fs_path_len + strlen(offset);
-
-		if (plen > PATH_MAX) {
-			warn(ap->logopt, "path loo long");
-			goto cont;
-		}
-
-		oe = cache_lookup_offset(base, offset, start, &me->multi_list);
-		if (!oe)
-			goto cont;
-
-		debug(ap->logopt, "mount offset %s", oe->key);
-
-		if (mount_autofs_offset(ap, oe) < 0)
-			warn(ap->logopt, "failed to mount offset");
-		else
-			mounted++;
-cont:
-		offset = cache_get_offset(base,
-				offset, start, &me->multi_list, &pos);
-	}
-
-	return mounted;
-}
-
-int umount_multi_triggers(struct autofs_point *ap, char *root, struct mapent *me, const char *base)
-{
-	char path[PATH_MAX + 1];
-	char *offset;
-	struct mapent *oe;
-	struct list_head *mm_root, *pos;
-	const char o_root[] = "/";
-	const char *mm_base;
-	int left, start;
-
-	left = 0;
-	start = strlen(root);
-
-	mm_root = &me->multi->multi_list;
-
-	if (!base)
-		mm_base = o_root;
-	else
-		mm_base = base;
-
-	pos = NULL;
-	offset = path;
-
-	/* Make sure "none" of the offsets have an active mount. */
-	while ((offset = cache_get_offset(mm_base, offset, start, mm_root, &pos))) {
-		char *oe_base;
-
-		oe = cache_lookup_offset(mm_base, offset, start, &me->multi_list);
-		/* root offset is a special case */
-		if (!oe || (strlen(oe->key) - start) == 1)
-			continue;
-
-		/*
-		 * Check for and umount subtree offsets resulting from
-		 * nonstrict mount fail.
-		 */
-		oe_base = oe->key + strlen(root);
-		left += umount_multi_triggers(ap, root, oe, oe_base);
-
-		if (oe->ioctlfd != -1)
-			left++;
-	}
-
-	if (left)
-		return left;
-
-	pos = NULL;
-	offset = path;
-
-	/* Make sure "none" of the offsets have an active mount. */
-	while ((offset = cache_get_offset(mm_base, offset, start, mm_root, &pos))) {
-		oe = cache_lookup_offset(mm_base, offset, start, &me->multi_list);
-		/* root offset is a special case */
-		if (!oe || (strlen(oe->key) - start) == 1)
-			continue;
-
-		debug(ap->logopt, "umount offset %s", oe->key);
-
-		if (umount_autofs_offset(ap, oe)) {
-			warn(ap->logopt, "failed to umount offset");
-			left++;
-		}
-	}
-
-	if (!left && me->multi == me) {
-		struct mapent_cache *mc = me->mc;
-		int status;
-
-		/*
-		 * Special case.
-		 * If we can't umount the root container then we can't
-		 * delete the offsets from the cache and we need to put
-		 * the offset triggers back.
-		 */
-		if (is_mounted(_PATH_MOUNTED, root, MNTS_REAL)) {
-			info(ap->logopt, "unmounting dir = %s", root);
-			if (umount_ent(ap, root)) {
-				if (!mount_multi_triggers(ap, root, me, "/"))
-					warn(ap->logopt,
-					     "failed to remount offset triggers");
-				return left++;
-			}
-		}
-
-		/* We're done - clean out the offsets */
-		status = cache_delete_offset_list(mc, me->key);
-		if (status != CHE_OK)
-			warn(ap->logopt, "couldn't delete offset list");
-	}
-
-	return left;
-}
-
diff -up autofs-5.0.3/lib/mounts.c.active-restart autofs-5.0.3/lib/mounts.c
--- autofs-5.0.3/lib/mounts.c.active-restart	2008-02-25 09:16:05.000000000 +0900
+++ autofs-5.0.3/lib/mounts.c	2008-02-25 09:16:46.000000000 +0900
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------- *
  *   
- *  mounts.c - module for Linux automount mount table lookup functions
+ *  mounts.c - module for mount utilities.
  *
  *   Copyright 2002-2005 Ian Kent <raven@themaw.net> - All Rights Reserved
  *
@@ -23,12 +23,21 @@
 #include <fcntl.h>
 #include <sys/mount.h>
 #include <stdio.h>
+#include <dirent.h>
+#include <sys/vfs.h>
+#include <pwd.h>
+#include <grp.h>
 
 #include "automount.h"
 
 #define MAX_OPTIONS_LEN		80
 #define MAX_MNT_NAME_LEN	30
 
+const unsigned int indirect = AUTOFS_TYPE_INDIRECT;
+const unsigned int direct = AUTOFS_TYPE_DIRECT;
+const unsigned int offset = AUTOFS_TYPE_OFFSET;
+const unsigned int type_count = 3;
+
 static const char options_template[]       = "fd=%d,pgrp=%u,minproto=5,maxproto=%d";
 static const char options_template_extra[] = "fd=%d,pgrp=%u,minproto=5,maxproto=%d,%s";
 static const char mnt_name_template[]      = "automount(pid%u)";
@@ -466,7 +475,7 @@ int has_fstab_option(const char *opt)
  * super block when searching for the mount.
  */
 int find_mnt_devid(const char *table,
-		   const char *path, char *devid, unsigned int type)
+		   const char *path, char *devid, const unsigned int type)
 {
 	struct mntent *mnt;
 	struct mntent mnt_wrk;
@@ -1070,3 +1079,528 @@ int tree_find_mnt_devid(struct mnt_list 
 	return 1;
 }
 
+void set_tsd_user_vars(unsigned int logopt, uid_t uid, gid_t gid)
+{
+	struct thread_stdenv_vars *tsv;
+	struct passwd pw;
+	struct passwd *ppw = &pw;
+	struct passwd **pppw = &ppw;
+	struct group gr;
+	struct group *pgr;
+	struct group **ppgr;
+	char *pw_tmp, *gr_tmp;
+	int status, tmplen, grplen;
+
+	/*
+	 * Setup thread specific data values for macro
+	 * substution in map entries during the mount.
+	 * Best effort only as it must go ahead.
+	 */
+
+	tsv = malloc(sizeof(struct thread_stdenv_vars));
+	if (!tsv) {
+		error(logopt, "failed alloc tsv storage");
+		return;
+	}
+
+	tsv->uid = uid;
+	tsv->gid = gid;
+
+	/* Try to get passwd info */
+
+	tmplen = sysconf(_SC_GETPW_R_SIZE_MAX);
+	if (tmplen < 0) {
+		error(logopt, "failed to get buffer size for getpwuid_r");
+		goto free_tsv;
+	}
+
+	pw_tmp = malloc(tmplen + 1);
+	if (!pw_tmp) {
+		error(logopt, "failed to malloc buffer for getpwuid_r");
+		goto free_tsv;
+	}
+
+	status = getpwuid_r(uid, ppw, pw_tmp, tmplen, pppw);
+	if (status || !ppw) {
+		error(logopt, "failed to get passwd info from getpwuid_r");
+		free(pw_tmp);
+		goto free_tsv;
+	}
+
+	tsv->user = strdup(pw.pw_name);
+	if (!tsv->user) {
+		error(logopt, "failed to malloc buffer for user");
+		free(pw_tmp);
+		goto free_tsv;
+	}
+
+	tsv->home = strdup(pw.pw_dir);
+	if (!tsv->user) {
+		error(logopt, "failed to malloc buffer for home");
+		free(pw_tmp);
+		goto free_tsv_user;
+	}
+
+	free(pw_tmp);
+
+	/* Try to get group info */
+
+	grplen = sysconf(_SC_GETGR_R_SIZE_MAX);
+	if (tmplen < 0) {
+		error(logopt, "failed to get buffer size for getgrgid_r");
+		goto free_tsv_home;
+	}
+
+	gr_tmp = NULL;
+	tmplen = grplen;
+	while (1) {
+		char *tmp = realloc(gr_tmp, tmplen + 1);
+		if (!tmp) {
+			error(logopt, "failed to malloc buffer for getgrgid_r");
+			if (gr_tmp)
+				free(gr_tmp);
+			goto free_tsv_home;
+		}
+		gr_tmp = tmp;
+		pgr = &gr;
+		ppgr = &pgr;
+		status = getgrgid_r(gid, pgr, gr_tmp, tmplen, ppgr);
+		if (status != ERANGE)
+			break;
+		tmplen += grplen;
+	}
+
+	if (status || !pgr) {
+		error(logopt, "failed to get group info from getgrgid_r");
+		free(gr_tmp);
+		goto free_tsv_home;
+	}
+
+	tsv->group = strdup(gr.gr_name);
+	if (!tsv->group) {
+		error(logopt, "failed to malloc buffer for group");
+		free(gr_tmp);
+		goto free_tsv_home;
+	}
+
+	free(gr_tmp);
+
+	status = pthread_setspecific(key_thread_stdenv_vars, tsv);
+	if (status) {
+		error(logopt, "failed to set stdenv thread var");
+		goto free_tsv_group;
+	}
+
+	return;
+
+free_tsv_group:
+	free(tsv->group);
+free_tsv_home:
+	free(tsv->home);
+free_tsv_user:
+	free(tsv->user);
+free_tsv:
+	free(tsv);
+	return;
+}
+
+const char *mount_type_str(const unsigned int type)
+{
+	static const char *str_type[] = {
+		"direct",
+		"indirect",
+		"offset"
+	};
+	unsigned int pos, i;
+
+	for (pos = 0, i = type; pos < type_count; i >>= 1, pos++)
+		if (i & 0x1)
+			break;
+
+	return (pos == type_count ? NULL : str_type[pos]);
+}
+
+void notify_mount_result(struct autofs_point *ap,
+			 const char *path, const char *type)
+{
+	if (ap->exp_timeout)
+		info(ap->logopt,
+		    "mounted %s on %s with timeout %u, freq %u seconds",
+		    type, path,
+		    (unsigned int) ap->exp_timeout,
+		    (unsigned int) ap->exp_runfreq);
+	else
+		info(ap->logopt,
+		     "mounted %s on %s with timeouts disabled",
+		     type, path);
+
+	return;
+}
+
+static int do_remount_direct(struct autofs_point *ap, int fd, const char *path)
+{
+	struct ioctl_ops *ops = get_ioctl_ops();
+	uid_t uid;
+	gid_t gid;
+	int ret;
+
+	ops->requestor(ap->logopt, fd, path, &uid, &gid);
+	if (uid != -1 && gid != -1)
+		set_tsd_user_vars(ap->logopt, uid, gid);
+
+	ret = lookup_nss_mount(ap, NULL, path, strlen(path));
+	if (ret)
+		info(ap->logopt, "re-mounted %s", path);
+	else
+		info(ap->logopt, "failed to re-mount %s", path);
+
+	return ret;
+}
+
+static int do_remount_indirect(struct autofs_point *ap, int fd, const char *path)
+{
+	struct ioctl_ops *ops = get_ioctl_ops();
+	struct dirent **de;
+	char buf[PATH_MAX + 1];
+	uid_t uid;
+	gid_t gid;
+	unsigned int mounted;
+	int n, size;
+
+	n = scandir(path, &de, 0, alphasort);
+	if (n < 0)
+		return -1;
+
+	size = sizeof(buf);
+
+	while (n--) {
+		int ret, len;
+
+		if (strcmp(de[n]->d_name, ".") == 0 ||
+		    strcmp(de[n]->d_name, "..") == 0) {
+			free(de[n]);
+			continue;
+		}
+
+		ret = cat_path(buf, size, path, de[n]->d_name);
+		if (!ret) {
+			do {
+				free(de[n]);
+			} while (n--);
+			free(de);
+			return -1;
+		}
+
+		ops->ismountpoint(ap->logopt, fd, buf, &mounted);
+		if (!mounted) {
+			free(de[n]);
+			continue;
+		}
+
+		ops->requestor(ap->logopt, fd, buf, &uid, &gid);
+		if (uid != -1 && gid != -1)
+			set_tsd_user_vars(ap->logopt, uid, gid);
+
+		len = strlen(de[n]->d_name);
+
+		ret = lookup_nss_mount(ap, NULL, de[n]->d_name, len);
+		if (ret)
+			info(ap->logopt, "re-mounted %s", buf);
+		else
+			info(ap->logopt, "failed to re-mount %s", buf);
+
+		free(de[n]);
+	}
+	free(de);
+
+	return 0;
+}
+
+int remount_active_mount(struct autofs_point *ap, struct mapent_cache *mc,
+			 const char *path, dev_t devid, const unsigned int type,
+			 int *ioctlfd)
+{
+	struct ioctl_ops *ops = get_ioctl_ops();
+	time_t timeout = ap->exp_timeout;
+	const char *str_type = mount_type_str(type);
+	unsigned int mounted;
+	struct stat st;
+	int fd;
+
+	*ioctlfd = -1;
+
+	/* Open failed, no mount present */
+	ops->open(ap->logopt, &fd, devid, path, type);
+	if (fd == -1)
+		return REMOUNT_OPEN_FAIL;
+
+	/* Re-reading the map, set timeout and return */
+	if (ap->state == ST_READMAP) {
+		ops->timeout(ap->logopt, fd, &timeout);
+		ops->close(ap->logopt, fd);
+		return REMOUNT_READ_MAP;
+	}
+
+	/* Mounted so set pipefd and timeout etc. */
+	ops->catatonic(ap->logopt, fd);
+	ops->setpipefd(ap->logopt, fd, ap->kpipefd);
+	ops->timeout(ap->logopt, fd, &timeout);
+	if (fstat(fd, &st) == -1) {
+		error(ap->logopt,
+		      "failed to stat %s mount %s", str_type, path);
+		ops->close(ap->logopt, fd);
+		return REMOUNT_STAT_FAIL;
+	}
+	ap->dev = st.st_dev;
+	if (mc)
+		cache_set_ino_index(mc, path, st.st_dev, st.st_ino);
+	notify_mount_result(ap, path, str_type);
+
+	debug(ap->logopt, "re-connected to mount %s", path);
+
+	*ioctlfd = fd;
+
+	/* Any mounts on or below? */
+	ops->ismountpoint(ap->logopt, fd, path, &mounted);
+	if (!mounted) {
+		/*
+		 * If we're an indirect mount we pass back the fd.
+		 * But if were a direct or offset mount with no active
+		 * mount we don't retain an open file descriptor.
+		 */
+		if (type == direct) {
+			ops->close(ap->logopt, fd);
+			*ioctlfd = -1;
+		}
+	} else {
+		/*
+		 * What can I do if we can't remount the existing
+		 * mount(s) (possibly a partial failure), everything
+		 * following will be broken?
+		 */
+		if (type == indirect)
+			do_remount_indirect(ap, fd, path);
+		else
+			do_remount_direct(ap, fd, path);
+	}
+
+	return REMOUNT_SUCCESS;
+}
+
+int umount_ent(struct autofs_point *ap, const char *path)
+{
+	struct stat st;
+	struct statfs fs;
+	int sav_errno;
+	int status, is_smbfs = 0;
+	int ret, rv = 1;
+
+	ret = statfs(path, &fs);
+	if (ret == -1) {
+		warn(ap->logopt, "could not stat fs of %s", path);
+		is_smbfs = 0;
+	} else {
+		int cifsfs = fs.f_type == (__SWORD_TYPE) CIFS_MAGIC_NUMBER;
+		int smbfs = fs.f_type == (__SWORD_TYPE) SMB_SUPER_MAGIC;
+		is_smbfs = (cifsfs | smbfs) ? 1 : 0;
+	}
+
+	status = lstat(path, &st);
+	sav_errno = errno;
+
+	if (status < 0)
+		warn(ap->logopt, "lstat of %s failed with %d", path, status);
+
+	/*
+	 * lstat failed and we're an smbfs fs returning an error that is not
+	 * EIO or EBADSLT or the lstat failed so it's a bad path. Return
+	 * a fail.
+	 *
+	 * EIO appears to correspond to an smb mount that has gone away
+	 * and EBADSLT relates to CD changer not responding.
+	 */
+	if (!status && (S_ISDIR(st.st_mode) && st.st_dev != ap->dev)) {
+		rv = spawn_umount(ap->logopt, path, NULL);
+	} else if (is_smbfs && (sav_errno == EIO || sav_errno == EBADSLT)) {
+		rv = spawn_umount(ap->logopt, path, NULL);
+	}
+
+	/* We are doing a forced shutcwdown down so unlink busy mounts */
+	if (rv && (ap->state == ST_SHUTDOWN_FORCE || ap->state == ST_SHUTDOWN)) {
+		ret = stat(path, &st);
+		if (ret == -1 && errno == ENOENT) {
+			warn(ap->logopt, "mount point does not exist");
+			return 0;
+		}
+
+		if (ret == 0 && !S_ISDIR(st.st_mode)) {
+			warn(ap->logopt, "mount point is not a directory");
+			return 0;
+		}
+
+		if (ap->state == ST_SHUTDOWN_FORCE) {
+			info(ap->logopt, "forcing umount of %s", path);
+			rv = spawn_umount(ap->logopt, "-l", path, NULL);
+		}
+
+		/*
+		 * Verify that we actually unmounted the thing.  This is a
+		 * belt and suspenders approach to not eating user data.
+		 * We have seen cases where umount succeeds, but there is
+		 * still a file system mounted on the mount point.  How
+		 * this happens has not yet been determined, but we want to
+		 * make sure to return failure here, if that is the case,
+		 * so that we do not try to call rmdir_path on the
+		 * directory.
+		 */
+		if (!rv && is_mounted(_PATH_MOUNTED, path, MNTS_REAL)) {
+			crit(ap->logopt,
+			     "the umount binary reported that %s was "
+			     "unmounted, but there is still something "
+			     "mounted on this path.", path);
+			rv = -1;
+		}
+	}
+
+	return rv;
+}
+
+int mount_multi_triggers(struct autofs_point *ap, char *root, struct mapent *me, const char *base)
+{
+	char path[PATH_MAX + 1];
+	char *offset = path;
+	struct mapent *oe;
+	struct list_head *pos = NULL;
+	unsigned int fs_path_len;
+	unsigned int mounted;
+	int start;
+
+	fs_path_len = strlen(root) + strlen(base);
+	if (fs_path_len > PATH_MAX)
+		return -1;
+
+	strcpy(path, root);
+	strcat(path, base);
+
+	mounted = 0;
+	start = strlen(root);
+	offset = cache_get_offset(base, offset, start, &me->multi_list, &pos);
+	while (offset) {
+		int plen = fs_path_len + strlen(offset);
+
+		if (plen > PATH_MAX) {
+			warn(ap->logopt, "path loo long");
+			goto cont;
+		}
+
+		oe = cache_lookup_offset(base, offset, start, &me->multi_list);
+		if (!oe)
+			goto cont;
+
+		debug(ap->logopt, "mount offset %s", oe->key);
+
+		if (mount_autofs_offset(ap, oe) < 0)
+			warn(ap->logopt, "failed to mount offset");
+		else
+			mounted++;
+cont:
+		offset = cache_get_offset(base,
+				offset, start, &me->multi_list, &pos);
+	}
+
+	return mounted;
+}
+
+int umount_multi_triggers(struct autofs_point *ap, char *root, struct mapent *me, const char *base)
+{
+	char path[PATH_MAX + 1];
+	char *offset;
+	struct mapent *oe;
+	struct list_head *mm_root, *pos;
+	const char o_root[] = "/";
+	const char *mm_base;
+	int left, start;
+
+	left = 0;
+	start = strlen(root);
+
+	mm_root = &me->multi->multi_list;
+
+	if (!base)
+		mm_base = o_root;
+	else
+		mm_base = base;
+
+	pos = NULL;
+	offset = path;
+
+	/* Make sure "none" of the offsets have an active mount. */
+	while ((offset = cache_get_offset(mm_base, offset, start, mm_root, &pos))) {
+		char *oe_base;
+
+		oe = cache_lookup_offset(mm_base, offset, start, &me->multi_list);
+		/* root offset is a special case */
+		if (!oe || (strlen(oe->key) - start) == 1)
+			continue;
+
+		/*
+		 * Check for and umount subtree offsets resulting from
+		 * nonstrict mount fail.
+		 */
+		oe_base = oe->key + strlen(root);
+		left += umount_multi_triggers(ap, root, oe, oe_base);
+
+		if (oe->ioctlfd != -1)
+			left++;
+	}
+
+	if (left)
+		return left;
+
+	pos = NULL;
+	offset = path;
+
+	/* Make sure "none" of the offsets have an active mount. */
+	while ((offset = cache_get_offset(mm_base, offset, start, mm_root, &pos))) {
+		oe = cache_lookup_offset(mm_base, offset, start, &me->multi_list);
+		/* root offset is a special case */
+		if (!oe || (strlen(oe->key) - start) == 1)
+			continue;
+
+		debug(ap->logopt, "umount offset %s", oe->key);
+
+		if (umount_autofs_offset(ap, oe)) {
+			warn(ap->logopt, "failed to umount offset");
+			left++;
+		}
+	}
+
+	if (!left && me->multi == me) {
+		struct mapent_cache *mc = me->mc;
+		int status;
+
+		/*
+		 * Special case.
+		 * If we can't umount the root container then we can't
+		 * delete the offsets from the cache and we need to put
+		 * the offset triggers back.
+		 */
+		if (is_mounted(_PATH_MOUNTED, root, MNTS_REAL)) {
+			info(ap->logopt, "unmounting dir = %s", root);
+			if (umount_ent(ap, root)) {
+				if (!mount_multi_triggers(ap, root, me, "/"))
+					warn(ap->logopt,
+					     "failed to remount offset triggers");
+				return left++;
+			}
+		}
+
+		/* We're done - clean out the offsets */
+		status = cache_delete_offset_list(mc, me->key);
+		if (status != CHE_OK)
+			warn(ap->logopt, "couldn't delete offset list");
+	}
+
+	return left;
+}
+
diff -up autofs-5.0.3/lib/cache.c.active-restart autofs-5.0.3/lib/cache.c
--- autofs-5.0.3/lib/cache.c.active-restart	2008-01-14 13:39:16.000000000 +0900
+++ autofs-5.0.3/lib/cache.c	2008-02-25 09:16:46.000000000 +0900
@@ -111,14 +111,29 @@ void cache_lock_cleanup(void *arg)
 	return;
 }
 
-void cache_multi_lock(struct mapent *me)
+void cache_multi_readlock(struct mapent *me)
 {
 	int status;
 
 	if (!me)
 		return;
 
-	status = pthread_mutex_lock(&me->multi_mutex);
+	status = pthread_rwlock_rdlock(&me->multi_rwlock);
+	if (status) {
+		logmsg("mapent cache multi mutex lock failed");
+		fatal(status);
+	}
+	return;
+}
+
+void cache_multi_writelock(struct mapent *me)
+{
+	int status;
+
+	if (!me)
+		return;
+
+	status = pthread_rwlock_wrlock(&me->multi_rwlock);
 	if (status) {
 		logmsg("mapent cache multi mutex lock failed");
 		fatal(status);
@@ -133,7 +148,7 @@ void cache_multi_unlock(struct mapent *m
 	if (!me)
 		return;
 
-	status = pthread_mutex_unlock(&me->multi_mutex);
+	status = pthread_rwlock_unlock(&me->multi_rwlock);
 	if (status) {
 		logmsg("mapent cache multi mutex unlock failed");
 		fatal(status);
@@ -553,8 +568,9 @@ int cache_add(struct mapent_cache *mc, s
 	me->ioctlfd = -1;
 	me->dev = (dev_t) -1;
 	me->ino = (ino_t) -1;
+	me->dir_created = 0;
 
-	status = pthread_mutex_init(&me->multi_mutex, NULL);
+	status = pthread_rwlock_init(&me->multi_rwlock, NULL);
 	if (status)
 		fatal(status);
 
@@ -760,7 +776,7 @@ int cache_delete(struct mapent_cache *mc
 				goto done;
 			}
 			pred->next = me->next;
-			status = pthread_mutex_destroy(&me->multi_mutex);
+			status = pthread_rwlock_destroy(&me->multi_rwlock);
 			if (status)
 				fatal(status);
 			ino_index_lock(mc);
@@ -784,7 +800,7 @@ int cache_delete(struct mapent_cache *mc
 			goto done;
 		}
 		mc->hash[hashval] = me->next;
-		status = pthread_mutex_destroy(&me->multi_mutex);
+		status = pthread_rwlock_destroy(&me->multi_rwlock);
 		if (status)
 			fatal(status);
 		ino_index_lock(mc);
diff -up autofs-5.0.3/lib/master.c.active-restart autofs-5.0.3/lib/master.c
--- autofs-5.0.3/lib/master.c.active-restart	2008-02-25 09:16:05.000000000 +0900
+++ autofs-5.0.3/lib/master.c	2008-02-25 09:16:46.000000000 +0900
@@ -997,28 +997,31 @@ next:
 
 static int master_do_mount(struct master_mapent *entry)
 {
+	struct startup_cond suc;
 	struct autofs_point *ap;
 	pthread_t thid;
 	int status;
 
-	status = pthread_mutex_lock(&suc.mutex);
-	if (status)
-		fatal(status);
+	ap = entry->ap;
+
+	if (handle_mounts_startup_cond_init(&suc)) {
+		crit(ap->logopt,
+		     "failed to init startup cond for mount %s", entry->path);
+		return 0;
+	}
 
+	suc.ap = ap;
 	suc.done = 0;
 	suc.status = 0;
 
-	ap = entry->ap;
-
 	debug(ap->logopt, "mounting %s", entry->path);
 
-	if (pthread_create(&thid, &thread_attr, handle_mounts, ap)) {
+	status = pthread_create(&thid, &thread_attr, handle_mounts, &suc);
+	if (status) {
 		crit(ap->logopt,
 		     "failed to create mount handler thread for %s",
 		     entry->path);
-		status = pthread_mutex_unlock(&suc.mutex);
-		if (status)
-			fatal(status);
+		handle_mounts_startup_cond_destroy(&suc);
 		return 0;
 	}
 	entry->thid = thid;
@@ -1031,15 +1034,11 @@ static int master_do_mount(struct master
 
 	if (suc.status) {
 		error(ap->logopt, "failed to startup mount");
-		status = pthread_mutex_unlock(&suc.mutex);
-		if (status)
-			fatal(status);
+		handle_mounts_startup_cond_destroy(&suc);
 		return 0;
 	}
 
-	status = pthread_mutex_unlock(&suc.mutex);
-	if (status)
-		fatal(status);
+	handle_mounts_startup_cond_destroy(&suc);
 
 	return 1;
 }
diff -up autofs-5.0.3/CHANGELOG.active-restart autofs-5.0.3/CHANGELOG
--- autofs-5.0.3/CHANGELOG.active-restart	2008-02-25 09:16:05.000000000 +0900
+++ autofs-5.0.3/CHANGELOG	2008-02-25 09:16:46.000000000 +0900
@@ -9,6 +9,7 @@
 - fix expire working harder than needed.
 - fix unlink of mount tree incorrectly causing autofs mount fail.
 - add miscellaneous device node interface library.
+- use miscellaneous device node, if available, for active restart.
  
 14/01/2008 autofs-5.0.3
 -----------------------