upgrade-apply: Stop copying data twice 43/292643/3
authorMateusz Moscicki <m.moscicki2@partner.samsung.com>
Wed, 10 May 2023 12:02:24 +0000 (14:02 +0200)
committerMateusz Moscicki <m.moscicki2@partner.samsung.com>
Mon, 7 Aug 2023 09:33:52 +0000 (11:33 +0200)
In case the destination partition is the clone of the source partition,
then there is no need to copy data again, because it is already in
place.

Change-Id: I31efe018a76f1237452109fd463056c949e88bf9

scripts/upgrade-support/upgrade-common.inc
src/upgrade-apply/main.c
src/upgrade-apply/patch/patch.c
src/upgrade-apply/patch/patch.h
src/upgrade-apply/patch/patch_helper.c

index 88473fecf23298aef4947e3b62b29c4c890577d8..2829dc34f34182a4b9794cf31bdad9c2c39f9a88 100644 (file)
@@ -235,6 +235,7 @@ upgrade_images() {
                                                          --archive-file "$DELTA_NAME" \
                                                          --kind ss_brotli_patch \
                                                          --patch-orig "$CURR_PARTITION" \
+                                                         --no-write-all \
                                                          --dest-sha1 "$NEW_SHA" && UP_RES=$? || UP_RES=$?
                                ;;
                        DELTA_FS)
index ecde48a8a857d27705eeae0dc6d77604accc2869..5711e7511452bc04a7c87005ebd02c130509d5cb 100644 (file)
@@ -69,6 +69,7 @@ struct parse_result {
        const char *patch_orig;
        const char *dest_sha1;
        size_t dest_size;
+       bool write_all;
        enum archive_kind kind;
 };
 
@@ -82,6 +83,7 @@ struct parse_result parse_args(int argc, char **argv)
        long long int dest_size = 0;
        enum archive_kind kind = -1;
        bool help = false;
+       bool write_all = true;
 
        for (;;) {
                const struct option long_options[] = {
@@ -92,10 +94,11 @@ struct parse_result parse_args(int argc, char **argv)
                        {"patch-orig",   required_argument, NULL, 4  },
                        {"dest-sha1",    required_argument, NULL, 5  },
                        {"dest-size",    required_argument, NULL, 6  },
+                       {"no-write-all", no_argument,       NULL, 'n'},
                        {"help",         no_argument,       NULL, 'h'},
                        {0}
                };
-               int option = getopt_long(argc, argv, "h", long_options, NULL);
+               int option = getopt_long(argc, argv, "hn", long_options, NULL);
                if (option < 0)
                        break;
 
@@ -149,6 +152,12 @@ struct parse_result parse_args(int argc, char **argv)
                                return (struct parse_result) { .result = PARSE_BAD_SIZE };
                        break;
 
+               case 'n': // no-write-all
+                       if (!write_all)
+                               return (struct parse_result) { .result = PARSE_REPEATED_ARGUMENT };
+                       write_all = false;
+                       break;
+
                case 'h': // help
                        if (help)
                                return (struct parse_result) { .result = PARSE_REPEATED_ARGUMENT };
@@ -189,6 +198,7 @@ struct parse_result parse_args(int argc, char **argv)
                .dest_sha1 = dest_sha1,
                .dest_size = dest_size,
                .kind = kind,
+               .write_all = write_all,
        };
 }
 
