f2fs: support superblock checksum
authorJunling Zheng <zhengjunling@huawei.com>
Fri, 28 Sep 2018 12:25:56 +0000 (20:25 +0800)
committerJaegeuk Kim <jaegeuk@kernel.org>
Mon, 1 Oct 2018 01:34:18 +0000 (18:34 -0700)
Now we support crc32 checksum for superblock.

Reviewed-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Junling Zheng <zhengjunling@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
fs/f2fs/f2fs.h
fs/f2fs/super.c
fs/f2fs/sysfs.c
include/linux/f2fs_fs.h

index 1924367..668836c 100644 (file)
@@ -148,6 +148,7 @@ struct f2fs_mount_info {
 #define F2FS_FEATURE_INODE_CRTIME      0x0100
 #define F2FS_FEATURE_LOST_FOUND                0x0200
 #define F2FS_FEATURE_VERITY            0x0400  /* reserved */
+#define F2FS_FEATURE_SB_CHKSUM         0x0800
 
 #define F2FS_HAS_FEATURE(sb, mask)                                     \
        ((F2FS_SB(sb)->raw_super->feature & cpu_to_le32(mask)) != 0)
@@ -3431,6 +3432,7 @@ F2FS_FEATURE_FUNCS(flexible_inline_xattr, FLEXIBLE_INLINE_XATTR);
 F2FS_FEATURE_FUNCS(quota_ino, QUOTA_INO);
 F2FS_FEATURE_FUNCS(inode_crtime, INODE_CRTIME);
 F2FS_FEATURE_FUNCS(lost_found, LOST_FOUND);
+F2FS_FEATURE_FUNCS(sb_chksum, SB_CHKSUM);
 
 #ifdef CONFIG_BLK_DEV_ZONED
 static inline int get_blkz_type(struct f2fs_sb_info *sbi,
index 218695e..a449132 100644 (file)
@@ -2178,6 +2178,26 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
                                        (bh->b_data + F2FS_SUPER_OFFSET);
        struct super_block *sb = sbi->sb;
        unsigned int blocksize;
+       size_t crc_offset = 0;
+       __u32 crc = 0;
+
+       /* Check checksum_offset and crc in superblock */
+       if (le32_to_cpu(raw_super->feature) & F2FS_FEATURE_SB_CHKSUM) {
+               crc_offset = le32_to_cpu(raw_super->checksum_offset);
+               if (crc_offset !=
+                       offsetof(struct f2fs_super_block, crc)) {
+                       f2fs_msg(sb, KERN_INFO,
+                               "Invalid SB checksum offset: %zu",
+                               crc_offset);
+                       return 1;
+               }
+               crc = le32_to_cpu(raw_super->crc);
+               if (!f2fs_crc_valid(sbi, crc, raw_super, crc_offset)) {
+                       f2fs_msg(sb, KERN_INFO,
+                               "Invalid SB checksum value: %u", crc);
+                       return 1;
+               }
+       }
 
        if (F2FS_SUPER_MAGIC != le32_to_cpu(raw_super->magic)) {
                f2fs_msg(sb, KERN_INFO,
@@ -2635,6 +2655,7 @@ static int read_raw_super_block(struct f2fs_sb_info *sbi,
 int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover)
 {
        struct buffer_head *bh;
+       __u32 crc = 0;
        int err;
 
        if ((recover && f2fs_readonly(sbi->sb)) ||
@@ -2643,6 +2664,13 @@ int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover)
                return -EROFS;
        }
 
+       /* we should update superblock crc here */
+       if (!recover && f2fs_sb_has_sb_chksum(sbi->sb)) {
+               crc = f2fs_crc32(sbi, F2FS_RAW_SUPER(sbi),
+                               offsetof(struct f2fs_super_block, crc));
+               F2FS_RAW_SUPER(sbi)->crc = cpu_to_le32(crc);
+       }
+
        /* write back-up superblock first */
        bh = sb_bread(sbi->sb, sbi->valid_super_block ? 0 : 1);
        if (!bh)
index f5a5454..b777cbd 100644 (file)
@@ -117,6 +117,9 @@ static ssize_t features_show(struct f2fs_attr *a,
        if (f2fs_sb_has_lost_found(sb))
                len += snprintf(buf + len, PAGE_SIZE - len, "%s%s",
                                len ? ", " : "", "lost_found");
+       if (f2fs_sb_has_sb_chksum(sb))
+               len += snprintf(buf + len, PAGE_SIZE - len, "%s%s",
+                               len ? ", " : "", "sb_checksum");
        len += snprintf(buf + len, PAGE_SIZE - len, "\n");
        return len;
 }
@@ -334,6 +337,7 @@ enum feat_id {
        FEAT_QUOTA_INO,
        FEAT_INODE_CRTIME,
        FEAT_LOST_FOUND,
+       FEAT_SB_CHECKSUM,
 };
 
 static ssize_t f2fs_feature_show(struct f2fs_attr *a,
@@ -350,6 +354,7 @@ static ssize_t f2fs_feature_show(struct f2fs_attr *a,
        case FEAT_QUOTA_INO:
        case FEAT_INODE_CRTIME:
        case FEAT_LOST_FOUND:
+       case FEAT_SB_CHECKSUM:
                return snprintf(buf, PAGE_SIZE, "supported\n");
        }
        return 0;
@@ -434,6 +439,7 @@ F2FS_FEATURE_RO_ATTR(flexible_inline_xattr, FEAT_FLEXIBLE_INLINE_XATTR);
 F2FS_FEATURE_RO_ATTR(quota_ino, FEAT_QUOTA_INO);
 F2FS_FEATURE_RO_ATTR(inode_crtime, FEAT_INODE_CRTIME);
 F2FS_FEATURE_RO_ATTR(lost_found, FEAT_LOST_FOUND);
+F2FS_FEATURE_RO_ATTR(sb_checksum, FEAT_SB_CHECKSUM);
 
 #define ATTR_LIST(name) (&f2fs_attr_##name.attr)
 static struct attribute *f2fs_attrs[] = {
@@ -493,6 +499,7 @@ static struct attribute *f2fs_feat_attrs[] = {
        ATTR_LIST(quota_ino),
        ATTR_LIST(inode_crtime),
        ATTR_LIST(lost_found),
+       ATTR_LIST(sb_checksum),
        NULL,
 };
 
index 1d4b196..1db13ff 100644 (file)
@@ -109,7 +109,8 @@ struct f2fs_super_block {
        struct f2fs_device devs[MAX_DEVICES];   /* device list */
        __le32 qf_ino[F2FS_MAX_QUOTAS]; /* quota inode numbers */
        __u8 hot_ext_count;             /* # of hot file extension */
-       __u8 reserved[314];             /* valid reserved region */
+       __u8 reserved[310];             /* valid reserved region */
+       __le32 crc;                     /* checksum of superblock */
 } __packed;
 
 /*