Blame SOURCES/autofs-5.1.7-eliminate-cache_lookup_offset-usage.patch

beb904
autofs-5.1.7 - eliminate cache_lookup_offset() usage
beb904
beb904
From: Ian Kent <raven@themaw.net>
beb904
beb904
The function cache_lookup_offset() will do a linear search when
beb904
looking for an offset. If the number of offsets is large this
beb904
can be a lot of overhead.
beb904
beb904
But it's possible to use the information already present where
beb904
this is called to to do a hashed lookup instead.
beb904
beb904
Signed-off-by: Ian Kent <raven@themaw.net>
beb904
---
beb904
 CHANGELOG           |    1 
beb904
 lib/mounts.c        |   82 +++++++++++++++++++++++++++++++++-------------------
beb904
 modules/parse_sun.c |   77 ++++++++++++++++++++++++++++++------------------
beb904
 3 files changed, 102 insertions(+), 58 deletions(-)
beb904
beb904
--- autofs-5.1.4.orig/CHANGELOG
beb904
+++ autofs-5.1.4/CHANGELOG
beb904
@@ -4,6 +4,7 @@
beb904
 - dont use realloc in host exports list processing.
beb904
 - use sprintf() when constructing hosts mapent.
beb904
 - fix mnts_remove_amdmount() uses wrong list.
beb904
+- eliminate cache_lookup_offset() usage.
beb904
 
beb904
 xx/xx/2018 autofs-5.1.5
beb904
 - fix flag file permission.
