Blame SOURCES/autofs-5.1.7-fix-direct-mount-deadlock.patch

29d2b9
autofs-5.1.7 - fix direct mount deadlock
29d2b9
29d2b9
From: Ian Kent <raven@themaw.net>
29d2b9
29d2b9
When umounting direct mounts at exit or when umounting mounts no
29d2b9
longer in the map on re-load a deadlock can occur.
29d2b9
29d2b9
Signed-off-by: Ian Kent <raven@themaw.net>
29d2b9
---
29d2b9
 CHANGELOG       |    1 +
29d2b9
 daemon/direct.c |   22 +++++++++++++++++++++-
29d2b9
 daemon/state.c  |   14 +++++++++-----
29d2b9
 3 files changed, 31 insertions(+), 6 deletions(-)
29d2b9
29d2b9
--- autofs-5.1.7.orig/CHANGELOG
29d2b9
+++ autofs-5.1.7/CHANGELOG
29d2b9
@@ -73,6 +73,7 @@
29d2b9
 - use mapent tree root for tree_mapent_add_node().
29d2b9
 - eliminate redundant cache lookup in tree_mapent_add_node().
29d2b9
 - fix hosts map offset order.
29d2b9
+- fix direct mount deadlock.
29d2b9
 
29d2b9
 25/01/2021 autofs-5.1.7
29d2b9
 - make bind mounts propagation slave by default.
29d2b9
--- autofs-5.1.7.orig/daemon/direct.c
29d2b9
+++ autofs-5.1.7/daemon/direct.c
29d2b9
@@ -84,11 +84,27 @@ static void mnts_cleanup(void *arg)
29d2b9
 int do_umount_autofs_direct(struct autofs_point *ap, struct mapent *me)
29d2b9
 {
29d2b9
 	struct ioctl_ops *ops = get_ioctl_ops();
29d2b9
+	struct mapent_cache *mc = me->mc;
29d2b9
 	char buf[MAX_ERR_BUF];
29d2b9
 	int ioctlfd = -1, rv, left, retries;
29d2b9
+	char key[PATH_MAX + 1];
29d2b9
+	struct mapent *tmp;
29d2b9
 	int opened = 0;
29d2b9
 
29d2b9
-	left = umount_multi(ap, me->key, 0);
29d2b9
+	if (me->len > PATH_MAX) {
29d2b9
+		error(ap->logopt, "path too long");
29d2b9
+		return 1;
29d2b9
+	}
29d2b9
+	strcpy(key, me->key);
29d2b9
+
29d2b9
+	cache_unlock(mc);
29d2b9
+	left = umount_multi(ap, key, 0);
29d2b9
+	cache_readlock(mc);
29d2b9
+	tmp = cache_lookup_distinct(mc, key);
29d2b9
+	if (tmp != me) {
29d2b9
+		error(ap->logopt, "key %s no longer in mapent cache", key);
29d2b9
+		return -1;
29d2b9
+	}
29d2b9
 	if (left) {
29d2b9
 		warn(ap->logopt, "could not unmount %d dirs under %s",
29d2b9
 		     left, me->key);
29d2b9
@@ -213,6 +229,7 @@ int umount_autofs_direct(struct autofs_p
29d2b9
 		mc = map->mc;
29d2b9
 		pthread_cleanup_push(cache_lock_cleanup, mc);
29d2b9
 		cache_readlock(mc);
29d2b9
+restart:
29d2b9
 		me = cache_enumerate(mc, NULL);
29d2b9
 		while (me) {
29d2b9
 			int error;
29d2b9
@@ -230,6 +247,9 @@ int umount_autofs_direct(struct autofs_p
29d2b9
 			 * failed umount.
29d2b9
 			 */
29d2b9
 			error = do_umount_autofs_direct(ap, me);
29d2b9
+			/* cache became invalid, restart */
29d2b9
+			if (error == -1)
29d2b9
+				goto restart;
29d2b9
 			if (!error)
29d2b9
 				goto done;
29d2b9
 
29d2b9
--- autofs-5.1.7.orig/daemon/state.c
29d2b9
+++ autofs-5.1.7/daemon/state.c
29d2b9
@@ -324,11 +324,12 @@ static void do_readmap_cleanup(void *arg
29d2b9
 	return;
29d2b9
 }
29d2b9
 
29d2b9
-static void do_readmap_mount(struct autofs_point *ap,
29d2b9
+static int do_readmap_mount(struct autofs_point *ap,
29d2b9
 			     struct map_source *map, struct mapent *me, time_t now)
29d2b9
 {
29d2b9
 	struct mapent_cache *nc;
29d2b9
 	struct mapent *ne, *nested, *valid;
29d2b9
+	int ret = 0;
29d2b9
 
29d2b9
 	nc = ap->entry->master->nc;
29d2b9
 
29d2b9
@@ -387,7 +388,7 @@ static void do_readmap_mount(struct auto
29d2b9
 				cache_unlock(vmc);
29d2b9
 				error(ap->logopt,
29d2b9
 				     "failed to find expected existing valid map entry");
29d2b9
-				return;
29d2b9
+				return ret;
29d2b9
 			}
29d2b9
 			/* Take over the mount if there is one */
29d2b9
 			valid->ioctlfd = me->ioctlfd;
29d2b9
@@ -406,14 +407,14 @@ static void do_readmap_mount(struct auto
29d2b9
 					ap->exp_runfreq = runfreq;
29d2b9
 			}
29d2b9
 		} else if (!is_mounted(me->key, MNTS_REAL))
29d2b9
-			do_umount_autofs_direct(ap, me);
29d2b9
+			ret = do_umount_autofs_direct(ap, me);
29d2b9
 		else
29d2b9
 			debug(ap->logopt,
29d2b9
 			      "%s is mounted", me->key);
29d2b9
 	} else
29d2b9
 		do_mount_autofs_direct(ap, me, get_exp_timeout(ap, map));
29d2b9
 
29d2b9
-	return;
29d2b9
+	return ret;
29d2b9
 }
29d2b9
 
29d2b9
 static void *do_readmap(void *arg)
29d2b9
@@ -480,9 +481,12 @@ static void *do_readmap(void *arg)
29d2b9
 			mc = map->mc;
29d2b9
 			pthread_cleanup_push(cache_lock_cleanup, mc);
29d2b9
 			cache_readlock(mc);
29d2b9
+restart:
29d2b9
 			me = cache_enumerate(mc, NULL);
29d2b9
 			while (me) {
29d2b9
-				do_readmap_mount(ap, map, me, now);
29d2b9
+				int ret = do_readmap_mount(ap, map, me, now);
29d2b9
+				if (ret == -1)
29d2b9
+					goto restart;
29d2b9
 				me = cache_enumerate(mc, me);
29d2b9
 			}
29d2b9
 			lookup_prune_one_cache(ap, map->mc, now);