Blame SOURCES/autofs-5.1.1-always-set-direct-mounts-catatonic-at-exit.patch

019928
autofs-5.1.1 - always set direct mounts catatonic at exit
019928
019928
From: Ian Kent <raven@themaw.net>
019928
019928
Direct mounts are all mounted at application start or when the map
019928
is re-read and entries have been added.
019928
019928
They are only ever umounted at application exit or when the map is
019928
re-read and entries have been removed.
019928
019928
If these mounts are in use (so that they are not umounted) and aren't
019928
set catatonic at exit and an application attempts to access the path
019928
it will lead to a hang as there is no daemon to answer the mount
019928
request.
019928
019928
It's questionable whether to set busy direct mounts catatonic when
019928
attempting to umount them when re-reading the map as the mount may
019928
then expire leaving an unresponsive direct mount trigger that hasn't
019928
yet been cleaned from the map entry cache.
019928
019928
Signed-off-by: Ian Kent <raven@themaw.net>
019928
---
019928
 CHANGELOG       |    1 
019928
 daemon/direct.c |   99 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
019928
 2 files changed, 92 insertions(+), 8 deletions(-)
019928
019928
--- autofs-5.0.7.orig/CHANGELOG
019928
+++ autofs-5.0.7/CHANGELOG
019928
@@ -186,6 +186,7 @@
019928
 - add remote-fs.target systemd dependency.
019928
 - gaurd against incorrect umount return.
019928
 - fix typo in autofs.conf.
019928
+- always set direct mounts catatonic at exit.
019928
 
019928
 25/07/2012 autofs-5.0.7
019928
 =======================
019928
--- autofs-5.0.7.orig/daemon/direct.c
019928
+++ autofs-5.0.7/daemon/direct.c
019928
@@ -82,6 +82,65 @@ static void mnts_cleanup(void *arg)
019928
 	return;
019928
 }
019928
 
019928
+/* When exiting direct mount triggers must be set catatonic, regardless
019928
+ * of whether they are busy on not, to avoid a hang on access once the
019928
+ * daemon has gone away.
019928
+ */
019928
+static int set_direct_mount_catatonic(struct autofs_point *ap, struct mapent *me, int ioctlfd)
019928
+{
019928
+	struct ioctl_ops *ops = get_ioctl_ops();
019928
+	unsigned int opened = 0;
019928
+	char buf[MAX_ERR_BUF];
019928
+	int fd = -1;
019928
+	int error;
019928
+
019928
+	/* In case the miscellaneous device isn't being used try
019928
+	 * and use an existing ioctl control fd. In this case if
019928
+	 * we don't already have an ioctl fd the mount can't be
019928
+	 * set catatonic if it's covered.
019928
+	 */
019928
+	if (ioctlfd >= 0)
019928
+		fd = ioctlfd;
019928
+	else if (me->ioctlfd >= 0)
019928
+		fd = me->ioctlfd;
019928
+	else {
019928
+		error = ops->open(ap->logopt, &fd, me->dev, me->key);
019928
+		if (error == -1) {
019928
+			int err = errno;
019928
+			char *estr;
019928
+
019928
+			estr = strerror_r(errno, buf, MAX_ERR_BUF);
019928
+			error(ap->logopt,
019928
+			      "failed to open ioctlfd for %s, error: %s",
019928
+			      me->key, estr);
019928
+			return err;
019928
+		}
019928
+		opened = 1;
019928
+	}
019928
+
019928
+	if (fd >= 0) {
019928
+		error = ops->catatonic(ap->logopt, fd);
019928
+		if (error == -1) {
019928
+			int err = errno;
019928
+			char *estr;
019928
+
019928
+			estr = strerror_r(errno, buf, MAX_ERR_BUF);
019928
+			error(ap->logopt,
019928
+			      "failed to set %s catatonic, error: %s",
019928
+			      me->key, estr);
019928
+			if (opened)
019928
+				ops->close(ap->logopt, fd);
019928
+			return err;
019928
+		}
019928
+		if (opened)
019928
+			ops->close(ap->logopt, fd);
019928
+	}
019928
+
019928
+	debug(ap->logopt, "set %s catatonic", me->key);
019928
+
019928
+	return 0;
019928
+}
019928
+
019928
 int do_umount_autofs_direct(struct autofs_point *ap, struct mnt_list *mnts, struct mapent *me)
