Blob Blame History Raw
autofs-5.1.2 - set autofs mounts catatonic at exit

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.

Signed-off-by: Ian Kent <raven@themaw.net>
---
 CHANGELOG          |    1 
 daemon/automount.c |    1 
 daemon/direct.c    |   17 ++++---------
 daemon/indirect.c  |    3 --
 include/mounts.h   |    3 +-
 lib/mounts.c       |   69 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 6 files changed, 78 insertions(+), 16 deletions(-)

--- autofs-5.0.7.orig/CHANGELOG
+++ autofs-5.0.7/CHANGELOG
@@ -214,6 +214,7 @@
 - don't return until after master map retry read.
 - make lookup_nss_read_master() return nss status.
 - make set_direct_mount_catatonic() more general.
+- set autofs mounts catatonic at exit.
 
 25/07/2012 autofs-5.0.7
 =======================
--- autofs-5.0.7.orig/daemon/automount.c
+++ autofs-5.0.7/daemon/automount.c
@@ -1732,6 +1732,7 @@ int handle_mounts_exit(struct autofs_poi
 	 */
 	ret = umount_autofs(ap, NULL, 1);
 	if (!ret) {
+		set_indirect_mount_tree_catatonic(ap);
 		handle_mounts_cleanup(ap);
 		return 1;
 	}
--- autofs-5.0.7.orig/daemon/direct.c
+++ autofs-5.0.7/daemon/direct.c
@@ -130,20 +130,16 @@ int do_umount_autofs_direct(struct autof
 				error(ap->logopt,
 				      "ask umount returned busy for %s",
 				      me->key);
-				if (ap->state != ST_READMAP)
-					set_mount_catatonic(ap, me, ioctlfd);
 				if (opened)
 					ops->close(ap->logopt, ioctlfd);
 				return 1;
 			} else {
 				me->ioctlfd = -1;
-				set_mount_catatonic(ap, me, ioctlfd);
 				ops->close(ap->logopt, ioctlfd);
 				goto force_umount;
 			}
 		}
 		me->ioctlfd = -1;
-		set_mount_catatonic(ap, me, ioctlfd);
 		ops->close(ap->logopt, ioctlfd);
 	} else {
 		error(ap->logopt,
@@ -173,8 +169,11 @@ int do_umount_autofs_direct(struct autof
 			warn(ap->logopt, "mount point %s is in use", me->key);
 			if (ap->state == ST_SHUTDOWN_FORCE)
 				goto force_umount;
-			else
+			else {
+				if (ap->state != ST_READMAP)
+					set_direct_mount_tree_catatonic(ap, me);
 				return 0;
+			}
 			break;
 		case ENOTDIR:
 			error(ap->logopt, "mount point is not a directory");
@@ -238,12 +237,8 @@ int umount_autofs_direct(struct autofs_p
 			if (!error)
 				goto done;
 
-			error = set_mount_catatonic(ap, me, me->ioctlfd);
-			if (!error)
-				goto done;
-
-			/* We really need to set this, last ditch attempt */
-			set_mount_catatonic(ap, me, -1);
+			if (ap->state != ST_READMAP)
+				set_direct_mount_tree_catatonic(ap, me);
 done:
 			me = cache_enumerate(mc, me);
 		}
--- autofs-5.0.7.orig/daemon/indirect.c
+++ autofs-5.0.7/daemon/indirect.c
@@ -286,9 +286,6 @@ int umount_autofs_indirect(struct autofs
 #endif
 	}
 
-	if (ap->shutdown)
-		ops->catatonic(ap->logopt, ap->ioctlfd);
-
 	ops->close(ap->logopt, ap->ioctlfd);
 	ap->ioctlfd = -1;
 	sched_yield();
--- autofs-5.0.7.orig/include/mounts.h
+++ autofs-5.0.7/include/mounts.h
@@ -114,7 +114,8 @@ 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);
+void set_indirect_mount_tree_catatonic(struct autofs_point *);
+void set_direct_mount_tree_catatonic(struct autofs_point *, struct mapent *);
 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
@@ -1899,7 +1899,7 @@ int try_remount(struct autofs_point *ap,
  * 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)
+static int set_mount_catatonic(struct autofs_point *ap, struct mapent *me, int ioctlfd)
 {
 	struct ioctl_ops *ops = get_ioctl_ops();
 	unsigned int opened = 0;
@@ -1926,6 +1926,9 @@ int set_mount_catatonic(struct autofs_po
 			int err = errno;
 			char *estr;
 
+			if (errno == ENOENT)
+				return 0;
+
 			estr = strerror_r(errno, buf, MAX_ERR_BUF);
 			error(ap->logopt,
 			      "failed to open ioctlfd for %s, error: %s",
@@ -1958,6 +1961,70 @@ int set_mount_catatonic(struct autofs_po
 	return 0;
 }
 
+static void set_multi_mount_tree_catatonic(struct autofs_point *ap, struct mapent *me)
+{
+	if (!list_empty(&me->multi_list)) {
+		struct list_head *head = &me->multi_list;
+		struct list_head *p;
+
+		list_for_each(p, head) {
+			struct mapent *this;
+
+			this = list_entry(p, struct mapent, multi_list);
+			set_mount_catatonic(ap, this, this->ioctlfd);
+		}
+	}
+}
+
+void set_indirect_mount_tree_catatonic(struct autofs_point *ap)
+{
+	struct master_mapent *entry = ap->entry;
+	struct map_source *map;
+	struct mapent_cache *mc;
+	struct mapent *me;
+
+	if (!is_mounted(_PROC_MOUNTS, ap->path, MNTS_AUTOFS))
+		return;
+
+	map = entry->maps;
+	while (map) {
+		mc = map->mc;
+		cache_readlock(mc);
+		me = cache_enumerate(mc, NULL);
+		while (me) {
+			/* Skip negative map entries and wildcard entries */
+			if (!me->mapent)
+				goto next;
+
+			if (!strcmp(me->key, "*"))
+				goto next;
+
+			/* Only need to set offset mounts catatonic */
+			if (me->multi && me->multi == me)
+				set_multi_mount_tree_catatonic(ap, me);
+next:
+			me = cache_enumerate(mc, me);
+		}
+		cache_unlock(mc);
+		map = map->next;
+	}
+
+	/* By the time this function is called ap->ioctlfd will have
+	 * been closed so don't try and use it.
+	 */
+	set_mount_catatonic(ap, NULL, -1);
+
+	return;
+}
+
+void set_direct_mount_tree_catatonic(struct autofs_point *ap, struct mapent *me)
+{
+	/* Set offset mounts catatonic for this mapent */
+	if (me->multi && me->multi == me)
+		set_multi_mount_tree_catatonic(ap, me);
+	set_mount_catatonic(ap, me, me->ioctlfd);
+}
+
 int umount_ent(struct autofs_point *ap, const char *path)
 {
 	int rv;