Ian Kent 3685ec
autofs-5.0.3 - try not to block on expire
Ian Kent 3685ec
Ian Kent 3685ec
From: Ian Kent <raven@themaw.net>
Ian Kent 3685ec
Ian Kent 3685ec
When a server is not available umount and any stat statfs and related
Ian Kent 3685ec
function calls may block for a significant amount of time. This effects
Ian Kent 3685ec
expire timeouts a lot due to their synchronous nature. This patch limits
Ian Kent 3685ec
the time we wait on spawned umounts and elininates calls to functions
Ian Kent 3685ec
that would block. This allows us to retry the umount on the next expire
Ian Kent 3685ec
event and continue the expire of remaining mounts.
Ian Kent 3685ec
---
Ian Kent 3685ec
Ian Kent 3685ec
 CHANGELOG          |    2 ++
Ian Kent 3685ec
 daemon/automount.c |   34 ++++++++++++++++++------------
Ian Kent 3685ec
 daemon/direct.c    |   29 +++++---------------------
Ian Kent 3685ec
 daemon/indirect.c  |   26 +++++++++--------------
Ian Kent 3685ec
 daemon/spawn.c     |   59 ++++++++++++++++++++++++++++++++++++++++++----------
Ian Kent 3685ec
 include/master.h   |    1 +
Ian Kent 3685ec
 lib/master.c       |   23 ++++++++++++++++++++
Ian Kent 3685ec
 lib/mounts.c       |   48 ++----------------------------------------
Ian Kent 3685ec
 8 files changed, 112 insertions(+), 110 deletions(-)
Ian Kent 3685ec
Ian Kent 3685ec
Ian Kent 3685ec
diff --git a/CHANGELOG b/CHANGELOG
Ian Kent 3685ec
index ff04985..ff44cc7 100644
Ian Kent 3685ec
--- a/CHANGELOG
Ian Kent 3685ec
+++ b/CHANGELOG
Ian Kent 3685ec
@@ -27,6 +27,8 @@
Ian Kent 3685ec
 - don't use proc file system when checking if the daemon is running.
Ian Kent 3685ec
 - make handle_mounts startup condition distinct.
Ian Kent 3685ec
 - fix submount shutdown recovery handling.
Ian Kent 3685ec
+- avoid stat of possibly dead mount points and limit time to wait for
Ian Kent 3685ec
+  umount during expire.
Ian Kent 3685ec
  
Ian Kent 3685ec
 14/01/2008 autofs-5.0.3
Ian Kent 3685ec
 -----------------------
Ian Kent 3685ec
diff --git a/daemon/automount.c b/daemon/automount.c
Ian Kent 3685ec
index 68bf1d3..5bd5f6d 100644
Ian Kent 3685ec
--- a/daemon/automount.c
Ian Kent 3685ec
+++ b/daemon/automount.c
Ian Kent 3685ec
@@ -247,9 +247,17 @@ static int walk_tree(const char *base, int (*fn) (unsigned logopt,
Ian Kent 3685ec
 						  int, void *), int incl, unsigned logopt, void *arg)
