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

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