@@ -249,7 +259,7 @@ ssize_t gzip_write(__attribute__((unused)) int useless_fd, __attribute__((unused
 void help(char *name)
 {
        fprintf(stderr,
-               "Usage: %s --archive ARCHIVE --archive-file FILE --dest DESTINATION --kind KIND [--patch-orig ORIGIN] [--dest-sha1 SHA1] [--dest-size SIZE]\n"
+               "Usage: %s --archive ARCHIVE --archive-file FILE --dest DESTINATION --kind KIND [--patch-orig ORIGIN] [--dest-sha1 SHA1] [--dest-size SIZE] [--no-write-all]\n"
                "\n"
                "Patches a partition using an archive.\n"
                "It will look for a file named FILE in an archive called ARCHIVE; the archive should have an extension\n"
@@ -261,7 +271,9 @@ void help(char *name)
                "The results will be written to the DESTINATION partition.\n"
                "If SHA1 is provided (lowercase hexadecimal), it is compared to the one calculated on DESTINATION after writing.\n"
                "Additionally, if SIZE is provided, it is used as the destination size; this matters for SHA1 comparision,\n"
-               "and also if ss_brotli_patch.\n",
+               "and also if ss_brotli_patch.\n"
+               "In case the KIND is ss_brotli_path and the DESTINATION is the clone of the ORIGIN you can specify\n"
+               "the --no-write-all flag to not copy the data from the source, because it is already there.\n",
        name);
 }
 
@@ -474,7 +486,7 @@ int main(int argc, char **argv)
                case KIND_BROTLI_PATCH:
                        {
                                struct dec_funcs funcs = { init_brotli, decompress_brotli, free_brotli };
-                               r = apply_patch(parsed.patch_orig, parsed.dest, tar, parsed.dest_size, NULL, &funcs);
+                               r = apply_patch(parsed.patch_orig, parsed.dest, tar, parsed.dest_size, NULL, parsed.write_all, &funcs);
                                break;
                        }
                }
index e2af1456d61dbc4f0afa807cf90ab1e254d9ff44..6f2964083011a52c6bb22a48b0b772f087e26c3a 100644 (file)
@@ -335,7 +335,7 @@ int read_header(struct dec_funcs *funcs, struct bs_data *data, uint8_t **buff_ou
     return PF_OK;
 }
 
-int apply_patch(const char *source_file, const char *dest_file, TAR *patch_tar, size_t dest_size, size_t *free_space, struct dec_funcs *funcs)
+int apply_patch(const char *source_file, const char *dest_file, TAR *patch_tar, size_t dest_size, size_t *free_space, bool write_all, struct dec_funcs *funcs)
 {
     assert(source_file);
     assert(dest_file);
@@ -411,7 +411,14 @@ int apply_patch(const char *source_file, const char *dest_file, TAR *patch_tar,
                     goto exit;
                 if ((result = remmap_if_needed(&data.dest)) != PF_OK)
                     goto exit;
-                *data.dest.pos = *(uint8_t*)data.src.pos + *(uint8_t*)buff_out_pos;
+                /*
+                 * If *buff_out_pos == 0 and old_pos == new_pos then it is basically a data copy.
+                 * In case the destination partition is the clone of the source partition,
+                 * then there is no need to copy data again, because it is already in place.
+                 */
+                if (write_all || old_pos != new_pos || *(uint8_t*)buff_out_pos != 0) {
+                    *data.dest.pos = *(uint8_t*)data.src.pos + *(uint8_t*)buff_out_pos;
+                }
                 data.dest.pos++;
                 data.src.pos++;
                 buff_out_pos++;
index 8a2c462e05fa3710f7ccfd03a46afff4e41d1c8c..476e025779a7ecaddcfbca9554e2f68b93af8ffb 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <libtar.h>
 #include <stdint.h>
+#include <stdbool.h>
 #include <sys/types.h>
 
 #define PF_OK 0
@@ -65,4 +66,4 @@ struct dec_funcs {
     void (*clean)(struct bs_data *data);
 };
 
-extern int apply_patch(const char *source_file, const char *dest_file, TAR *patch_tar, size_t dest_size, size_t *free_space, struct dec_funcs *funcs);
+extern int apply_patch(const char *source_file, const char *dest_file, TAR *patch_tar, size_t dest_size, size_t *free_space, bool write_all, struct dec_funcs *funcs);
index fb6e7d1a8862b21111a814e0b00dd040ff239fe0..d71d454ff187b864fd6f1d8827cfebde142dfbd8 100644 (file)
@@ -18,8 +18,8 @@
 
 #include "brotli.h"
 
-int apply_patch_brotli(const char *source_file, const char *dest_file, TAR *patch_tar, size_t dest_size, size_t *free_space)
+int apply_patch_brotli(const char *source_file, const char *dest_file, TAR *patch_tar, size_t dest_size, size_t *free_space, bool write_all)
 {
     struct dec_funcs funcs = { init_brotli, decompress_brotli, free_brotli };
-    return apply_patch(source_file, dest_file, patch_tar, dest_size, free_space, &funcs);
+    return apply_patch(source_file, dest_file, patch_tar, dest_size, free_space, write_all, &funcs);
 }