Ian Kent 3685ec
 {
Ian Kent 3685ec
 	char buf[PATH_MAX + 1];
Ian Kent 3685ec
-	struct stat st;
Ian Kent 3685ec
+	struct stat st, *pst = &st;
Ian Kent 3685ec
+	int ret;
Ian Kent 3685ec
+
Ian Kent 3685ec
+	if (!is_mounted(_PATH_MOUNTED, base, MNTS_REAL))
Ian Kent 3685ec
+		ret = lstat(base, pst);
Ian Kent 3685ec
+	else {
Ian Kent 3685ec
+		pst = NULL;
Ian Kent 3685ec
+		ret = 0;
Ian Kent 3685ec
+	}
Ian Kent 3685ec
 
Ian Kent 3685ec
-	if (lstat(base, &st) != -1 && (fn) (logopt, base, &st, 0, arg)) {
Ian Kent 3685ec
+	if (ret != -1 && (fn) (logopt, base, pst, 0, arg)) {
Ian Kent 3685ec
 		if (S_ISDIR(st.st_mode)) {
Ian Kent 3685ec
 			struct dirent **de;
Ian Kent 3685ec
 			int n;
Ian Kent 3685ec
@@ -283,7 +291,7 @@ static int walk_tree(const char *base, int (*fn) (unsigned logopt,
Ian Kent 3685ec
 			free(de);
Ian Kent 3685ec
 		}
Ian Kent 3685ec
 		if (incl)
Ian Kent 3685ec
-			(fn) (logopt, base, &st, 1, arg);
Ian Kent 3685ec
+			(fn) (logopt, base, pst, 1, arg);
Ian Kent 3685ec
 	}
Ian Kent 3685ec
 	return 0;
Ian Kent 3685ec
 }
Ian Kent 3685ec
@@ -294,6 +302,9 @@ static int rm_unwanted_fn(unsigned logopt, const char *file, const struct stat *
Ian Kent 3685ec
 	char buf[MAX_ERR_BUF];
Ian Kent 3685ec
 	struct stat newst;
Ian Kent 3685ec
 
Ian Kent 3685ec
+	if (!st)
Ian Kent 3685ec
+		return 0;
Ian Kent 3685ec
+
Ian Kent 3685ec
 	if (when == 0) {
Ian Kent 3685ec
 		if (st->st_dev != dev)
Ian Kent 3685ec
 			return 0;
Ian Kent 3685ec
@@ -344,8 +355,8 @@ static int counter_fn(unsigned logopt, const char *file, const struct stat *st,
Ian Kent 3685ec
 {
Ian Kent 3685ec
 	struct counter_args *counter = (struct counter_args *) arg;
Ian Kent 3685ec
 
Ian Kent 3685ec
-	if (S_ISLNK(st->st_mode) || (S_ISDIR(st->st_mode) 
Ian Kent 3685ec
-		&& st->st_dev != counter->dev)) {
Ian Kent 3685ec
+	if (!st || (S_ISLNK(st->st_mode) || (S_ISDIR(st->st_mode)
Ian Kent 3685ec
+		&& st->st_dev != counter->dev))) {
Ian Kent 3685ec
 		counter->count++;
Ian Kent 3685ec
 		return 0;
Ian Kent 3685ec
 	}
Ian Kent 3685ec
@@ -512,9 +523,8 @@ static int umount_subtree_mounts(struct autofs_point *ap, const char *path, unsi
Ian Kent 3685ec
 int umount_multi(struct autofs_point *ap, const char *path, int incl)
Ian Kent 3685ec
 {
Ian Kent 3685ec
 	struct mapent_cache *nc;
Ian Kent 3685ec
-	struct statfs fs;
Ian Kent 3685ec
 	int is_autofs_fs;
Ian Kent 3685ec
-	int ret, left;
Ian Kent 3685ec
+	int left;
Ian Kent 3685ec
 
Ian Kent 3685ec
 	debug(ap->logopt, "path %s incl %d", path, incl);
Ian Kent 3685ec
 
Ian Kent 3685ec
@@ -526,13 +536,9 @@ int umount_multi(struct autofs_point *ap, const char *path, int incl)
Ian Kent 3685ec
 	}
Ian Kent 3685ec
 	cache_unlock(nc);
Ian Kent 3685ec
 
Ian Kent 3685ec
-	ret = statfs(path, &fs);
Ian Kent 3685ec
-	if (ret == -1) {
Ian Kent 3685ec
-		error(ap->logopt, "could not stat fs of %s", path);
Ian Kent 3685ec
-		return 1;
Ian Kent 3685ec
-	}
Ian Kent 3685ec
-
Ian Kent 3685ec
-	is_autofs_fs = fs.f_type == (__SWORD_TYPE) AUTOFS_SUPER_MAGIC ? 1 : 0;
Ian Kent 3685ec
+	is_autofs_fs = 0;
Ian Kent 3685ec
+	if (master_find_submount(ap, path))
Ian Kent 3685ec
+		is_autofs_fs = 1;
Ian Kent 3685ec
 
Ian Kent 3685ec
 	left = 0;
Ian Kent 3685ec
 
Ian Kent 3685ec
diff --git a/daemon/direct.c b/daemon/direct.c
Ian Kent 3685ec
index 334a4b6..7fb78a3 100644
Ian Kent 3685ec
--- a/daemon/direct.c
Ian Kent 3685ec
+++ b/daemon/direct.c
Ian Kent 3685ec
@@ -152,7 +152,7 @@ int do_umount_autofs_direct(struct autofs_point *ap, struct mnt_list *mnts, stru
Ian Kent 3685ec
 
Ian Kent 3685ec
 	retries = UMOUNT_RETRIES;
Ian Kent 3685ec
 	while ((rv = umount(me->key)) == -1 && retries--) {
Ian Kent 3685ec
-		struct timespec tm = {0, 100000000};
Ian Kent 3685ec
+		struct timespec tm = {0, 200000000};
Ian Kent 3685ec
 		if (errno != EBUSY)
Ian Kent 3685ec
 			break;
Ian Kent 3685ec
 		nanosleep(&tm, NULL);
Ian Kent 3685ec
@@ -604,7 +604,7 @@ int umount_autofs_offset(struct autofs_point *ap, struct mapent *me)
Ian Kent 3685ec
 
Ian Kent 3685ec
 	retries = UMOUNT_RETRIES;
Ian Kent 3685ec
 	while ((rv = umount(me->key)) == -1 && retries--) {
Ian Kent 3685ec
-		struct timespec tm = {0, 100000000};
Ian Kent 3685ec
+		struct timespec tm = {0, 200000000};
Ian Kent 3685ec
 		if (errno != EBUSY)
Ian Kent 3685ec
 			break;
Ian Kent 3685ec
 		nanosleep(&tm, NULL);
Ian Kent 3685ec
@@ -705,7 +705,7 @@ int mount_autofs_offset(struct autofs_point *ap, struct mapent *me)
Ian Kent 3685ec
 			 * the kernel NFS client.
Ian Kent 3685ec
 			 */
Ian Kent 3685ec
 			if (me->multi != me &&
Ian Kent 3685ec
-			    is_mounted(_PROC_MOUNTS, me->key, MNTS_REAL))
Ian Kent 3685ec
+			    is_mounted(_PATH_MOUNTED, me->key, MNTS_REAL))
Ian Kent 3685ec
 				return MOUNT_OFFSET_IGNORE;
Ian Kent 3685ec
 
Ian Kent 3685ec
 			/* 
Ian Kent 3685ec
@@ -807,17 +807,7 @@ out_err:
Ian Kent 3685ec
 
Ian Kent 3685ec
 static int expire_direct(int ioctlfd, const char *path, unsigned int when, unsigned int logopt)
Ian Kent 3685ec
 {
Ian Kent 3685ec
-	char buf[MAX_ERR_BUF];
Ian Kent 3685ec
-	int ret, retries;
Ian Kent 3685ec
-	struct stat st;
Ian Kent 3685ec
-
Ian Kent 3685ec
-	if (fstat(ioctlfd, &st) == -1) {
Ian Kent 3685ec
-		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
Ian Kent 3685ec
-		debug(logopt, "fstat failed: %s", estr);
Ian Kent 3685ec
-		return 0;
Ian Kent 3685ec
-	}
Ian Kent 3685ec
-
Ian Kent 3685ec
-	retries = (count_mounts(logopt, path, st.st_dev) + 1) * EXPIRE_RETRIES;
Ian Kent 3685ec
+	int ret, retries = EXPIRE_RETRIES;
Ian Kent 3685ec
 
Ian Kent 3685ec
 	while (retries--) {
Ian Kent 3685ec
 		struct timespec tm = {0, 100000000};
Ian Kent 3685ec
@@ -911,7 +901,6 @@ void *expire_proc_direct(void *arg)
Ian Kent 3685ec
 
Ian Kent 3685ec
 		if (!strcmp(next->fs_type, "autofs")) {
Ian Kent 3685ec
 			struct stat st;
Ian Kent 3685ec
-			struct statfs fs;
Ian Kent 3685ec
 			int ioctlfd;
Ian Kent 3685ec
 
Ian Kent 3685ec
 			cache_unlock(me->mc);
Ian Kent 3685ec
@@ -932,14 +921,8 @@ void *expire_proc_direct(void *arg)
Ian Kent 3685ec
 				continue;
Ian Kent 3685ec
 			}
Ian Kent 3685ec
 
Ian Kent 3685ec
-			if (statfs(next->path, &fs) == -1) {
Ian Kent 3685ec
-				pthread_setcancelstate(cur_state, NULL);
Ian Kent 3685ec
-				warn(ap->logopt,
Ian Kent 3685ec
-				    "fstatfs failed for %s", next->path);
Ian Kent 3685ec
-				continue;
Ian Kent 3685ec
-			}
Ian Kent 3685ec
-
Ian Kent 3685ec
-			if (fs.f_type != (__SWORD_TYPE) AUTOFS_SUPER_MAGIC) {
Ian Kent 3685ec
+			/* It's got a mount, deal with in the outer loop */
Ian Kent 3685ec
+			if (tree_is_mounted(mnts, me->key, MNTS_REAL)) {
Ian Kent 3685ec
 				pthread_setcancelstate(cur_state, NULL);
Ian Kent 3685ec
 				continue;
Ian Kent 3685ec
 			}
Ian Kent 3685ec
diff --git a/daemon/indirect.c b/daemon/indirect.c
Ian Kent 3685ec
index 17bed3e..e832cd4 100644
Ian Kent 3685ec
--- a/daemon/indirect.c
Ian Kent 3685ec
+++ b/daemon/indirect.c
Ian Kent 3685ec
@@ -285,7 +285,7 @@ int umount_autofs_indirect(struct autofs_point *ap)
Ian Kent 3685ec
 
Ian Kent 3685ec
 	retries = UMOUNT_RETRIES;
Ian Kent 3685ec
 	while ((rv = umount(ap->path)) == -1 && retries--) {
Ian Kent 3685ec
-		struct timespec tm = {0, 100000000};
Ian Kent 3685ec
+		struct timespec tm = {0, 200000000};
Ian Kent 3685ec
 		if (errno != EBUSY)
Ian Kent 3685ec
 			break;
Ian Kent 3685ec
 		nanosleep(&tm, NULL);
Ian Kent 3685ec
@@ -368,17 +368,7 @@ force_umount:
Ian Kent 3685ec
 
Ian Kent 3685ec
 static int expire_indirect(struct autofs_point *ap, int ioctlfd, const char *path, unsigned int when)
Ian Kent 3685ec
 {
Ian Kent 3685ec
-	char buf[MAX_ERR_BUF];
Ian Kent 3685ec
-	int ret, retries;
Ian Kent 3685ec
-	struct stat st;
Ian Kent 3685ec
-
Ian Kent 3685ec
-	if (fstat(ioctlfd, &st) == -1) {
Ian Kent 3685ec
-		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
Ian Kent 3685ec
-		debug(ap->logopt, "fstat failed: %s", estr);
Ian Kent 3685ec
-		return 0;
Ian Kent 3685ec
-	}
Ian Kent 3685ec
-
Ian Kent 3685ec
-	retries = (count_mounts(ap->logopt, path, st.st_dev) + 1) * EXPIRE_RETRIES;
Ian Kent 3685ec
+	int ret, retries = EXPIRE_RETRIES;
Ian Kent 3685ec
 
Ian Kent 3685ec
 	while (retries--) {
Ian Kent 3685ec
 		struct timespec tm = {0, 100000000};
Ian Kent 3685ec
@@ -512,7 +502,6 @@ void *expire_proc_indirect(void *arg)
Ian Kent 3685ec
 			left++;
Ian Kent 3685ec
 		pthread_setcancelstate(cur_state, NULL);
Ian Kent 3685ec
 	}
Ian Kent 3685ec
-	pthread_cleanup_pop(1);
Ian Kent 3685ec
 
Ian Kent 3685ec
 	/*
Ian Kent 3685ec
 	 * If there are no more real mounts left we could still
Ian Kent 3685ec
@@ -520,12 +509,17 @@ void *expire_proc_indirect(void *arg)
Ian Kent 3685ec
 	 * umount them here.
Ian Kent 3685ec
 	 */
Ian Kent 3685ec
 	if (mnts) {
Ian Kent 3685ec
+		int retries;
Ian Kent 3685ec
 		pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
Ian Kent 3685ec
-		ret = expire_indirect(ap, ap->ioctlfd, ap->path, now);
Ian Kent 3685ec
-		if (!ret)
Ian Kent 3685ec
-			left++;
Ian Kent 3685ec
+		retries = (count_mounts(ap->logopt, ap->path, ap->dev) + 1);
Ian Kent 3685ec
+		while (retries--) {
Ian Kent 3685ec
+			ret = expire_indirect(ap, ap->ioctlfd, ap->path, now);
Ian Kent 3685ec
+			if (!ret)
Ian Kent 3685ec
+				left++;
Ian Kent 3685ec
+		}
Ian Kent 3685ec
 		pthread_setcancelstate(cur_state, NULL);
Ian Kent 3685ec
 	}
Ian Kent 3685ec
+	pthread_cleanup_pop(1);
Ian Kent 3685ec
 
Ian Kent 3685ec
 	count = offsets = submnts = 0;
Ian Kent 3685ec
 	mnts = get_mnt_list(_PROC_MOUNTS, ap->path, 0);
Ian Kent 3685ec
diff --git a/daemon/spawn.c b/daemon/spawn.c
Ian Kent 3685ec
index 78d69c6..e3c355e 100644
Ian Kent 3685ec
--- a/daemon/spawn.c
Ian Kent 3685ec
+++ b/daemon/spawn.c
Ian Kent 3685ec
@@ -89,13 +89,43 @@ void reset_signals(void)
Ian Kent 3685ec
 
Ian Kent 3685ec
 #define ERRBUFSIZ 2047		/* Max length of error string excl \0 */
Ian Kent 3685ec
 
Ian Kent 3685ec
-static int do_spawn(unsigned logopt, unsigned int options, const char *prog, const char *const *argv)
Ian Kent 3685ec
+static int timed_read(int pipe, char *buf, size_t len, int time)
Ian Kent 3685ec
+{
Ian Kent 3685ec
+	struct timeval timeout = { 0, 0 };
Ian Kent 3685ec
+	struct timeval *tout = NULL;
Ian Kent 3685ec
+	fd_set wset, rset;
Ian Kent 3685ec
+	int ret;
Ian Kent 3685ec
+
Ian Kent 3685ec
+	FD_ZERO(&rset);
Ian Kent 3685ec
+	FD_SET(pipe, &rset);
Ian Kent 3685ec
+	wset = rset;
Ian Kent 3685ec
+
Ian Kent 3685ec
+	if (time != -1) {
Ian Kent 3685ec
+		timeout.tv_sec = time;
Ian Kent 3685ec
+		tout = &timeout;
Ian Kent 3685ec
+	}
Ian Kent 3685ec
+
Ian Kent 3685ec
+	ret = select(pipe + 1, &rset, &wset, NULL, tout);
Ian Kent 3685ec
+	if (ret <= 0) {
Ian Kent 3685ec
+		if (ret == 0)
Ian Kent 3685ec
+			ret = -ETIMEDOUT;
Ian Kent 3685ec
+		return ret;
Ian Kent 3685ec
+	}
Ian Kent 3685ec
+
Ian Kent 3685ec
+	while ((ret = read(pipe, buf, len)) == -1 && errno == EINTR);
Ian Kent 3685ec
+
Ian Kent 3685ec
+	return ret;
Ian Kent 3685ec
+}
Ian Kent 3685ec
+
Ian Kent 3685ec
+static int do_spawn(unsigned logopt, unsigned int wait,
Ian Kent 3685ec
+		    unsigned int options, const char *prog,
Ian Kent 3685ec
+		    const char *const *argv)
Ian Kent 3685ec
 {
Ian Kent 3685ec
 	pid_t f;
Ian Kent 3685ec
 	int ret, status, pipefd[2];
Ian Kent 3685ec
 	char errbuf[ERRBUFSIZ + 1], *p, *sp;
Ian Kent 3685ec
 	int errp, errn;
Ian Kent 3685ec
-	int cancel_state;
Ian Kent 3685ec
+	int flags, cancel_state;
Ian Kent 3685ec
 	unsigned int use_lock = options & SPAWN_OPT_LOCK;
Ian Kent 3685ec
 	unsigned int use_access = options & SPAWN_OPT_ACCESS;
Ian Kent 3685ec
 	sigset_t allsigs, tmpsig, oldsig;
Ian Kent 3685ec
@@ -183,12 +213,15 @@ static int do_spawn(unsigned logopt, unsigned int options, const char *prog, con
Ian Kent 3685ec
 			return -1;
Ian Kent 3685ec
 		}
Ian Kent 3685ec
 
Ian Kent 3685ec
+		if ((flags = fcntl(pipefd[0], F_GETFD, 0)) != -1) {
Ian Kent 3685ec
+			flags |= FD_CLOEXEC;
Ian Kent 3685ec
+			fcntl(pipefd[0], F_SETFD, flags);
Ian Kent 3685ec
+		}
Ian Kent 3685ec
+
Ian Kent 3685ec
 		errp = 0;
Ian Kent 3685ec
 		do {
Ian Kent 3685ec
-			while ((errn =
Ian Kent 3685ec
-				read(pipefd[0], errbuf + errp, ERRBUFSIZ - errp)) == -1
Ian Kent 3685ec
-			       && errno == EINTR);
Ian Kent 3685ec
-
Ian Kent 3685ec
+			errn = timed_read(pipefd[0],
Ian Kent 3685ec
+					  errbuf + errp, ERRBUFSIZ - errp, wait);
Ian Kent 3685ec
 			if (errn > 0) {
Ian Kent 3685ec
 				errp += errn;
Ian Kent 3685ec
 
Ian Kent 3685ec
@@ -213,6 +246,9 @@ static int do_spawn(unsigned logopt, unsigned int options, const char *prog, con
Ian Kent 3685ec
 			}
Ian Kent 3685ec
 		} while (errn > 0);
Ian Kent 3685ec
 
Ian Kent 3685ec
+		if (errn == -ETIMEDOUT)
Ian Kent 3685ec
+			kill(f, SIGTERM);
Ian Kent 3685ec
+
Ian Kent 3685ec
 		close(pipefd[0]);
Ian Kent 3685ec
 
Ian Kent 3685ec
 		if (errp > 0) {
Ian Kent 3685ec
@@ -238,7 +274,7 @@ static int do_spawn(unsigned logopt, unsigned int options, const char *prog, con
Ian Kent 3685ec
 
Ian Kent 3685ec
 int spawnv(unsigned logopt, const char *prog, const char *const *argv)
Ian Kent 3685ec
 {
Ian Kent 3685ec
-	return do_spawn(logopt, SPAWN_OPT_NONE, prog, argv);
Ian Kent 3685ec
+	return do_spawn(logopt, -1, SPAWN_OPT_NONE, prog, argv);
Ian Kent 3685ec
 }
Ian Kent 3685ec
 
Ian Kent 3685ec
 int spawnl(unsigned logopt, const char *prog, ...)
Ian Kent 3685ec
@@ -259,7 +295,7 @@ int spawnl(unsigned logopt, const char *prog, ...)
Ian Kent 3685ec
 	while ((*p++ = va_arg(arg, char *)));
Ian Kent 3685ec
 	va_end(arg);
Ian Kent 3685ec
 
Ian Kent 3685ec
-	return do_spawn(logopt, SPAWN_OPT_NONE, prog, (const char **) argv);
Ian Kent 3685ec
+	return do_spawn(logopt, -1, SPAWN_OPT_NONE, prog, (const char **) argv);
Ian Kent 3685ec
 }
Ian Kent 3685ec
 
Ian Kent 3685ec
 int spawn_mount(unsigned logopt, ...)
Ian Kent 3685ec
@@ -307,7 +343,7 @@ int spawn_mount(unsigned logopt, ...)
Ian Kent 3685ec
 	va_end(arg);
Ian Kent 3685ec
 
Ian Kent 3685ec
 	while (retries--) {
Ian Kent 3685ec
-		ret = do_spawn(logopt, options, prog, (const char **) argv);
Ian Kent 3685ec
+		ret = do_spawn(logopt, -1, options, prog, (const char **) argv);
Ian Kent 3685ec
 		if (ret & MTAB_NOTUPDATED) {
Ian Kent 3685ec
 			struct timespec tm = {3, 0};
Ian Kent 3685ec
 
Ian Kent 3685ec
@@ -406,7 +442,7 @@ int spawn_bind_mount(unsigned logopt, ...)
Ian Kent 3685ec
 	va_end(arg);
Ian Kent 3685ec
 
Ian Kent 3685ec
 	while (retries--) {
Ian Kent 3685ec
-		ret = do_spawn(logopt, options, prog, (const char **) argv);
Ian Kent 3685ec
+		ret = do_spawn(logopt, -1, options, prog, (const char **) argv);
Ian Kent 3685ec
 		if (ret & MTAB_NOTUPDATED) {
Ian Kent 3685ec
 			struct timespec tm = {3, 0};
Ian Kent 3685ec
 
Ian Kent 3685ec
@@ -466,6 +502,7 @@ int spawn_umount(unsigned logopt, ...)
Ian Kent 3685ec
 	unsigned int options;
Ian Kent 3685ec
 	unsigned int retries = MTAB_LOCK_RETRIES;
Ian Kent 3685ec
 	int ret, printed = 0;
Ian Kent 3685ec
+	unsigned int wait = 12;
Ian Kent 3685ec
 
Ian Kent 3685ec
 #ifdef ENABLE_MOUNT_LOCKING
Ian Kent 3685ec
 	options = SPAWN_OPT_LOCK;
Ian Kent 3685ec
@@ -488,7 +525,7 @@ int spawn_umount(unsigned logopt, ...)
Ian Kent 3685ec
 	va_end(arg);
Ian Kent 3685ec
 
Ian Kent 3685ec
 	while (retries--) {
Ian Kent 3685ec
-		ret = do_spawn(logopt, options, prog, (const char **) argv);
Ian Kent 3685ec
+		ret = do_spawn(logopt, wait, options, prog, (const char **) argv);
Ian Kent 3685ec
 		if (ret & MTAB_NOTUPDATED) {
Ian Kent 3685ec
 			/*
Ian Kent 3685ec
 			 * If the mount succeeded but the mtab was not
Ian Kent 3685ec
diff --git a/include/master.h b/include/master.h
Ian Kent 3685ec
index 86ae045..a397a75 100644
Ian Kent 3685ec
--- a/include/master.h
Ian Kent 3685ec
+++ b/include/master.h
Ian Kent 3685ec
@@ -91,6 +91,7 @@ void master_source_lock_cleanup(void *);
Ian Kent 3685ec
 void master_source_current_wait(struct master_mapent *);
Ian Kent 3685ec
 void master_source_current_signal(struct master_mapent *);
Ian Kent 3685ec
 struct master_mapent *master_find_mapent(struct master *, const char *);
Ian Kent 3685ec
+struct autofs_point *master_find_submount(struct autofs_point *, const char *);
Ian Kent 3685ec
 struct master_mapent *master_new_mapent(struct master *, const char *, time_t);
Ian Kent 3685ec
 void master_add_mapent(struct master *, struct master_mapent *);
Ian Kent 3685ec
 void master_remove_mapent(struct master_mapent *);
Ian Kent 3685ec
diff --git a/lib/master.c b/lib/master.c
Ian Kent 3685ec
index 522b919..71ba04a 100644
Ian Kent 3685ec
--- a/lib/master.c
Ian Kent 3685ec
+++ b/lib/master.c
Ian Kent 3685ec
@@ -602,6 +602,29 @@ struct master_mapent *master_find_mapent(struct master *master, const char *path
Ian Kent 3685ec
 	return NULL;
Ian Kent 3685ec
 }
Ian Kent 3685ec
 
Ian Kent 3685ec
+struct autofs_point *master_find_submount(struct autofs_point *ap, const char *path)
Ian Kent 3685ec
+{
Ian Kent 3685ec
+	struct list_head *head, *p;
Ian Kent 3685ec
+
Ian Kent 3685ec
+	mounts_mutex_lock(ap);
Ian Kent 3685ec
+
Ian Kent 3685ec
+	head = &ap->submounts;
Ian Kent 3685ec
+	list_for_each(p, head) {
Ian Kent 3685ec
+		struct autofs_point *submount;
Ian Kent 3685ec
+
Ian Kent 3685ec
+		submount = list_entry(p, struct autofs_point, mounts);
Ian Kent 3685ec
+
Ian Kent 3685ec
+		if (!strcmp(submount->path, path)) {
Ian Kent 3685ec
+			mounts_mutex_unlock(ap);
Ian Kent 3685ec
+			return submount;
Ian Kent 3685ec
+		}
Ian Kent 3685ec
+	}
Ian Kent 3685ec
+
Ian Kent 3685ec
+	mounts_mutex_unlock(ap);
Ian Kent 3685ec
+
Ian Kent 3685ec
+	return NULL;
Ian Kent 3685ec
+}
Ian Kent 3685ec
+
Ian Kent 3685ec
 struct master_mapent *master_new_mapent(struct master *master, const char *path, time_t age)
Ian Kent 3685ec
 {
Ian Kent 3685ec
 	struct master_mapent *entry;
Ian Kent 3685ec
diff --git a/lib/mounts.c b/lib/mounts.c
Ian Kent 3685ec
index a4bf86c..d77a6b0 100644
Ian Kent 3685ec
--- a/lib/mounts.c
Ian Kent 3685ec
+++ b/lib/mounts.c
Ian Kent 3685ec
@@ -1073,55 +1073,11 @@ free_tsv:
Ian Kent 3685ec
 
Ian Kent 3685ec
 int umount_ent(struct autofs_point *ap, const char *path)
Ian Kent 3685ec
 {
Ian Kent 3685ec
-	struct stat st;
Ian Kent 3685ec
-	struct statfs fs;
Ian Kent 3685ec
-	int sav_errno;
Ian Kent 3685ec
-	int status, is_smbfs = 0;
Ian Kent 3685ec
-	int ret, rv = 1;
Ian Kent 3685ec
-
Ian Kent 3685ec
-	ret = statfs(path, &fs);
Ian Kent 3685ec
-	if (ret == -1) {
Ian Kent 3685ec
-		warn(ap->logopt, "could not stat fs of %s", path);
Ian Kent 3685ec
-		is_smbfs = 0;
Ian Kent 3685ec
-	} else {
Ian Kent 3685ec
-		int cifsfs = fs.f_type == (__SWORD_TYPE) CIFS_MAGIC_NUMBER;
Ian Kent 3685ec
-		int smbfs = fs.f_type == (__SWORD_TYPE) SMB_SUPER_MAGIC;
Ian Kent 3685ec
-		is_smbfs = (cifsfs | smbfs) ? 1 : 0;
Ian Kent 3685ec
-	}
Ian Kent 3685ec
-
Ian Kent 3685ec
-	status = lstat(path, &st);
Ian Kent 3685ec
-	sav_errno = errno;
Ian Kent 3685ec
-
Ian Kent 3685ec
-	if (status < 0)
Ian Kent 3685ec
-		warn(ap->logopt, "lstat of %s failed with %d", path, status);
Ian Kent 3685ec
-
Ian Kent 3685ec
-	/*
Ian Kent 3685ec
-	 * lstat failed and we're an smbfs fs returning an error that is not
Ian Kent 3685ec
-	 * EIO or EBADSLT or the lstat failed so it's a bad path. Return
Ian Kent 3685ec
-	 * a fail.
Ian Kent 3685ec
-	 *
Ian Kent 3685ec
-	 * EIO appears to correspond to an smb mount that has gone away
Ian Kent 3685ec
-	 * and EBADSLT relates to CD changer not responding.
Ian Kent 3685ec
-	 */
Ian Kent 3685ec
-	if (!status && (S_ISDIR(st.st_mode) && st.st_dev != ap->dev)) {
Ian Kent 3685ec
-		rv = spawn_umount(ap->logopt, path, NULL);
Ian Kent 3685ec
-	} else if (is_smbfs && (sav_errno == EIO || sav_errno == EBADSLT)) {
Ian Kent 3685ec
-		rv = spawn_umount(ap->logopt, path, NULL);
Ian Kent 3685ec
-	}
Ian Kent 3685ec
+	int rv;
Ian Kent 3685ec
 
Ian Kent 3685ec
+	rv = spawn_umount(ap->logopt, path, NULL);
Ian Kent 3685ec
 	/* We are doing a forced shutcwdown down so unlink busy mounts */
Ian Kent 3685ec
 	if (rv && (ap->state == ST_SHUTDOWN_FORCE || ap->state == ST_SHUTDOWN)) {
Ian Kent 3685ec
-		ret = stat(path, &st);
Ian Kent 3685ec
-		if (ret == -1 && errno == ENOENT) {
Ian Kent 3685ec
-			warn(ap->logopt, "mount point does not exist");
Ian Kent 3685ec
-			return 0;
Ian Kent 3685ec
-		}
Ian Kent 3685ec
-
Ian Kent 3685ec
-		if (ret == 0 && !S_ISDIR(st.st_mode)) {
Ian Kent 3685ec
-			warn(ap->logopt, "mount point is not a directory");
Ian Kent 3685ec
-			return 0;
Ian Kent 3685ec
-		}
Ian Kent 3685ec
-
Ian Kent 3685ec
 		if (ap->state == ST_SHUTDOWN_FORCE) {
Ian Kent 3685ec
 			info(ap->logopt, "forcing umount of %s", path);
Ian Kent 3685ec
 			rv = spawn_umount(ap->logopt, "-l", path, NULL);