beb904
--- autofs-5.1.4.orig/lib/mounts.c
beb904
+++ autofs-5.1.4/lib/mounts.c
beb904
@@ -2489,24 +2489,27 @@ int mount_multi_triggers(struct autofs_p
beb904
 	char *offset = path;
beb904
 	struct mapent *oe;
beb904
 	struct list_head *pos = NULL;
beb904
-	unsigned int fs_path_len;
beb904
+	unsigned int root_len = strlen(root);
beb904
 	int mounted;
beb904
 
beb904
-	fs_path_len = start + strlen(base);
beb904
-	if (fs_path_len > PATH_MAX)
beb904
-		return -1;
beb904
-
beb904
 	mounted = 0;
beb904
 	offset = cache_get_offset(base, offset, start, &me->multi_list, &pos;;
beb904
 	while (offset) {
beb904
-		int plen = fs_path_len + strlen(offset);
beb904
+		char key[PATH_MAX + 1];
beb904
+		int key_len = root_len + strlen(offset);
beb904
 
beb904
-		if (plen > PATH_MAX) {
beb904
+		if (key_len > PATH_MAX) {
beb904
 			warn(ap->logopt, "path loo long");
beb904
 			goto cont;
beb904
 		}
beb904
 
beb904
-		oe = cache_lookup_offset(base, offset, start, &me->multi_list);
beb904
+		/* The root offset is always mounted seperately so the
beb904
+		 * offset path will always be root + offset.
beb904
+		 */
beb904
+		strcpy(key, root);
beb904
+		strcat(key, offset);
beb904
+
beb904
+		oe = cache_lookup_distinct(me->mc, key);
beb904
 		if (!oe || !oe->mapent)
beb904
 			goto cont;
beb904
 
beb904
@@ -2519,12 +2522,8 @@ int mount_multi_triggers(struct autofs_p
beb904
 		 */
beb904
 		if (ap->state == ST_READMAP && ap->flags & MOUNT_FLAG_REMOUNT) {
beb904
 			if (oe->ioctlfd != -1 ||
beb904
-			    is_mounted(oe->key, MNTS_REAL)) {
beb904
-				char oe_root[PATH_MAX + 1];
beb904
-				strcpy(oe_root, root);
beb904
-				strcat(oe_root, offset); 
beb904
-				mount_multi_triggers(ap, oe, oe_root, strlen(oe_root), base);
beb904
-			}
beb904
+			    is_mounted(oe->key, MNTS_REAL))
beb904
+				mount_multi_triggers(ap, oe, key, strlen(key), base);
beb904
 		}
beb904
 cont:
beb904
 		offset = cache_get_offset(base,
beb904
@@ -2578,6 +2577,8 @@ int umount_multi_triggers(struct autofs_
beb904
 	const char o_root[] = "/";
beb904
 	const char *mm_base;
beb904
 	int left, start;
beb904
+	unsigned int root_len;
beb904
+	unsigned int mm_base_len;
beb904
 
beb904
 	left = 0;
beb904
 	start = strlen(root);
beb904
@@ -2591,11 +2592,28 @@ int umount_multi_triggers(struct autofs_
beb904
 
beb904
 	pos = NULL;
beb904
 	offset = path;
beb904
+	root_len = start;
beb904
+	mm_base_len = strlen(mm_base);
beb904
 
beb904
 	while ((offset = cache_get_offset(mm_base, offset, start, mm_root, &pos))) {
beb904
+		char key[PATH_MAX + 1];
beb904
+		int key_len = root_len + strlen(offset);
beb904
 		char *oe_base;
beb904
 
beb904
-		oe = cache_lookup_offset(mm_base, offset, start, &me->multi_list);
beb904
+		if (mm_base_len > 1)
beb904
+			key_len += mm_base_len;
beb904
+
beb904
+		if (key_len > PATH_MAX) {
beb904
+			warn(ap->logopt, "path loo long");
beb904
+			continue;
beb904
+		}
beb904
+
beb904
+		strcpy(key, root);
beb904
+		if (mm_base_len > 1)
beb904
+			strcat(key, mm_base);
beb904
+		strcat(key, offset);
beb904
+
beb904
+		oe = cache_lookup_distinct(me->mc, key);
beb904
 		/* root offset is a special case */
beb904
 		if (!oe || (strlen(oe->key) - start) == 1)
beb904
 			continue;
beb904
@@ -2680,13 +2698,14 @@ int clean_stale_multi_triggers(struct au
beb904
 	char *root;
beb904
 	char mm_top[PATH_MAX + 1];
beb904
 	char path[PATH_MAX + 1];
beb904
-	char buf[MAX_ERR_BUF];
beb904
 	char *offset;
beb904
 	struct mapent *oe;
beb904
 	struct list_head *mm_root, *pos;
beb904
 	const char o_root[] = "/";
beb904
 	const char *mm_base;
beb904
 	int left, start;
beb904
+	unsigned int root_len;
beb904
+	unsigned int mm_base_len;
beb904
 	time_t age;
beb904
 
beb904
 	if (top)
beb904
@@ -2714,14 +2733,30 @@ int clean_stale_multi_triggers(struct au
beb904
 
beb904
 	pos = NULL;
beb904
 	offset = path;
beb904
+	root_len = start;
beb904
+	mm_base_len = strlen(mm_base);
beb904
 	age = me->multi->age;
beb904
 
beb904
 	while ((offset = cache_get_offset(mm_base, offset, start, mm_root, &pos))) {
beb904
+		char key[PATH_MAX + 1];
beb904
+		int key_len = root_len + strlen(offset);
beb904
 		char *oe_base;
beb904
-		char *key;
beb904
 		int ret;
beb904
 
beb904
-		oe = cache_lookup_offset(mm_base, offset, start, &me->multi_list);
beb904
+		if (mm_base_len > 1)
beb904
+			key_len += mm_base_len;
beb904
+
beb904
+		if (key_len > PATH_MAX) {
beb904
+			warn(ap->logopt, "path loo long");
beb904
+			continue;
beb904
+		}
beb904
+
beb904
+		strcpy(key, root);
beb904
+		if (mm_base_len > 1)
beb904
+			strcat(key, mm_base);
beb904
+		strcat(key, offset);
beb904
+
beb904
+		oe = cache_lookup_distinct(me->mc, key);
beb904
 		/* root offset is a special case */
beb904
 		if (!oe || (strlen(oe->key) - start) == 1)
beb904
 			continue;
beb904
@@ -2772,14 +2807,6 @@ int clean_stale_multi_triggers(struct au
beb904
 			}
beb904
 		}
beb904
 
beb904
-		key = strdup(oe->key);
beb904
-		if (!key) {
beb904
-	                char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
beb904
-		        error(ap->logopt, "malloc: %s", estr);
beb904
-			left++;
beb904
-			continue;
beb904
-		}
beb904
-
beb904
 		debug(ap->logopt, "umount offset %s", oe->key);
beb904
 
beb904
 		if (umount_autofs_offset(ap, oe)) {
beb904
@@ -2794,7 +2821,6 @@ int clean_stale_multi_triggers(struct au
beb904
 				if (cache_delete_offset(oe->mc, key) == CHE_FAIL)
beb904
 					error(ap->logopt,
beb904
 					     "failed to delete offset key %s", key);
beb904
-				free(key);
beb904
 				continue;
beb904
 			}
beb904
 
beb904
@@ -2810,7 +2836,6 @@ int clean_stale_multi_triggers(struct au
beb904
 					left++;
beb904
 					/* But we did origianlly create this */
beb904
 					oe->flags |= MOUNT_FLAG_DIR_CREATED;
beb904
-					free(key);
beb904
 					continue;
beb904
 				}
beb904
 				/*
beb904
@@ -2828,7 +2853,6 @@ int clean_stale_multi_triggers(struct au
beb904
 				error(ap->logopt,
beb904
 				     "failed to delete offset key %s", key);
beb904
 		}
beb904
-		free(key);
beb904
 	}
beb904
 
beb904
 	return left;
beb904
--- autofs-5.1.4.orig/modules/parse_sun.c
beb904
+++ autofs-5.1.4/modules/parse_sun.c
beb904
@@ -1088,6 +1088,8 @@ static void cleanup_multi_triggers(struc
beb904
 	struct list_head *mm_root, *pos;
beb904
 	const char o_root[] = "/";
beb904
 	const char *mm_base;
beb904
+	unsigned int root_len;
beb904
+	unsigned int mm_base_len;
beb904
 
beb904
 	mm_root = &me->multi->multi_list;
beb904
 
beb904
@@ -1097,16 +1099,31 @@ static void cleanup_multi_triggers(struc
beb904
 		mm_base = base;
beb904
 
beb904
 	pos = NULL;
beb904
+	root_len = strlen(root);
beb904
+	mm_base_len = strlen(mm_base);
beb904
 
beb904
 	/* Make sure "none" of the offsets have an active mount. */
beb904
 	while ((poffset = cache_get_offset(mm_base, poffset, start, mm_root, &pos))) {
beb904
-		oe = cache_lookup_offset(mm_base, poffset, start, &me->multi_list);
beb904
-		/* root offset is a special case */
beb904
-		if (!oe || !oe->mapent || (strlen(oe->key) - start) == 1)
beb904
+		unsigned int path_len = root_len + strlen(poffset);
beb904
+
beb904
+		if (mm_base_len > 1)
beb904
+			path_len += mm_base_len;
beb904
+
beb904
+		if (path_len > PATH_MAX) {
beb904
+			warn(ap->logopt, "path loo long");
beb904
 			continue;
beb904
+		}
beb904
 
beb904
 		strcpy(path, root);
beb904
+		if (mm_base_len > 1)
beb904
+			strcat(path, mm_base);
beb904
 		strcat(path, poffset);
beb904
+
beb904
+		oe = cache_lookup_distinct(me->mc, path);
beb904
+		/* root offset is a special case */
beb904
+		if (!oe || !oe->mapent || (strlen(oe->key) - start) == 1)
beb904
+			continue;
beb904
+
beb904
 		if (umount(path)) {
beb904
 			error(ap->logopt, "error recovering from mount fail");
beb904
 			error(ap->logopt, "cannot umount offset %s", path);
beb904
@@ -1119,17 +1136,14 @@ static void cleanup_multi_triggers(struc
beb904
 static int mount_subtree(struct autofs_point *ap, struct mapent *me,
beb904
 			 const char *name, char *loc, char *options, void *ctxt)
beb904
 {
beb904
-	struct mapent *mm;
beb904
 	struct mapent *ro;
beb904
 	char *mm_root, *mm_base, *mm_key;
beb904
-	const char *mnt_root;
beb904
-	unsigned int mm_root_len, mnt_root_len;
beb904
+	unsigned int mm_root_len;
beb904
 	int start, ret = 0, rv;
beb904
 
beb904
 	rv = 0;
beb904
 
beb904
-	mm = me->multi;
beb904
-	mm_key = mm->key;
beb904
+	mm_key = me->multi->key;
beb904
 
beb904
 	if (*mm_key == '/') {
beb904
 		mm_root = mm_key;
beb904
@@ -1143,20 +1157,26 @@ static int mount_subtree(struct autofs_p
beb904
 	}
beb904
 	mm_root_len = strlen(mm_root);
beb904
 
beb904
-	mnt_root = mm_root;
beb904
-	mnt_root_len = mm_root_len;
beb904
-
beb904
 	if (me == me->multi) {
beb904
+		char key[PATH_MAX + 1];
beb904
+
beb904
+		if (mm_root_len + 1 > PATH_MAX) {
beb904
+			warn(ap->logopt, "path loo long");
beb904
+			return 1;
beb904
+		}
beb904
+
beb904
 		/* name = NULL */
beb904
 		/* destination = mm_root */
beb904
 		mm_base = "/";
beb904
 
beb904
+		strcpy(key, mm_root);
beb904
+		strcat(key, mm_base);
beb904
+
beb904
 		/* Mount root offset if it exists */
beb904
-		ro = cache_lookup_offset(mm_base, mm_base, strlen(mm_root), &me->multi_list);
beb904
+		ro = cache_lookup_distinct(me->mc, key);
beb904
 		if (ro) {
beb904
-			char *myoptions, *ro_loc, *tmp;
beb904
+			char *myoptions, *ro_loc;
beb904
 			int namelen = name ? strlen(name) : 0;
beb904
-			const char *root;
beb904
 			int ro_len;
beb904
 
beb904
 			myoptions = NULL;
beb904
@@ -1174,13 +1194,7 @@ static int mount_subtree(struct autofs_p
beb904
 			if (ro_loc)
beb904
 				ro_len = strlen(ro_loc);
beb904
 
beb904
-			tmp = alloca(mnt_root_len + 2);
beb904
-			strcpy(tmp, mnt_root);
beb904
-			tmp[mnt_root_len] = '/';
beb904
-			tmp[mnt_root_len + 1] = '\0';
beb904
-			root = tmp;
beb904
-
beb904
-			rv = sun_mount(ap, root, name, namelen, ro_loc, ro_len, myoptions, ctxt);
beb904
+			rv = sun_mount(ap, key, name, namelen, ro_loc, ro_len, myoptions, ctxt);
beb904
 
beb904
 			free(myoptions);
beb904
 			if (ro_loc)
beb904
@@ -1188,11 +1202,11 @@ static int mount_subtree(struct autofs_p
beb904
 		}
beb904
 
beb904
 		if (ro && rv == 0) {
beb904
-			ret = mount_multi_triggers(ap, me, mnt_root, start, mm_base);
beb904
+			ret = mount_multi_triggers(ap, me, mm_root, start, mm_base);
beb904
 			if (ret == -1) {
beb904
 				error(ap->logopt, MODPREFIX
beb904
 					 "failed to mount offset triggers");
beb904
-				cleanup_multi_triggers(ap, me, mnt_root, start, mm_base);
beb904
+				cleanup_multi_triggers(ap, me, mm_root, start, mm_base);
beb904
 				return 1;
beb904
 			}
beb904
 		} else if (rv <= 0) {
beb904
@@ -1208,24 +1222,29 @@ static int mount_subtree(struct autofs_p
beb904
 		int loclen = strlen(loc);
beb904
 		int namelen = strlen(name);
beb904
 
beb904
-		mnt_root = name;
beb904
-
beb904
 		/* name = mm_root + mm_base */
beb904
 		/* destination = mm_root + mm_base = name */
beb904
 		mm_base = &me->key[start];
beb904
 
beb904
-		rv = sun_mount(ap, mnt_root, name, namelen, loc, loclen, options, ctxt);
beb904
+		rv = sun_mount(ap, name, name, namelen, loc, loclen, options, ctxt);
beb904
 		if (rv == 0) {
beb904
-			ret = mount_multi_triggers(ap, me->multi, mnt_root, start, mm_base);
beb904
+			ret = mount_multi_triggers(ap, me->multi, name, start, mm_base);
beb904
 			if (ret == -1) {
beb904
 				error(ap->logopt, MODPREFIX
beb904
 					 "failed to mount offset triggers");
beb904
-				cleanup_multi_triggers(ap, me, mnt_root, start, mm_base);
beb904
+				cleanup_multi_triggers(ap, me, name, start, mm_base);
beb904
 				return 1;
beb904
 			}
beb904
 		} else if (rv < 0) {
beb904
-			char *mm_root_base = alloca(strlen(mm_root) + strlen(mm_base) + 1);
beb904
+			char mm_root_base[PATH_MAX + 1];
beb904
+			unsigned int mm_root_base_len = mm_root_len + strlen(mm_base) + 1;
beb904
 	
beb904
+			if (mm_root_base_len > PATH_MAX) {
beb904
+				warn(ap->logopt, MODPREFIX "path too long");
beb904
+				cache_delete_offset_list(me->mc, name);
beb904
+				return 1;
beb904
+			}
beb904
+
beb904
 			strcpy(mm_root_base, mm_root);
beb904
 			strcat(mm_root_base, mm_base);
beb904