Blame SOURCES/autofs-5.1.7-eliminate-clean_stale_multi_triggers.patch

29d2b9
autofs-5.1.7 - eliminate clean_stale_multi_triggers()
29d2b9
29d2b9
From: Ian Kent <raven@themaw.net>
29d2b9
29d2b9
Eliminate clean_stale_multi_triggers() by checking for stale offsets at
29d2b9
the time mount_subtree() is called.
29d2b9
29d2b9
This should result in the same behaviour but eliminate an additional
29d2b9
seperate traversal of the offset list.
29d2b9
29d2b9
Signed-off-by: Ian Kent <raven@themaw.net>
29d2b9
---
29d2b9
 CHANGELOG           |    1 
29d2b9
 lib/mounts.c        |  209 ++++++++++-----------------------------------------
29d2b9
 modules/parse_sun.c |   10 --
29d2b9
 3 files changed, 43 insertions(+), 177 deletions(-)
29d2b9
29d2b9
diff --git a/CHANGELOG b/CHANGELOG
29d2b9
index 5a3bedc1..b1ce7b69 100644
29d2b9
--- a/CHANGELOG
29d2b9
+++ b/CHANGELOG
29d2b9
@@ -12,6 +12,7 @@
29d2b9
 - remove redundant variables from mount_autofs_offset().
29d2b9
 - remove unused parameter form do_mount_autofs_offset().
29d2b9
 - refactor umount_multi_triggers().
29d2b9
+- eliminate clean_stale_multi_triggers().
29d2b9
 
29d2b9
 25/01/2021 autofs-5.1.7
29d2b9
 - make bind mounts propagation slave by default.
