diff mbox series

[V2,34/36] delta: add the option to limit size for source

Message ID 20211114172733.71602-35-sbabic@denx.de
State Changes Requested
Headers show
Series DELTA Update | expand

Commit Message

Stefano Babic Nov. 14, 2021, 5:27 p.m. UTC
When upgrading a partition, the filesystem could be much more smaller as
the partition itself. The handler as default will read the whole
partition and it will create the whole ZCK index for it, but this
requires more memory as really needed. Add a way to check the real size
of the filesystem, and do not index the rest of the partition.

Signed-off-by: Stefano Babic <sbabic@denx.de>
---
 doc/source/handlers.rst  |  6 ++++++
 handlers/delta_handler.c | 42 ++++++++++++++++++++++++++++++++++++++--
 2 files changed, 46 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/doc/source/handlers.rst b/doc/source/handlers.rst
index 8d78bbd..ecd2bf5 100644
--- a/doc/source/handlers.rst
+++ b/doc/source/handlers.rst
@@ -996,6 +996,12 @@  The resulting header file must be packed inside the SWU.
    |             |             | printed, and it reports if a chunk                 |
    |             |             | is downloaded  or copied from the source.          |
    +-------------+-------------+----------------------------------------------------+
+   | source-size | string      | This limits the index of the source                |
+   |             |             | It is helpful in case of filesystem in much        |
+   |             |             | bigger partition. It has the value for the size    |
+   |             |             | or it can be set to "detect" and the handler       |
+   |             |             | will try to find the effective size of fs.         |
+   +-------------+-------------+----------------------------------------------------+
 
 
 Example:
diff --git a/handlers/delta_handler.c b/handlers/delta_handler.c
index d959509..5229657 100644
--- a/handlers/delta_handler.c
+++ b/handlers/delta_handler.c
@@ -21,6 +21,7 @@ 
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/wait.h>
+#include <sys/statvfs.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <ctype.h>
@@ -35,6 +36,7 @@ 
 #include <util.h>
 #include <pctl.h>
 #include <pthread.h>
+#include <fs_interface.h>
 #include "delta_handler.h"
 #include "multipart_parser.h"
 #include "installer.h"
@@ -90,6 +92,8 @@  struct hnd_priv {
 	char *srcdev;			/* device as source for comparison */
 	char *chainhandler;		/* Handler to pass the decompressed image */
 	zck_log_type zckloglevel;	/* if found, set log level for ZCK to this */
+	bool detectsrcsize;		/* if set, try to compute size of filesystem in srcdev */
+	size_t srcsize;			/* Size of source */
 	unsigned long max_ranges;	/* Max allowed ranges (configured via sw-description) */
 	/* Data to be transferred to chain handler */
 	struct img_type img;
@@ -319,6 +323,15 @@  static int delta_retrieve_attributes(struct img_type *img, struct hnd_priv *priv
 	if (errno || priv->max_ranges == 0)
 		priv->max_ranges = DEFAULT_MAX_RANGES;
 
+	char *srcsize;
+	srcsize = dict_get_value(&img->properties, "source-size");
+	if (srcsize) {
+		if (!strcmp(srcsize, "detect"))
+			priv->detectsrcsize = true;
+		else
+			priv->srcsize = ustrtoull(srcsize, 10);
+	}
+
 	char *zckloglevel = dict_get_value(&img->properties, "zckloglevel");
 	if (!zckloglevel)
 		return 0;
@@ -452,7 +465,7 @@  static void zck_log_toswupdate(const char *function, zck_log_type lt,
 /*
  * Create a zck Index from a file
  */
-static bool create_zckindex(zckCtx *zck, int fd)
+static bool create_zckindex(zckCtx *zck, int fd, size_t maxbytes)
 {
 	const size_t bufsize = 16384;
 	char *buf = malloc(bufsize);
@@ -470,6 +483,8 @@  static bool create_zckindex(zckCtx *zck, int fd)
 			free(buf);
 			return false;
 		}
+		if (maxbytes && n > maxbytes)
+			break;
 	}
 
 	free(buf);
@@ -918,6 +933,29 @@  static int install_delta(struct img_type *img,
 		ERROR("/dev/null not present or cannot be opened, aborting...");
 		goto cleanup;
 	}
+
+	if (priv->detectsrcsize) {
+#if defined(CONFIG_DISKFORMAT)
+		char *filesystem = diskformat_fs_detect(priv->srcdev);
+		if (filesystem) {
+			char* DATADST_DIR = alloca(strlen(get_tmpdir())+strlen(DATADST_DIR_SUFFIX)+1);
+			sprintf(DATADST_DIR, "%s%s", get_tmpdir(), DATADST_DIR_SUFFIX);
+			if (!swupdate_mount(priv->srcdev, DATADST_DIR, filesystem)) {
+				struct statvfs vfs;
+				if (!statvfs(DATADST_DIR, &vfs)) {
+					TRACE("Detected filesystem %s, block size : %lu, %lu blocks =  %lu size",
+					       filesystem, vfs.f_frsize, vfs.f_blocks, vfs.f_frsize * vfs.f_blocks);
+					priv->srcsize = vfs.f_frsize * vfs.f_blocks;
+				}
+				swupdate_umount(DATADST_DIR);
+			}
+			free(filesystem);
+		}
+#else
+		WARN("SWUPdate not compiled with DISKFORMAT, skipping size detection..");
+#endif
+	}
+
 	in_fd = open(priv->srcdev, O_RDONLY);
 	if(in_fd < 0) {
 		ERROR("Unable to open Source : %s for reading", priv->srcdev);
@@ -984,7 +1022,7 @@  static int install_delta(struct img_type *img,
 		goto cleanup;
 	}
 
-	if (!create_zckindex(zckSrc, in_fd)) {
+	if (!create_zckindex(zckSrc, in_fd, priv->srcsize)) {
 		WARN("ZCK Header form %s cannot be created, fallback to full download",
 			priv->srcdev);
 	} else {