ubi: provide a way to skip CRC checks
authorQuentin Schulz <quentin.schulz@bootlin.com>
Thu, 12 Sep 2019 14:41:01 +0000 (16:41 +0200)
committerHeiko Schocher <hs@denx.de>
Wed, 16 Oct 2019 03:42:27 +0000 (05:42 +0200)
Some users of static UBI volumes implement their own integrity check,
thus making the volume CRC check done at open time useless. For
instance, this is the case when one use the ubiblock + dm-verity +
squashfs combination, where dm-verity already checks integrity of the
block device but this time at the block granularity instead of verifying
the whole volume.

Skipping this test drastically improves the boot-time.

Adapted to U-Boot by Stefan Roese.

Signed-off-by: Quentin Schulz <quentin.schulz@bootlin.com>
Signed-off-by: Stefan Roese <sr@denx.de>
Reviewed-by: Heiko Schocher <hs@denx.de>
Cc: Quentin Schulz <quentin.schulz@bootlin.com>
Cc: Boris Brezillon <boris.brezillon@bootlin.com>
cmd/ubi.c
drivers/mtd/ubi/kapi.c
drivers/mtd/ubi/ubi-media.h
drivers/mtd/ubi/ubi.h
drivers/mtd/ubi/vmt.c
drivers/mtd/ubi/vtbl.c
include/mtd/ubi-user.h

index ca5dc9021b128d1b57bb338a0272a51ea35cd393..c857f07d930a1e6f6a3715e40529b4dfad11ce03 100644 (file)
--- a/cmd/ubi.c
+++ b/cmd/ubi.c
@@ -146,7 +146,8 @@ bad:
        return err;
 }
 
