[PATCH] bareboximd: Use mmap when possibly

Sascha Hauer s.hauer at pengutronix.de
Wed Apr 14 14:46:19 BST 2021


It's hard to believe but there are systems out there that are so sparse
with memory that they can't afford 1MiB of RAM to read a file into.
Use mmap when possible and fall back to reading into an allocated buffer
otherwise.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 common/imd.c         |  6 ++++-
 scripts/bareboximd.c | 53 ++++++++++++++++++++++++++++----------------
 2 files changed, 39 insertions(+), 20 deletions(-)

diff --git a/common/imd.c b/common/imd.c
index aff3b00b6b..e1d5733c6b 100644
--- a/common/imd.c
+++ b/common/imd.c
@@ -17,6 +17,10 @@ int imd_command_setenv(const char *variable_name, const char *value)
 	return -ENOSYS;
 }
 #endif
+static inline void read_file_2_free(void *buf)
+{
+	free(buf);
+}
 #endif
 
 /*
@@ -542,6 +546,6 @@ int imd_command(int argc, char *argv[])
 
 	ret = 0;
 out:
-	free(buf);
+	read_file_2_free(buf);
 	return ret;
 }
diff --git a/scripts/bareboximd.c b/scripts/bareboximd.c
index 9558c77d1a..c3dcb4dcf0 100644
--- a/scripts/bareboximd.c
+++ b/scripts/bareboximd.c
@@ -15,6 +15,7 @@
 #include <stdarg.h>
 #include <linux/err.h>
 #include <linux/kernel.h>
+#include <sys/mman.h>
 
 #include "../include/image-metadata.h"
 
@@ -96,29 +97,35 @@ static int read_file_2(const char *filename, size_t *size, void **outbuf, size_t
 		goto close;
 	}
 
-	buf = malloc(max_size);
-	if (!buf) {
-		fprintf(stderr, "Cannot allocate memory\n");
-		ret = -ENOMEM;
-		goto close;
-	}
+	buf = mmap(NULL, max_size, PROT_READ, MAP_SHARED, fd, 0);
+	if (buf == MAP_FAILED ) {
+		buf = malloc(max_size);
+		if (!buf) {
+			fprintf(stderr, "Cannot allocate memory\n");
+			ret = -ENOMEM;
+			goto close;
+		}
 
-	*outbuf = buf;
-	while (*size < max_size) {
-		rsize = read(fd, buf, max_size-*size);
-		if (rsize == 0) {
-			ret = -EIO;
-			goto free;
-		} else if (rsize < 0) {
-			if (errno == EAGAIN)
-				continue;
-			else {
+		*outbuf = buf;
+
+		while (*size < max_size) {
+			rsize = read(fd, buf, max_size - *size);
+			if (rsize == 0) {
+				ret = -EIO;
+				goto free;
+			}
+
+			if (rsize < 0) {
 				ret = -errno;
 				goto free;
 			}
-		} /* ret > 0 */
-		buf += rsize;
-		*size += rsize;
+
+			buf += rsize;
+			*size += rsize;
+		}
+	} else {
+		*outbuf = buf;
+		*size = max_size;
 	}
 
 	ret = 0;
@@ -131,6 +138,14 @@ close:
 	return ret;
 }
 
+static inline void read_file_2_free(void *buf)
+{
+	/*
+	 * Can't free() here because buffer might be mmapped. No need
+	 * to do anything as we are exitting in a moment anyway.
+	 */
+}
+
 static unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base)
 {
 	return strtoul(cp, endp, base);
-- 
2.29.2




More information about the barebox mailing list