29d2b9
diff --git a/lib/mounts.c b/lib/mounts.c
29d2b9
index 5268ba5b..a9abbebf 100644
29d2b9
--- a/lib/mounts.c
29d2b9
+++ b/lib/mounts.c
29d2b9
@@ -2601,10 +2601,44 @@ static int do_umount_offset(struct autofs_point *ap, struct mapent *oe, const ch
29d2b9
 	oe_base = oe->key + strlen(root);
29d2b9
 	left += do_umount_multi_triggers(ap, oe, root, oe_base);
29d2b9
 
29d2b9
+	/*
29d2b9
+	 * If an offset that has an active mount has been removed
29d2b9
+	 * from the multi-mount we don't want to attempt to trigger
29d2b9
+	 * mounts for it. Obviously this is because it has been
29d2b9
+	 * removed, but less obvious is the potential strange
29d2b9
+	 * behaviour that can result if we do try and mount it
29d2b9
+	 * again after it's been expired. For example, if an NFS
29d2b9
+	 * file system is no longer exported and is later umounted
29d2b9
+	 * it can be mounted again without any error message but
29d2b9
+	 * shows as an empty directory. That's going to confuse
29d2b9
+	 * people for sure.
29d2b9
+	 *
29d2b9
+	 * If the mount cannot be umounted (the process is now
29d2b9
+	 * using a stale mount) the offset needs to be invalidated
29d2b9
+	 * so no further mounts will be attempted but the offset
29d2b9
+	 * cache entry must remain so expires can continue to
29d2b9
+	 * attempt to umount it. If the mount can be umounted and
29d2b9
+	 * the offset is removed, at least for NFS we will get
29d2b9
+	 * ESTALE errors when attempting list the directory.
29d2b9
+	 */
29d2b9
 	if (oe->ioctlfd != -1 ||
29d2b9
 	    is_mounted(oe->key, MNTS_REAL)) {
29d2b9
-		left++;
29d2b9
-		return left;
29d2b9
+		if (umount_ent(ap, oe->key) &&
29d2b9
+		    is_mounted(oe->key, MNTS_REAL)) {
29d2b9
+			debug(ap->logopt,
29d2b9
+			      "offset %s has active mount, invalidate",
29d2b9
+			      oe->key);
29d2b9
+			/*
29d2b9
+			 * Ok, so we shouldn't modify the mapent but
29d2b9
+			 * mount requests are blocked at a point above
29d2b9
+			 * this and expire only uses the mapent key.
29d2b9
+			 */
29d2b9
+			if (oe->mapent) {
29d2b9
+				free(oe->mapent);
29d2b9
+				oe->mapent = NULL;
29d2b9
+			}
29d2b9
+			return ++left;
29d2b9
+		}
29d2b9
 	}
29d2b9
 
29d2b9
 	debug(ap->logopt, "umount offset %s", oe->key);
29d2b9
@@ -2666,6 +2700,11 @@ int mount_multi_triggers(struct autofs_point *ap, struct mapent *me,
29d2b9
 		oe = cache_lookup_distinct(me->mc, key);
29d2b9
 		if (!oe || !oe->mapent)
29d2b9
 			goto cont;
29d2b9
+		if (oe->age != me->multi->age) {
29d2b9
+			/* Best effort */
29d2b9
+			do_umount_offset(ap, oe, root);
29d2b9
+			goto cont;
29d2b9
+		}
29d2b9
 
29d2b9
 		mounted += do_mount_autofs_offset(ap, oe, root);
29d2b9
 
29d2b9
@@ -2725,169 +2764,3 @@ int umount_multi_triggers(struct autofs_point *ap, struct mapent *me, char *root
29d2b9
 
29d2b9
 	return left;
29d2b9
 }
29d2b9
-
29d2b9
-int clean_stale_multi_triggers(struct autofs_point *ap,
29d2b9
-			       struct mapent *me, char *top, const char *base)
29d2b9
-{
29d2b9
-	char *root;
29d2b9
-	char mm_top[PATH_MAX + 1];
29d2b9
-	char path[PATH_MAX + 1];
29d2b9
-	char *offset;
29d2b9
-	struct mapent *oe;
29d2b9
-	struct list_head *mm_root, *pos;
29d2b9
-	const char o_root[] = "/";
29d2b9
-	const char *mm_base;
29d2b9
-	int left, start;
29d2b9
-	unsigned int root_len;
29d2b9
-	unsigned int mm_base_len;
29d2b9
-	time_t age;
29d2b9
-
29d2b9
-	if (top)
29d2b9
-		root = top;
29d2b9
-	else {
29d2b9
-		if (!strchr(me->multi->key, '/'))
29d2b9
-			/* Indirect multi-mount root */
29d2b9
-			/* sprintf okay - if it's mounted, it's
29d2b9
-			 * PATH_MAX or less bytes */
29d2b9
-			sprintf(mm_top, "%s/%s", ap->path, me->multi->key);
29d2b9
-		else
29d2b9
-			strcpy(mm_top, me->multi->key);
29d2b9
-		root = mm_top;
29d2b9
-	}
29d2b9
-
29d2b9
-	left = 0;
29d2b9
-	start = strlen(root);
29d2b9
-
29d2b9
-	mm_root = &me->multi->multi_list;
29d2b9
-
29d2b9
-	if (!base)
29d2b9
-		mm_base = o_root;
29d2b9
-	else
29d2b9
-		mm_base = base;
29d2b9
-
29d2b9
-	pos = NULL;
29d2b9
-	offset = path;
29d2b9
-	root_len = start;
29d2b9
-	mm_base_len = strlen(mm_base);
29d2b9
-	age = me->multi->age;
29d2b9
-
29d2b9
-	while ((offset = cache_get_offset(mm_base, offset, start, mm_root, &pos))) {
29d2b9
-		char key[PATH_MAX + 1];
29d2b9
-		int key_len = root_len + strlen(offset);
29d2b9
-		char *oe_base;
29d2b9
-		int ret;
29d2b9
-
29d2b9
-		if (mm_base_len > 1)
29d2b9
-			key_len += mm_base_len;
29d2b9
-
29d2b9
-		if (key_len > PATH_MAX) {
29d2b9
-			warn(ap->logopt, "path loo long");
29d2b9
-			continue;
29d2b9
-		}
29d2b9
-
29d2b9
-		strcpy(key, root);
29d2b9
-		if (mm_base_len > 1)
29d2b9
-			strcat(key, mm_base);
29d2b9
-		strcat(key, offset);
29d2b9
-
29d2b9
-		oe = cache_lookup_distinct(me->mc, key);
29d2b9
-		/* root offset is a special case */
29d2b9
-		if (!oe || (strlen(oe->key) - start) == 1)
29d2b9
-			continue;
29d2b9
-
29d2b9
-		/* Check for and umount stale subtree offsets */
29d2b9
-		oe_base = oe->key + strlen(root);
29d2b9
-		ret = clean_stale_multi_triggers(ap, oe, root, oe_base);
29d2b9
-		left += ret;
29d2b9
-		if (ret)
29d2b9
-			continue;
29d2b9
-
29d2b9
-		if (oe->age == age)
29d2b9
-			continue;
29d2b9
-
29d2b9
-		/*
29d2b9
-		 * If an offset that has an active mount has been removed
29d2b9
-		 * from the multi-mount we don't want to attempt to trigger
29d2b9
-		 * mounts for it. Obviously this is because it has been
29d2b9
-		 * removed, but less obvious is the potential strange
29d2b9
-		 * behaviour that can result if we do try and mount it
29d2b9
-		 * again after it's been expired. For example, if an NFS
29d2b9
-		 * file system is no longer exported and is later umounted
29d2b9
-		 * it can be mounted again without any error message but
29d2b9
-		 * shows as an empty directory. That's going to confuse
29d2b9
-		 * people for sure.
29d2b9
-		 *
29d2b9
-		 * If the mount cannot be umounted (the process is now
29d2b9
-		 * using a stale mount) the offset needs to be invalidated
29d2b9
-		 * so no further mounts will be attempted but the offset
29d2b9
-		 * cache entry must remain so expires can continue to
29d2b9
-		 * attempt to umount it. If the mount can be umounted and
29d2b9
-		 * the offset is removed, at least for NFS we will get
29d2b9
-		 * ESTALE errors when attempting list the directory.
29d2b9
-		 */
29d2b9
-		if (oe->ioctlfd != -1 ||
29d2b9
-		    is_mounted(oe->key, MNTS_REAL)) {
29d2b9
-			if (umount_ent(ap, oe->key) &&
29d2b9
-			    is_mounted(oe->key, MNTS_REAL)) {
29d2b9
-				debug(ap->logopt,
29d2b9
-				      "offset %s has active mount, invalidate",
29d2b9
-				      oe->key);
29d2b9
-				if (oe->mapent) {
29d2b9
-					free(oe->mapent);
29d2b9
-					oe->mapent = NULL;
29d2b9
-				}
29d2b9
-				left++;
29d2b9
-				continue;
29d2b9
-			}
29d2b9
-		}
29d2b9
-
29d2b9
-		debug(ap->logopt, "umount offset %s", oe->key);
29d2b9
-
29d2b9
-		if (umount_autofs_offset(ap, oe)) {
29d2b9
-			warn(ap->logopt, "failed to umount offset %s", key);
29d2b9
-			left++;
29d2b9
-		} else {
29d2b9
-			struct stat st;
29d2b9
-
29d2b9
-			/* Mount point not ours to delete ? */
29d2b9
-			if (!(oe->flags & MOUNT_FLAG_DIR_CREATED)) {
29d2b9
-				debug(ap->logopt, "delete offset key %s", key);
29d2b9
-				if (cache_delete_offset(oe->mc, key) == CHE_FAIL)
29d2b9
-					error(ap->logopt,
29d2b9
-					     "failed to delete offset key %s", key);
29d2b9
-				continue;
29d2b9
-			}
29d2b9
-
29d2b9
-			/*
29d2b9
-			 * An error due to partial directory removal is
29d2b9
-			 * ok so only try and remount the offset if the
29d2b9
-			 * actual mount point still exists.
29d2b9
-			 */
29d2b9
-			ret = rmdir_path_offset(ap, oe);
29d2b9
-			if (ret == -1 && !stat(oe->key, &st)) {
29d2b9
-				ret = do_mount_autofs_offset(ap, oe, root);
29d2b9
-				if (ret) {
29d2b9
-					left++;
29d2b9
-					/* But we did origianlly create this */
29d2b9
-					oe->flags |= MOUNT_FLAG_DIR_CREATED;
29d2b9
-					continue;
29d2b9
-				}
29d2b9
-				/*
29d2b9
-				 * Fall through if the trigger can't be mounted
29d2b9
-				 * again, since there is no offset there can't
29d2b9
-				 * be any mount requests so remove the map
29d2b9
-				 * entry from the cache. There's now a dead
29d2b9
-				 * offset mount, but what else can we do ....
29d2b9
-				 */
29d2b9
-			}
29d2b9
-
29d2b9
-			debug(ap->logopt, "delete offset key %s", key);
29d2b9
-
29d2b9
-			if (cache_delete_offset(oe->mc, key) == CHE_FAIL)
29d2b9
-				error(ap->logopt,
29d2b9
-				     "failed to delete offset key %s", key);
29d2b9
-		}
29d2b9
-	}
29d2b9
-
29d2b9
-	return left;
29d2b9
-}
29d2b9
diff --git a/modules/parse_sun.c b/modules/parse_sun.c
29d2b9
index f42af7b7..f4d5125c 100644
29d2b9
--- a/modules/parse_sun.c
29d2b9
+++ b/modules/parse_sun.c
29d2b9
@@ -1176,7 +1176,7 @@ static int mount_subtree(struct autofs_point *ap, struct mapent *me,
29d2b9
 
29d2b9
 		/* Mount root offset if it exists */
29d2b9
 		ro = cache_lookup_distinct(me->mc, key);
29d2b9
-		if (ro) {
29d2b9
+		if (ro && ro->age == me->multi->age) {
29d2b9
 			char *myoptions, *ro_loc;
29d2b9
 			int namelen = name ? strlen(name) : 0;
29d2b9
 			int ro_len;
29d2b9
@@ -1610,14 +1610,6 @@ dont_expand:
29d2b9
 			free(myoptions);
29d2b9
 		} while (*p == '/' || (*p == '"' && *(p + 1) == '/'));
29d2b9
 
29d2b9
-		/*
29d2b9
-		 * We've got the ordered list of multi-mount entries so go
29d2b9
-		 * through and remove any stale entries if this is the top
29d2b9
-		 * of the multi-mount and set the parent entry of each.
29d2b9
-		 */
29d2b9
-		if (me == me->multi)
29d2b9
-			clean_stale_multi_triggers(ap, me, NULL, NULL);
29d2b9
-
29d2b9
 		rv = mount_subtree(ap, me, name, NULL, options, ctxt);
29d2b9
 
29d2b9
 		cache_multi_unlock(me);