-static int ubi_create_vol(char *volume, int64_t size, int dynamic, int vol_id)
+static int ubi_create_vol(char *volume, int64_t size, int dynamic, int vol_id,
+                         bool skipcheck)
 {
        struct ubi_mkvol_req req;
        int err;
@@ -163,7 +164,10 @@ static int ubi_create_vol(char *volume, int64_t size, int dynamic, int vol_id)
        strcpy(req.name, volume);
        req.name_len = strlen(volume);
        req.name[req.name_len] = '\0';
-       req.padding1 = 0;
+       req.flags = 0;
+       if (skipcheck)
+               req.flags |= UBI_VOL_SKIP_CRC_CHECK_FLG;
+
        /* It's duplicated at drivers/mtd/ubi/cdev.c */
        err = verify_mkvol_req(ubi, &req);
        if (err) {
@@ -469,6 +473,7 @@ static int do_ubi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
        int64_t size = 0;
        ulong addr = 0;
+       bool skipcheck = false;
 
        if (argc < 2)
                return CMD_RET_USAGE;
@@ -527,6 +532,12 @@ static int do_ubi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
                /* Use maximum available size */
                size = 0;
 
+               /* E.g., create volume with "skipcheck" bit set */
+               if (argc == 7) {
+                       skipcheck = strncmp(argv[6], "--skipcheck", 11) == 0;
+                       argc--;
+               }
+
                /* E.g., create volume size type vol_id */
                if (argc == 6) {
                        id = simple_strtoull(argv[5], NULL, 16);
@@ -555,8 +566,10 @@ static int do_ubi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
                        printf("No size specified -> Using max size (%lld)\n", size);
                }
                /* E.g., create volume */
-               if (argc == 3)
-                       return ubi_create_vol(argv[2], size, dynamic, id);
+               if (argc == 3) {
+                       return ubi_create_vol(argv[2], size, dynamic, id,
+                                             skipcheck);
+               }
        }
 
        if (strncmp(argv[1], "remove", 6) == 0) {
@@ -623,7 +636,7 @@ static int do_ubi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 }
 
 U_BOOT_CMD(
-       ubi, 6, 1, do_ubi,
+       ubi, 7, 1, do_ubi,
        "ubi commands",
        "detach"
                " - detach ubi from a mtd partition\n"
@@ -634,7 +647,7 @@ U_BOOT_CMD(
                " - Display volume and ubi layout information\n"
        "ubi check volumename"
                " - check if volumename exists\n"
-       "ubi create[vol] volume [size] [type] [id]\n"
+       "ubi create[vol] volume [size] [type] [id] [--skipcheck]\n"
                " - create volume name with size ('-' for maximum"
                " available size)\n"
        "ubi write[vol] address volume size"
index 2e171b0209c5a427063a0c53817e49e4a88aa70e..bcea71b1b2364f0f86121a4c51f5e2e308ce83e4 100644 (file)
@@ -196,7 +196,7 @@ struct ubi_volume_desc *ubi_open_volume(int ubi_num, int vol_id, int mode)
        desc->mode = mode;
 
        mutex_lock(&ubi->ckvol_mutex);
-       if (!vol->checked) {
+       if (!vol->checked && !vol->skip_check) {
                /* This is the first open - check the volume */
                err = ubi_check_volume(ubi, vol_id);
                if (err < 0) {
index bd7a580961c5e2c33a54460bee6b1b07c216d164..4af85c4247bd73d385a087fd3810ecada7da7043 100644 (file)
@@ -48,6 +48,11 @@ enum {
  * Volume flags used in the volume table record.
  *
  * @UBI_VTBL_AUTORESIZE_FLG: auto-resize this volume
+ * @UBI_VTBL_SKIP_CRC_CHECK_FLG: skip the CRC check done on a static volume at
+ *                              open time. Should only be set on volumes that
+ *                              are used by upper layers doing this kind of
+ *                              check. Main use-case for this flag is
+ *                              boot-time reduction
  *
  * %UBI_VTBL_AUTORESIZE_FLG flag can be set only for one volume in the volume
  * table. UBI automatically re-sizes the volume which has this flag and makes
@@ -79,6 +84,7 @@ enum {
  */
 enum {
        UBI_VTBL_AUTORESIZE_FLG = 0x01,
+       UBI_VTBL_SKIP_CRC_CHECK_FLG = 0x02,
 };
 
 /*
index 918d03590c8a6313b6caa6df630385f08cb1d390..f44960186bbd20b2a97e52b1c12a83d6b2a52dcb 100644 (file)
@@ -293,6 +293,9 @@ struct ubi_fm_pool {
  *           atomic LEB change
  *
  * @eba_tbl: EBA table of this volume (LEB->PEB mapping)
+ * @skip_check: %1 if CRC check of this static volume should be skipped.
+ *             Directly reflects the presence of the
+ *             %UBI_VTBL_SKIP_CRC_CHECK_FLG flag in the vtbl entry
  * @checked: %1 if this static volume was checked
  * @corrupted: %1 if the volume is corrupted (static volumes only)
  * @upd_marker: %1 if the update marker is set for this volume
@@ -341,6 +344,7 @@ struct ubi_volume {
        void *upd_buf;
 
        int *eba_tbl;
+       unsigned int skip_check:1;
        unsigned int checked:1;
        unsigned int corrupted:1;
        unsigned int upd_marker:1;
index 94c8a98d47a19ce6d2fddabe03bf87121e4a2e4f..a2ff1b5769d092c2f3cb7846fea0e9e8e955768f 100644 (file)
@@ -162,6 +162,9 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
        if (!vol)
                return -ENOMEM;
 
+       if (req->flags & UBI_VOL_SKIP_CRC_CHECK_FLG)
+               vol->skip_check = 1;
+
        spin_lock(&ubi->volumes_lock);
        if (vol_id == UBI_VOL_NUM_AUTO) {
                /* Find unused volume ID */
@@ -295,6 +298,10 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
                vtbl_rec.vol_type = UBI_VID_DYNAMIC;
        else
                vtbl_rec.vol_type = UBI_VID_STATIC;
+
+       if (vol->skip_check)
+               vtbl_rec.flags |= UBI_VTBL_SKIP_CRC_CHECK_FLG;
+
        memcpy(vtbl_rec.name, vol->name, vol->name_len);
 
        err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec);
@@ -738,6 +745,11 @@ static int self_check_volume(struct ubi_device *ubi, int vol_id)
                        ubi_err(ubi, "bad used_bytes");
                        goto fail;
                }
+
+               if (vol->skip_check) {
+                       ubi_err(ubi, "bad skip_check");
+                       goto fail;
+               }
        } else {
                if (vol->used_ebs < 0 || vol->used_ebs > vol->reserved_pebs) {
                        ubi_err(ubi, "bad used_ebs");
index fe96d3a894daf37064be7064565ec2b57e34340b..fb535c1a878044bb10547bdeffbc611f3c5b5404 100644 (file)
@@ -554,6 +554,9 @@ static int init_volumes(struct ubi_device *ubi,
                vol->name[vol->name_len] = '\0';
                vol->vol_id = i;
 
+               if (vtbl[i].flags & UBI_VTBL_SKIP_CRC_CHECK_FLG)
+                       vol->skip_check = 1;
+
                if (vtbl[i].flags & UBI_VTBL_AUTORESIZE_FLG) {
                        /* Auto re-size flag may be set only for one volume */
                        if (ubi->autoresize_vol_id != -1) {
index cd81ef965c84f7517051f61af9e2a40c7d09372f..8d472cc01380efd9570631fe8f2c9b398c7d1865 100644 (file)
@@ -271,6 +271,20 @@ struct ubi_attach_req {
        __s8 padding[10];
 };
 
+/*
+ * UBI volume flags.
+ *
+ * @UBI_VOL_SKIP_CRC_CHECK_FLG: skip the CRC check done on a static volume at
+ *                             open time. Only valid for static volumes and
+ *                             should only be used if the volume user has a
+ *                             way to verify data integrity
+ */
+enum {
+       UBI_VOL_SKIP_CRC_CHECK_FLG = 0x1,
+};
+
+#define UBI_VOL_VALID_FLGS     (UBI_VOL_SKIP_CRC_CHECK_FLG)
+
 /**
  * struct ubi_mkvol_req - volume description data structure used in
  *                        volume creation requests.
@@ -278,7 +292,7 @@ struct ubi_attach_req {
  * @alignment: volume alignment
  * @bytes: volume size in bytes
  * @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME)
- * @padding1: reserved for future, not used, has to be zeroed
+ * @flags: volume flags (%UBI_VOL_SKIP_CRC_CHECK_FLG)
  * @name_len: volume name length
  * @padding2: reserved for future, not used, has to be zeroed
  * @name: volume name
@@ -307,7 +321,7 @@ struct ubi_mkvol_req {
        __s32 alignment;
        __s64 bytes;
        __s8 vol_type;
-       __s8 padding1;
+       __u8 flags;
        __s16 name_len;
        __s8 padding2[4];
        char name[UBI_MAX_VOLUME_NAME + 1];