diff options
author | Pratik Shinde <pratikshinde320@gmail.com> | 2019-11-07 12:03:26 +0800 |
---|---|---|
committer | Gao Xiang <hsiangkao@aol.com> | 2019-11-08 21:50:24 +0800 |
commit | fb757ede69e7f310e2c91cd3672e2e4049a1d348 (patch) | |
tree | 991208d72a7514f2ca24a7f8685d58026ad5daf3 /mkfs/main.c | |
parent | a34f86beb16b25cb0f44c85934acb93749fc844c (diff) | |
download | erofs-utils-fb757ede69e7f310e2c91cd3672e2e4049a1d348.tar.gz |
erofs-utils: support calculating checksum of superblock
Added code for calculating crc of superblock.
Note that the first 1024 bytes are not checksummed to allow
for the installation of x86 boot sectors and other oddities.
Fill 'feature_compat' field of erofs_super_block so that it
can be used on kernel side. also fixing one typo.
Link: https://lore.kernel.org/r/20191107040327.93369-1-gaoxiang25@huawei.com
Signed-off-by: Pratik Shinde <pratikshinde320@gmail.com>
Reviewed-by: Chao Yu <yuchao0@huawei.com>
Reviewed-by: Li Guifu <blucerlee@gmail.com>
Signed-off-by: Gao Xiang <gaoxiang25@huawei.com>
Diffstat (limited to 'mkfs/main.c')
-rw-r--r-- | mkfs/main.c | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/mkfs/main.c b/mkfs/main.c index ab57896..9187c43 100644 --- a/mkfs/main.c +++ b/mkfs/main.c @@ -109,6 +109,12 @@ static int parse_extended_opts(const char *opts) return -EINVAL; cfg.c_force_inodeversion = FORCE_INODE_EXTENDED; } + + if (MATCH_EXTENTED_OPT("nosbcrc", token, keylen)) { + if (vallen) + return -EINVAL; + sbi.feature_compat &= ~EROFS_FEATURE_COMPAT_SB_CHKSUM; + } } return 0; } @@ -218,6 +224,8 @@ int erofs_mkfs_update_super_block(struct erofs_buffer_head *bh, .meta_blkaddr = sbi.meta_blkaddr, .xattr_blkaddr = sbi.xattr_blkaddr, .feature_incompat = cpu_to_le32(sbi.feature_incompat), + .feature_compat = cpu_to_le32(sbi.feature_compat & + ~EROFS_FEATURE_COMPAT_SB_CHKSUM), }; const unsigned int sb_blksize = round_up(EROFS_SUPER_END, EROFS_BLKSIZ); @@ -240,6 +248,63 @@ int erofs_mkfs_update_super_block(struct erofs_buffer_head *bh, return 0; } +#define CRC32C_POLY_LE 0x82F63B78 +static inline u32 crc32c(u32 crc, const u8 *in, size_t len) +{ + int i; + + while (len--) { + crc ^= *in++; + for (i = 0; i < 8; i++) + crc = (crc >> 1) ^ ((crc & 1) ? CRC32C_POLY_LE : 0); + } + return crc; +} + +static int erofs_mkfs_superblock_csum_set(void) +{ + int ret; + u8 buf[EROFS_BLKSIZ]; + u32 crc; + struct erofs_super_block *sb; + + ret = blk_read(buf, 0, 1); + if (ret) { + erofs_err("failed to read superblock to set checksum: %s", + erofs_strerror(ret)); + return ret; + } + + /* + * skip the first 1024 bytes, to allow for the installation + * of x86 boot sectors and other oddities. + */ + sb = (struct erofs_super_block *)(buf + EROFS_SUPER_OFFSET); + + if (le32_to_cpu(sb->magic) != EROFS_SUPER_MAGIC_V1) { + erofs_err("internal error: not an erofs valid image"); + return -EFAULT; + } + + /* turn on checksum feature */ + sb->feature_compat = cpu_to_le32(le32_to_cpu(sb->feature_compat) | + EROFS_FEATURE_COMPAT_SB_CHKSUM); + crc = crc32c(~0, (u8 *)sb, EROFS_BLKSIZ - EROFS_SUPER_OFFSET); + + /* set up checksum field to erofs_super_block */ + sb->checksum = cpu_to_le32(crc); + + ret = blk_write(buf, 0, 1); + if (ret) { + erofs_err("failed to write checksummed superblock: %s", + erofs_strerror(ret)); + return ret; + } + + erofs_info("superblock checksum 0x%08x written", crc); + return 0; +} + int main(int argc, char **argv) { int err = 0; @@ -255,6 +320,7 @@ int main(int argc, char **argv) cfg.c_legacy_compress = false; sbi.feature_incompat = EROFS_FEATURE_INCOMPAT_LZ4_0PADDING; + sbi.feature_compat = EROFS_FEATURE_COMPAT_SB_CHKSUM; err = mkfs_parse_options_cfg(argc, argv); if (err) { @@ -337,6 +403,9 @@ int main(int argc, char **argv) err = -EIO; else err = dev_resize(nblocks); + + if (!err && (sbi.feature_compat & EROFS_FEATURE_COMPAT_SB_CHKSUM)) + err = erofs_mkfs_superblock_csum_set(); exit: z_erofs_compress_exit(); dev_close(); |