]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
erofs: micro-optimize superblock checksum
authorGao Xiang <hsiangkao@linux.alibaba.com>
Thu, 12 Dec 2024 02:39:48 +0000 (10:39 +0800)
committerGao Xiang <hsiangkao@linux.alibaba.com>
Thu, 16 Jan 2025 19:17:32 +0000 (03:17 +0800)
Just verify the remaining unknown on-disk data instead of allocating a
temporary buffer for the whole superblock and zeroing out the checksum
field since .magic(EROFS_SUPER_MAGIC_V1) is verified and .checksum(0)
is fixed.

Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
Link: https://lore.kernel.org/r/20241212023948.1143038-1-hsiangkao@linux.alibaba.com
fs/erofs/erofs_fs.h
fs/erofs/super.c

index c8f2ae845bd29e84a5bf2739f49971370f8db15a..199395ed1c1f9b0852d6596c4ce8bb235a8432f4 100644 (file)
@@ -9,6 +9,7 @@
 #ifndef __EROFS_FS_H
 #define __EROFS_FS_H
 
+/* to allow for x86 boot sectors and other oddities. */
 #define EROFS_SUPER_OFFSET      1024
 
 #define EROFS_FEATURE_COMPAT_SB_CHKSUM          0x00000001
@@ -54,7 +55,7 @@ struct erofs_deviceslot {
 /* erofs on-disk super block (currently 128 bytes) */
 struct erofs_super_block {
        __le32 magic;           /* file system magic number */
-       __le32 checksum;        /* crc32c(super_block) */
+       __le32 checksum;        /* crc32c to avoid unexpected on-disk overlap */
        __le32 feature_compat;
        __u8 blkszbits;         /* filesystem block size in bit shift */
        __u8 sb_extslots;       /* superblock size = 128 + sb_extslots * 16 */
index f5956474bfdea30bc518f965d5b4e1d400648df1..1fc5623c3a4d429296a677c9b5695d714d9880c6 100644 (file)
@@ -39,29 +39,21 @@ void _erofs_printk(struct super_block *sb, const char *fmt, ...)
 
 static int erofs_superblock_csum_verify(struct super_block *sb, void *sbdata)
 {
-       size_t len = 1 << EROFS_SB(sb)->blkszbits;
-       struct erofs_super_block *dsb;
-       u32 expected_crc, crc;
+       struct erofs_super_block *dsb = sbdata + EROFS_SUPER_OFFSET;
+       u32 len = 1 << EROFS_SB(sb)->blkszbits, crc;
 
        if (len > EROFS_SUPER_OFFSET)
                len -= EROFS_SUPER_OFFSET;
+       len -= offsetof(struct erofs_super_block, checksum) +
+                       sizeof(dsb->checksum);
 
-       dsb = kmemdup(sbdata + EROFS_SUPER_OFFSET, len, GFP_KERNEL);
-       if (!dsb)
-               return -ENOMEM;
-
-       expected_crc = le32_to_cpu(dsb->checksum);
-       dsb->checksum = 0;
-       /* to allow for x86 boot sectors and other oddities. */
-       crc = crc32c(~0, dsb, len);
-       kfree(dsb);
-
-       if (crc != expected_crc) {
-               erofs_err(sb, "invalid checksum 0x%08x, 0x%08x expected",
-                         crc, expected_crc);
-               return -EBADMSG;
-       }
-       return 0;
+       /* skip .magic(pre-verified) and .checksum(0) fields */
+       crc = crc32c(0x5045B54A, (&dsb->checksum) + 1, len);
+       if (crc == le32_to_cpu(dsb->checksum))
+               return 0;
+       erofs_err(sb, "invalid checksum 0x%08x, 0x%08x expected",
+                 crc, le32_to_cpu(dsb->checksum));
+       return -EBADMSG;
 }
 
 static void erofs_inode_init_once(void *ptr)