Blob Blame History Raw
autofs-5.1.7 - dont use realloc in host exports list processing

From: Ian Kent <raven@themaw.net>

If a server exports list is very large calling realloc(3) for each
export is slow. It's better to traverse the exports list twice, once
to calculate the length of the mapent then allocate the memory and
traverse the exports list again to construct the mapent.

Signed-off-by: Ian Kent <raven@themaw.net>
---
 CHANGELOG              |    1 +
 modules/lookup_hosts.c |   59 +++++++++++++++++++++---------------------------
 2 files changed, 27 insertions(+), 33 deletions(-)

--- autofs-5.1.4.orig/CHANGELOG
+++ autofs-5.1.4/CHANGELOG
@@ -1,6 +1,7 @@
 
 - add xdr_exports().
 - remove mount.x and rpcgen dependencies.
+- dont use realloc in host exports list processing.
 
 xx/xx/2018 autofs-5.1.5
 - fix flag file permission.
--- autofs-5.1.4.orig/modules/lookup_hosts.c
+++ autofs-5.1.4/modules/lookup_hosts.c
@@ -89,44 +89,40 @@ static char *get_exports(struct autofs_p
 	char buf[MAX_ERR_BUF];
 	char *mapent;
 	struct exportinfo *exp, *this;
+	size_t hostlen = strlen(host);
+	size_t mapent_len;
 
 	debug(ap->logopt, MODPREFIX "fetchng export list for %s", host);
 
 	exp = rpc_get_exports(host, 10, 0, RPC_CLOSE_NOLINGER);
 
-	mapent = NULL;
 	this = exp;
+	mapent_len = 0;
 	while (this) {
-		if (mapent) {
-			int len = strlen(mapent) + 1;
+		mapent_len += hostlen + 2*(strlen(this->dir) + 2) + 3;
+		this = this->next;
+	}
 
-			len += strlen(host) + 2*(strlen(this->dir) + 2) + 3;
-			mapent = realloc(mapent, len);
-			if (!mapent) {
-				char *estr;
-				estr = strerror_r(errno, buf, MAX_ERR_BUF);
-				error(ap->logopt, MODPREFIX "malloc: %s", estr);
-				rpc_exports_free(exp);
-				return NULL;
-			}
-			strcat(mapent, " \"");
-			strcat(mapent, this->dir);
-			strcat(mapent, "\"");
-		} else {
-			int len = 2*(strlen(this->dir) + 2) + strlen(host) + 3;
-
-			mapent = malloc(len);
-			if (!mapent) {
-				char *estr;
-				estr = strerror_r(errno, buf, MAX_ERR_BUF);
-				error(ap->logopt, MODPREFIX "malloc: %s", estr);
-				rpc_exports_free(exp);
-				return NULL;
-			}
+	mapent = malloc(mapent_len + 1);
+	if (!mapent) {
+		char *estr;
+		estr = strerror_r(errno, buf, MAX_ERR_BUF);
+		error(ap->logopt, MODPREFIX "malloc: %s", estr);
+		error(ap->logopt, MODPREFIX "exports lookup failed for %s", host);
+		rpc_exports_free(exp);
+		return NULL;
+	}
+	*mapent = 0;
+
+	this = exp;
+	while (this) {
+		if (!*mapent)
 			strcpy(mapent, "\"");
-			strcat(mapent, this->dir);
-			strcat(mapent, "\"");
-		}
+		else
+			strcat(mapent, " \"");
+		strcat(mapent, this->dir);
+		strcat(mapent, "\"");
+
 		strcat(mapent, " \"");
 		strcat(mapent, host);
 		strcat(mapent, ":");
@@ -137,9 +133,6 @@ static char *get_exports(struct autofs_p
 	}
 	rpc_exports_free(exp);
 
-	if (!mapent)
-		error(ap->logopt, MODPREFIX "exports lookup failed for %s", host);
-
 	return mapent;
 }