Blob Blame History Raw
autofs-5.1.2 - make set_direct_mount_catatonic() more general

From: Ian Kent <raven@themaw.net>

Setting direct mounts catatonic at exit doesn't go far enough.

To avoid possible hang on access of automount managed paths when
the daemon has exited all mounted autofs file systems must be set
catatonic when the daemon exits.

Start by making set_direct_mount_catatonic() able to handle the
different types of autofs mounts and move it to the mounts function
library.
---
 CHANGELOG        |    1 
 daemon/direct.c  |   69 +++----------------------------------------------------
 include/mounts.h |    1 
 lib/mounts.c     |   64 +++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 71 insertions(+), 64 deletions(-)

--- autofs-5.0.7.orig/CHANGELOG
+++ autofs-5.0.7/CHANGELOG
@@ -213,6 +213,7 @@
 - set sane default master read wait timeout.
 - don't return until after master map retry read.
 - make lookup_nss_read_master() return nss status.
+- make set_direct_mount_catatonic() more general.
 
 25/07/2012 autofs-5.0.7
 =======================
--- autofs-5.0.7.orig/daemon/direct.c
+++ autofs-5.0.7/daemon/direct.c
@@ -82,65 +82,6 @@ static void mnts_cleanup(void *arg)
 	return;
 }
 
-/* When exiting direct mount triggers must be set catatonic, regardless
- * of whether they are busy on not, to avoid a hang on access once the
- * daemon has gone away.
- */
-static int set_direct_mount_catatonic(struct autofs_point *ap, struct mapent *me, int ioctlfd)
-{
-	struct ioctl_ops *ops = get_ioctl_ops();
-	unsigned int opened = 0;
-	char buf[MAX_ERR_BUF];
-	int fd = -1;
-	int error;
-
-	/* In case the miscellaneous device isn't being used try
-	 * and use an existing ioctl control fd. In this case if
-	 * we don't already have an ioctl fd the mount can't be
-	 * set catatonic if it's covered.
-	 */
-	if (ioctlfd >= 0)
-		fd = ioctlfd;
-	else if (me->ioctlfd >= 0)
-		fd = me->ioctlfd;
-	else {
-		error = ops->open(ap->logopt, &fd, me->dev, me->key);
-		if (error == -1) {
-			int err = errno;
-			char *estr;
-
-			estr = strerror_r(errno, buf, MAX_ERR_BUF);
-			error(ap->logopt,
-			      "failed to open ioctlfd for %s, error: %s",
-			      me->key, estr);
-			return err;
-		}
-		opened = 1;
-	}
-
-	if (fd >= 0) {
-		error = ops->catatonic(ap->logopt, fd);
-		if (error == -1) {
-			int err = errno;
-			char *estr;
-
-			estr = strerror_r(errno, buf, MAX_ERR_BUF);
-			error(ap->logopt,
-			      "failed to set %s catatonic, error: %s",
-			      me->key, estr);
-			if (opened)
-				ops->close(ap->logopt, fd);
-			return err;
-		}
-		if (opened)
-			ops->close(ap->logopt, fd);
-	}
-
-	debug(ap->logopt, "set %s catatonic", me->key);
-
-	return 0;
-}
-
 int do_umount_autofs_direct(struct autofs_point *ap, struct mnt_list *mnts, struct mapent *me)
 {
 	struct ioctl_ops *ops = get_ioctl_ops();
@@ -190,19 +131,19 @@ int do_umount_autofs_direct(struct autof
 				      "ask umount returned busy for %s",
 				      me->key);
 				if (ap->state != ST_READMAP)
-					set_direct_mount_catatonic(ap, me, ioctlfd);
+					set_mount_catatonic(ap, me, ioctlfd);
 				if (opened)
 					ops->close(ap->logopt, ioctlfd);
 				return 1;
 			} else {
 				me->ioctlfd = -1;
-				set_direct_mount_catatonic(ap, me, ioctlfd);
+				set_mount_catatonic(ap, me, ioctlfd);
 				ops->close(ap->logopt, ioctlfd);
 				goto force_umount;
 			}
 		}
 		me->ioctlfd = -1;
