Adding code for superblock checksum calculation.

incorporated the changes suggested in previous patch.

Signed-off-by: Pratik Shinde <[email protected]>
---
 include/erofs/config.h |  1 +
 include/erofs_fs.h     | 10 ++++++++
 mkfs/main.c            | 64 +++++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 74 insertions(+), 1 deletion(-)

diff --git a/include/erofs/config.h b/include/erofs/config.h
index 05fe6b2..40cd466 100644
--- a/include/erofs/config.h
+++ b/include/erofs/config.h
@@ -22,6 +22,7 @@ struct erofs_configure {
        char *c_src_path;
        char *c_compr_alg_master;
        int c_compr_level_master;
+       int c_feature_flags;
 };
 
 extern struct erofs_configure cfg;
diff --git a/include/erofs_fs.h b/include/erofs_fs.h
index 601b477..9ac2635 100644
--- a/include/erofs_fs.h
+++ b/include/erofs_fs.h
@@ -20,6 +20,16 @@
 #define EROFS_REQUIREMENT_LZ4_0PADDING 0x00000001
 #define EROFS_ALL_REQUIREMENTS         EROFS_REQUIREMENT_LZ4_0PADDING
 
+/*
+ * feature definations.
+ */
+#define EROFS_DEFAULT_FEATURES         EROFS_FEATURE_SB_CHKSUM
+#define EROFS_FEATURE_SB_CHKSUM                0x0001
+
+
+#define EROFS_HAS_COMPAT_FEATURE(super,mask)   \
+       ( le32_to_cpu((super)->features) & (mask) )
+
 struct erofs_super_block {
 /*  0 */__le32 magic;           /* in the little endian */
 /*  4 */__le32 checksum;        /* crc32c(super_block) */
diff --git a/mkfs/main.c b/mkfs/main.c
index f127fe1..355fd2c 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -31,6 +31,45 @@ static void usage(void)
        fprintf(stderr, " -EX[,...] X=extended options\n");
 }
 
+#define CRCPOLY        0x82F63B78
+static inline u32 crc32c(u32 seed, unsigned char const *in, size_t len)
+{
+       int i;
+       u32 crc = seed;
+
+       while (len--) {
+               crc ^= *in++;
+               for (i = 0; i < 8; i++) {
+                       crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY : 0);
+               }
+       }
+       erofs_dump("calculated crc: 0x%x\n", crc);
+       return crc;
+}
+
+char *feature_opts[] = {
+       "nosbcrc", NULL
+};
+#define O_SB_CKSUM     0
+
+static int parse_feature_subopts(char *opts)
+{
+       char *arg;
+
+       cfg.c_feature_flags = EROFS_DEFAULT_FEATURES;
+       while (*opts != '\0') {
+               switch(getsubopt(&opts, feature_opts, &arg)) {
+               case O_SB_CKSUM:
+                       cfg.c_feature_flags |= (~EROFS_FEATURE_SB_CHKSUM);
+                       break;
+               default:
+                       erofs_err("incorrect suboption");
+                       return -EINVAL;
+               }
+       }
+       return 0;
+}
+
 static int parse_extended_opts(const char *opts)
 {
 #define MATCH_EXTENTED_OPT(opt, token, keylen) \
@@ -79,7 +118,8 @@ static int mkfs_parse_options_cfg(int argc, char *argv[])
 {
        int opt, i;
 
-       while ((opt = getopt(argc, argv, "d:z:E:")) != -1) {
+       cfg.c_feature_flags = EROFS_DEFAULT_FEATURES;
+       while ((opt = getopt(argc, argv, "d:z:E:o:")) != -1) {
                switch (opt) {
                case 'z':
                        if (!optarg) {
@@ -113,6 +153,12 @@ static int mkfs_parse_options_cfg(int argc, char *argv[])
                                return opt;
                        break;
 
+               case 'O':
+                       opt = parse_feature_subopts(optarg);
+                       if (opt)
+                               return opt;
+                       break;
+
                default: /* '?' */
                        return -EINVAL;
                }
@@ -144,6 +190,15 @@ static int mkfs_parse_options_cfg(int argc, char *argv[])
        return 0;
 }
 
+u32 erofs_superblock_checksum(struct erofs_super_block *sb)
+{
+       u32 crc;
+       crc = crc32c(~0, (const unsigned char *)sb,
+                   sizeof(struct erofs_super_block));
+       erofs_dump("superblock checksum: 0x%x\n", crc);
+       return crc;
+}
+
 int erofs_mkfs_update_super_block(struct erofs_buffer_head *bh,
                                  erofs_nid_t root_nid)
 {
@@ -155,6 +210,7 @@ int erofs_mkfs_update_super_block(struct erofs_buffer_head 
*bh,
                .meta_blkaddr  = sbi.meta_blkaddr,
                .xattr_blkaddr = 0,
                .requirements = cpu_to_le32(sbi.requirements),
+               .features = cpu_to_le32(cfg.c_feature_flags),
        };
        const unsigned int sb_blksize =
                round_up(EROFS_SUPER_END, EROFS_BLKSIZ);
@@ -169,6 +225,12 @@ int erofs_mkfs_update_super_block(struct erofs_buffer_head 
*bh,
        sb.blocks       = cpu_to_le32(erofs_mapbh(NULL, true));
        sb.root_nid     = cpu_to_le16(root_nid);
 
+       if (EROFS_HAS_COMPAT_FEATURE(&sb, EROFS_FEATURE_SB_CHKSUM)) {
+               sb.checksum = 0;
+               u32 crc = erofs_superblock_checksum(&sb);
+               sb.checksum = cpu_to_le32(crc);
+       }
+
        buf = calloc(sb_blksize, 1);
        if (!buf) {
                erofs_err("Failed to allocate memory for sb: %s",
-- 
2.9.3

Reply via email to