Ian Kent 9ef58b
autofs-5.0.4 - improve manual umount recovery
Ian Kent 9ef58b
Ian Kent 9ef58b
From: Ian Kent <raven@themaw.net>
Ian Kent 9ef58b
Ian Kent 9ef58b
The check for manually umounted mounts in the expire of direct mounts is
Ian Kent 9ef58b
racy and the check itself is inadequate in that it can incorrectly clear
Ian Kent 9ef58b
the descriptor of an active mount. Also, we do a similar test following
Ian Kent 9ef58b
the expire which is a waste since we can catch this on the next expire.
Ian Kent 9ef58b
So these two tests have been combined and the check done only prior to
Ian Kent 9ef58b
the expire. In the indirect expire we don't have a check at all so we
Ian Kent 9ef58b
add one.
Ian Kent 9ef58b
---
Ian Kent 9ef58b
Ian Kent 9ef58b
 CHANGELOG         |    1 +
Ian Kent 9ef58b
 daemon/direct.c   |   28 ++++++++++------------------
Ian Kent 9ef58b
 daemon/indirect.c |   47 ++++++++++++++++++++++++++++++++++++++++++++++-
Ian Kent 9ef58b
 3 files changed, 57 insertions(+), 19 deletions(-)
Ian Kent 9ef58b
Ian Kent 9ef58b
Ian Kent 9ef58b
diff --git a/CHANGELOG b/CHANGELOG
Ian Kent 9ef58b
index 5e01812..89aaa99 100644
Ian Kent 9ef58b
--- a/CHANGELOG
Ian Kent 9ef58b
+++ b/CHANGELOG
Ian Kent 9ef58b
@@ -45,6 +45,7 @@
Ian Kent 9ef58b
 - fix kernel includes.
Ian Kent 9ef58b
 - dont umount existing direct mount on master re-read.
Ian Kent 9ef58b
 - fix incorrect shutdown introduced by library relaod fixes.
Ian Kent 9ef58b
+- improve manual umount recovery.
Ian Kent 9ef58b
 
Ian Kent 9ef58b
 4/11/2008 autofs-5.0.4
Ian Kent 9ef58b
 -----------------------
Ian Kent 9ef58b
diff --git a/daemon/direct.c b/daemon/direct.c
Ian Kent 9ef58b
index 4f4ff20..1ed2b15 100644
Ian Kent 9ef58b
--- a/daemon/direct.c
Ian Kent 9ef58b
+++ b/daemon/direct.c
Ian Kent 9ef58b
@@ -881,13 +881,14 @@ void *expire_proc_direct(void *arg)
Ian Kent 9ef58b
 			 * avoid maintaining a file handle for control
Ian Kent 9ef58b
 			 * functions as once it's mounted all opens are
Ian Kent 9ef58b
 			 * directed to the mount not the trigger.
Ian Kent 9ef58b
-			 * But first expire possible rootless offsets first.
Ian Kent 9ef58b
 			 */
Ian Kent 9ef58b
 
Ian Kent 9ef58b
-			/* Offsets always have a real mount at their base */
Ian Kent 9ef58b
+			/* Check for manual umount */
Ian Kent 9ef58b
 			cache_writelock(me->mc);
Ian Kent 9ef58b
-			if (strstr(next->opts, "offset")) {
Ian Kent 9ef58b
-				ops->close(ap->logopt, me->ioctlfd);
Ian Kent 9ef58b
+			if (me->ioctlfd != -1 && 
Ian Kent 9ef58b
+			    fstat(ioctlfd, &st) != -1 &&
Ian Kent 9ef58b
+			    !count_mounts(ap->logopt, next->path, st.st_dev)) {
Ian Kent 9ef58b
+				ops->close(ap->logopt, ioctlfd);
Ian Kent 9ef58b
 				me->ioctlfd = -1;
Ian Kent 9ef58b
 				cache_unlock(me->mc);
Ian Kent 9ef58b
 				pthread_setcancelstate(cur_state, NULL);
Ian Kent 9ef58b
@@ -904,15 +905,6 @@ void *expire_proc_direct(void *arg)
Ian Kent 9ef58b
 				continue;
Ian Kent 9ef58b
 			}
Ian Kent 9ef58b
 
Ian Kent 9ef58b
-			cache_writelock(me->mc);
Ian Kent 9ef58b
-			if (me->ioctlfd != -1 && 
Ian Kent 9ef58b
-			    fstat(ioctlfd, &st) != -1 &&
Ian Kent 9ef58b
-			    !count_mounts(ap->logopt, next->path, st.st_dev)) {
Ian Kent 9ef58b
-				ops->close(ap->logopt, ioctlfd);
Ian Kent 9ef58b
-				me->ioctlfd = -1;
Ian Kent 9ef58b
-			}
Ian Kent 9ef58b
-			cache_unlock(me->mc);
Ian Kent 9ef58b
-
Ian Kent 9ef58b
 			pthread_setcancelstate(cur_state, NULL);
Ian Kent 9ef58b
 			continue;
Ian Kent 9ef58b
 		}