-		set_direct_mount_catatonic(ap, me, ioctlfd);
+		set_mount_catatonic(ap, me, ioctlfd);
 		ops->close(ap->logopt, ioctlfd);
 	} else {
 		error(ap->logopt,
@@ -297,12 +238,12 @@ int umount_autofs_direct(struct autofs_p
 			if (!error)
 				goto done;
 
-			error = set_direct_mount_catatonic(ap, me, me->ioctlfd);
+			error = set_mount_catatonic(ap, me, me->ioctlfd);
 			if (!error)
 				goto done;
 
 			/* We really need to set this, last ditch attempt */
-			set_direct_mount_catatonic(ap, me, -1);
+			set_mount_catatonic(ap, me, -1);
 done:
 			me = cache_enumerate(mc, me);
 		}
--- autofs-5.0.7.orig/include/mounts.h
+++ autofs-5.0.7/include/mounts.h
@@ -114,6 +114,7 @@ void set_tsd_user_vars(unsigned int, uid
 const char *mount_type_str(unsigned int);
 void notify_mount_result(struct autofs_point *, const char *, time_t, const char *);
 int try_remount(struct autofs_point *, struct mapent *, unsigned int);
+int set_mount_catatonic(struct autofs_point *, struct mapent *, int);
 int umount_ent(struct autofs_point *, const char *);
 int mount_multi_triggers(struct autofs_point *, struct mapent *, const char *, unsigned int, const char *);
 int umount_multi_triggers(struct autofs_point *, struct mapent *, char *, const char *);
--- autofs-5.0.7.orig/lib/mounts.c
+++ autofs-5.0.7/lib/mounts.c
@@ -1894,6 +1894,70 @@ int try_remount(struct autofs_point *ap,
 	return 0;
 }
 
+/*
+ * When exiting mounts need be set catatonic, regardless of whether they
+ * are busy on not, to avoid a hang on access once the daemon has gone
+ * away.
+ */
+int set_mount_catatonic(struct autofs_point *ap, struct mapent *me, int ioctlfd)
+{
+	struct ioctl_ops *ops = get_ioctl_ops();
+	unsigned int opened = 0;
+	char buf[MAX_ERR_BUF];
+	char *path;
+	int fd = -1;
+	int error;
+	dev_t dev;
+
+	path = ap->path;
+	dev = ap->dev;
+	if (me && (ap->type == LKP_DIRECT || *me->key == '/')) {
+		path = me->key;
+		dev = me->dev;
+	}
+
+	if (ioctlfd >= 0)
+		fd = ioctlfd;
+	else if (me && me->ioctlfd >= 0)
+		fd = me->ioctlfd;
+	else {
+		error = ops->open(ap->logopt, &fd, dev, path);
+		if (error == -1) {
+			int err = errno;
+			char *estr;
+
+			estr = strerror_r(errno, buf, MAX_ERR_BUF);
+			error(ap->logopt,
+			      "failed to open ioctlfd for %s, error: %s",
+			      path, estr);
+			return err;
+		}
+		opened = 1;
+	}
+
+	if (fd >= 0) {
+		error = ops->catatonic(ap->logopt, fd);
+		if (error == -1) {
+			int err = errno;
+			char *estr;
+
+			estr = strerror_r(errno, buf, MAX_ERR_BUF);
+			error(ap->logopt,
+			      "failed to set %s catatonic, error: %s",
+			      path, estr);
+			if (opened)
+				ops->close(ap->logopt, fd);
+			return err;
+		}
+		if (opened)
+			ops->close(ap->logopt, fd);
+	}
+
+	debug(ap->logopt, "set %s catatonic", path);
+
+	return 0;
+}
+
 int umount_ent(struct autofs_point *ap, const char *path)
 {
 	int rv;