Blame SOURCES/autofs-5.1.7-dont-use-realloc-in-host-exports-list-processing.patch

96dc52
autofs-5.1.7 - dont use realloc in host exports list processing
96dc52
96dc52
From: Ian Kent <raven@themaw.net>
96dc52
96dc52
If a server exports list is very large calling realloc(3) for each
96dc52
export is slow. It's better to traverse the exports list twice, once
96dc52
to calculate the length of the mapent then allocate the memory and
96dc52
traverse the exports list again to construct the mapent.
96dc52
96dc52
Signed-off-by: Ian Kent <raven@themaw.net>
96dc52
---
96dc52
 CHANGELOG              |    1 +
96dc52
 modules/lookup_hosts.c |   59 +++++++++++++++++++++---------------------------
96dc52
 2 files changed, 27 insertions(+), 33 deletions(-)
96dc52
96dc52
diff --git a/CHANGELOG b/CHANGELOG
96dc52
index 19af245e..1bd6ac7f 100644
96dc52
--- a/CHANGELOG
96dc52
+++ b/CHANGELOG
96dc52
@@ -1,6 +1,7 @@
96dc52
 
96dc52
 - add xdr_exports().
96dc52
 - remove mount.x and rpcgen dependencies.
96dc52
+- dont use realloc in host exports list processing.
96dc52
 
96dc52
 25/01/2021 autofs-5.1.7
96dc52
 - make bind mounts propagation slave by default.
96dc52
diff --git a/modules/lookup_hosts.c b/modules/lookup_hosts.c
96dc52
index 81a4eb18..e3ee0ab8 100644
96dc52
--- a/modules/lookup_hosts.c
96dc52
+++ b/modules/lookup_hosts.c
96dc52
@@ -89,44 +89,40 @@ static char *get_exports(struct autofs_point *ap, const char *host)
96dc52
 	char buf[MAX_ERR_BUF];
96dc52
 	char *mapent;
96dc52
 	struct exportinfo *exp, *this;
96dc52
+	size_t hostlen = strlen(host);
96dc52
+	size_t mapent_len;
96dc52
 
96dc52
 	debug(ap->logopt, MODPREFIX "fetchng export list for %s", host);
96dc52
 
96dc52
 	exp = rpc_get_exports(host, 10, 0, RPC_CLOSE_NOLINGER);
96dc52
 
96dc52
-	mapent = NULL;
96dc52
 	this = exp;
96dc52
+	mapent_len = 0;
96dc52
 	while (this) {
96dc52
-		if (mapent) {
96dc52
-			int len = strlen(mapent) + 1;
96dc52
-
96dc52
-			len += strlen(host) + 2*(strlen(this->dir) + 2) + 3;
96dc52
-			mapent = realloc(mapent, len);
96dc52
-			if (!mapent) {
96dc52
-				char *estr;
96dc52
-				estr = strerror_r(errno, buf, MAX_ERR_BUF);
96dc52
-				error(ap->logopt, MODPREFIX "malloc: %s", estr);
96dc52
-				rpc_exports_free(exp);
96dc52
-				return NULL;
96dc52
-			}
96dc52
-			strcat(mapent, " \"");
96dc52
-			strcat(mapent, this->dir);
96dc52
-			strcat(mapent, "\"");
96dc52
-		} else {
96dc52
-			int len = 2*(strlen(this->dir) + 2) + strlen(host) + 3;
96dc52
-
96dc52
-			mapent = malloc(len);
96dc52
-			if (!mapent) {
96dc52
-				char *estr;
96dc52
-				estr = strerror_r(errno, buf, MAX_ERR_BUF);
96dc52
-				error(ap->logopt, MODPREFIX "malloc: %s", estr);
96dc52
-				rpc_exports_free(exp);
96dc52
-				return NULL;
96dc52
-			}
96dc52
+		mapent_len += hostlen + 2*(strlen(this->dir) + 2) + 3;
96dc52
+		this = this->next;
96dc52
+	}
96dc52
+
96dc52
+	mapent = malloc(mapent_len + 1);
96dc52
+	if (!mapent) {
96dc52
+		char *estr;
96dc52
+		estr = strerror_r(errno, buf, MAX_ERR_BUF);
96dc52
+		error(ap->logopt, MODPREFIX "malloc: %s", estr);
96dc52
+		error(ap->logopt, MODPREFIX "exports lookup failed for %s", host);
96dc52
+		rpc_exports_free(exp);
96dc52
+		return NULL;
96dc52
+	}
96dc52
+	*mapent = 0;
96dc52
+
96dc52
+	this = exp;
96dc52
+	while (this) {
96dc52
+		if (!*mapent)
96dc52
 			strcpy(mapent, "\"");
96dc52
-			strcat(mapent, this->dir);
96dc52
-			strcat(mapent, "\"");
96dc52
-		}
96dc52
+		else
96dc52
+			strcat(mapent, " \"");
96dc52
+		strcat(mapent, this->dir);
96dc52
+		strcat(mapent, "\"");
96dc52
+
96dc52
 		strcat(mapent, " \"");
96dc52
 		strcat(mapent, host);
96dc52
 		strcat(mapent, ":");
96dc52
@@ -137,9 +133,6 @@ static char *get_exports(struct autofs_point *ap, const char *host)
96dc52
 	}
96dc52
 	rpc_exports_free(exp);
96dc52
 
96dc52
-	if (!mapent)
96dc52
-		error(ap->logopt, MODPREFIX "exports lookup failed for %s", host);
96dc52
-
96dc52
 	return mapent;
96dc52
 }
96dc52