019928
 {
019928
 	struct ioctl_ops *ops = get_ioctl_ops();
019928
@@ -97,7 +156,8 @@ int do_umount_autofs_direct(struct autof
019928
 	}
019928
 
019928
 	if (me->ioctlfd != -1) {
019928
-		if (tree_is_mounted(mnts, me->key, MNTS_REAL)) {
019928
+		if (ap->state == ST_READMAP &&
019928
+		    tree_is_mounted(mnts, me->key, MNTS_REAL)) {
019928
 			error(ap->logopt,
019928
 			      "attempt to umount busy direct mount %s",
019928
 			      me->key);
019928
@@ -116,7 +176,12 @@ int do_umount_autofs_direct(struct autof
019928
 		if (rv) {
019928
 			char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
019928
 			error(ap->logopt, "ioctl failed: %s", estr);
019928
-			if (opened && ioctlfd != -1)
019928
+			/* The ioctl failed so this probably won't
019928
+			 * work either but since we opened it here
019928
+			 * try anyway. We should set these catatonic
019928
+			 * too but ....
019928
+			 */
019928
+			if (opened)
019928
 				ops->close(ap->logopt, ioctlfd);
019928
 			return 1;
019928
 		} else if (!status) {
019928
@@ -124,18 +189,20 @@ int do_umount_autofs_direct(struct autof
019928
 				error(ap->logopt,
019928
 				      "ask umount returned busy for %s",
019928
 				      me->key);
019928
-				if (opened && ioctlfd != -1)
019928
+				if (ap->state != ST_READMAP)
019928
+					set_direct_mount_catatonic(ap, me, ioctlfd);
019928
+				if (opened)
019928
 					ops->close(ap->logopt, ioctlfd);
019928
 				return 1;
019928
 			} else {
019928
 				me->ioctlfd = -1;
019928
-				ops->catatonic(ap->logopt, ioctlfd);
019928
+				set_direct_mount_catatonic(ap, me, ioctlfd);
019928
 				ops->close(ap->logopt, ioctlfd);
019928
 				goto force_umount;
019928
 			}
019928
 		}
019928
 		me->ioctlfd = -1;
019928
-		ops->catatonic(ap->logopt, ioctlfd);
019928
+		set_direct_mount_catatonic(ap, me, ioctlfd);
019928
 		ops->close(ap->logopt, ioctlfd);
019928
 	} else {
019928
 		error(ap->logopt,
019928
@@ -212,15 +279,31 @@ int umount_autofs_direct(struct autofs_p
019928
 		cache_readlock(mc);
019928
 		me = cache_enumerate(mc, NULL);
019928
 		while (me) {
019928
+			int error;
019928
+
019928
 			ne = cache_lookup_distinct(nc, me->key);
019928
 			if (ne && map->master_line > ne->age) {
019928
 				me = cache_enumerate(mc, me);
019928
 				continue;
019928
 			}
019928
 
019928
-			/* TODO: check return, locking me */
019928
-			do_umount_autofs_direct(ap, mnts, me);
019928
-
019928
+			/* The daemon is exiting so ...
019928
+			 * If we get a fail here we must make our
019928
+			 * best effort to set the direct mount trigger
019928
+			 * catatonic regardless of the reason for the
019928
+			 * failed umount.
019928
+			 */
019928
+			error = do_umount_autofs_direct(ap, mnts, me);
019928
+			if (!error)
019928
+				goto done;
019928
+
019928
+			error = set_direct_mount_catatonic(ap, me, me->ioctlfd);
019928
+			if (!error)
019928
+				goto done;
019928
+
019928
+			/* We really need to set this, last ditch attempt */
019928
+			set_direct_mount_catatonic(ap, me, -1);
019928
+done:
019928
 			me = cache_enumerate(mc, me);
019928
 		}
019928
 		pthread_cleanup_pop(1);