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

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