Ian Kent 9ef58b
@@ -1068,7 +1060,7 @@ int handle_packet_expire_direct(struct autofs_point *ap, autofs_packet_expire_di
Ian Kent 9ef58b
 	map = ap->entry->maps;
Ian Kent 9ef58b
 	while (map) {
Ian Kent 9ef58b
 		mc = map->mc;
Ian Kent 9ef58b
-		cache_readlock(mc);
Ian Kent 9ef58b
+		cache_writelock(mc);
Ian Kent 9ef58b
 		me = cache_lookup_ino(mc, pkt->dev, pkt->ino);
Ian Kent 9ef58b
 		if (me)
Ian Kent 9ef58b
 			break;
Ian Kent 9ef58b
@@ -1345,7 +1337,7 @@ int handle_packet_missing_direct(struct autofs_point *ap, autofs_packet_missing_
Ian Kent 9ef58b
 		}
Ian Kent 9ef58b
 
Ian Kent 9ef58b
 		mc = map->mc;
Ian Kent 9ef58b
-		cache_readlock(mc);
Ian Kent 9ef58b
+		cache_writelock(mc);
Ian Kent 9ef58b
 		me = cache_lookup_ino(mc, pkt->dev, pkt->ino);
Ian Kent 9ef58b
 		if (me)
Ian Kent 9ef58b
 			break;
Ian Kent 9ef58b
@@ -1367,10 +1359,10 @@ int handle_packet_missing_direct(struct autofs_point *ap, autofs_packet_missing_
Ian Kent 9ef58b
 
Ian Kent 9ef58b
 	if (me->ioctlfd != -1) {
Ian Kent 9ef58b
 		/* Maybe someone did a manual umount, clean up ! */
Ian Kent 9ef58b
-		ioctlfd = me->ioctlfd;
Ian Kent 9ef58b
+		close(me->ioctlfd);
Ian Kent 9ef58b
 		me->ioctlfd = -1;
Ian Kent 9ef58b
-	} else
Ian Kent 9ef58b
-		ops->open(ap->logopt, &ioctlfd, me->dev, me->key);
Ian Kent 9ef58b
+	}
Ian Kent 9ef58b
+	ops->open(ap->logopt, &ioctlfd, me->dev, me->key);
Ian Kent 9ef58b
 
Ian Kent 9ef58b
 	if (ioctlfd == -1) {
Ian Kent 9ef58b
 		cache_unlock(mc);
Ian Kent 9ef58b
diff --git a/daemon/indirect.c b/daemon/indirect.c
Ian Kent 9ef58b
index 2539282..bc39e63 100644
Ian Kent 9ef58b
--- a/daemon/indirect.c
Ian Kent 9ef58b
+++ b/daemon/indirect.c
Ian Kent 9ef58b
@@ -428,8 +428,53 @@ void *expire_proc_indirect(void *arg)
Ian Kent 9ef58b
 			pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
Ian Kent 9ef58b
 			if (strstr(next->opts, "indirect"))
Ian Kent 9ef58b
 				master_notify_submount(ap, next->path, ap->state);
Ian Kent 9ef58b
-			pthread_setcancelstate(cur_state, NULL);
Ian Kent 9ef58b
+			else if (strstr(next->opts, "offset")) {
Ian Kent 9ef58b
+				struct map_source *map;
Ian Kent 9ef58b
+				struct mapent_cache *mc = NULL;
Ian Kent 9ef58b
+				struct mapent *me = NULL;
Ian Kent 9ef58b
+				struct stat st;
Ian Kent 9ef58b
+
Ian Kent 9ef58b
+				master_source_readlock(ap->entry);
Ian Kent 9ef58b
+
Ian Kent 9ef58b
+				map = ap->entry->maps;
Ian Kent 9ef58b
+				while (map) {
Ian Kent 9ef58b
+					mc = map->mc;
Ian Kent 9ef58b
+					cache_writelock(mc);
Ian Kent 9ef58b
+					me = cache_lookup_distinct(mc, next->path);
Ian Kent 9ef58b
+					if (me)
Ian Kent 9ef58b
+						break;
Ian Kent 9ef58b
+					cache_unlock(mc);
Ian Kent 9ef58b
+					map = map->next;
Ian Kent 9ef58b
+				}
Ian Kent 9ef58b
 
Ian Kent 9ef58b
+				if (!mc || !me) {
Ian Kent 9ef58b
+					master_source_unlock(ap->entry);
Ian Kent 9ef58b
+					pthread_setcancelstate(cur_state, NULL);
Ian Kent 9ef58b
+					continue;
Ian Kent 9ef58b
+				}
Ian Kent 9ef58b
+
Ian Kent 9ef58b
+				/* Check for manual umount */
Ian Kent 9ef58b
+				if (me->ioctlfd != -1 &&
Ian Kent 9ef58b
+				    (fstat(me->ioctlfd, &st) == -1 ||
Ian Kent 9ef58b
+				     !count_mounts(ap->logopt, me->key, st.st_dev))) {
Ian Kent 9ef58b
+					if (is_mounted(_PROC_MOUNTS, me->key, MNTS_REAL)) {
Ian Kent 9ef58b
+						error(ap->logopt,
Ian Kent 9ef58b
+						      "error: possible mtab mismatch %s",
Ian Kent 9ef58b
+						      me->key);
Ian Kent 9ef58b
+						cache_unlock(mc);
Ian Kent 9ef58b
+						master_source_unlock(ap->entry);
Ian Kent 9ef58b
+						pthread_setcancelstate(cur_state, NULL);
Ian Kent 9ef58b
+						continue;
Ian Kent 9ef58b
+					}
Ian Kent 9ef58b
+					close(me->ioctlfd);
Ian Kent 9ef58b
+					me->ioctlfd = -1;
Ian Kent 9ef58b
+				}
Ian Kent 9ef58b
+
Ian Kent 9ef58b
+				cache_unlock(mc);
Ian Kent 9ef58b
+				master_source_unlock(ap->entry);
Ian Kent 9ef58b
+			}
Ian Kent 9ef58b
+
Ian Kent 9ef58b
+			pthread_setcancelstate(cur_state, NULL);
Ian Kent 9ef58b
 			continue;
Ian Kent 9ef58b
 		}
Ian Kent 9ef58b