This patch adds a new feature 'node_checksum' which will be only enabled
with 'extended_node' feature, with it, we can do non-inode checksum
verification in both kernel and userspace side.

Signed-off-by: Chao Yu <[email protected]>
---
 fsck/dir.c              |  2 +-
 fsck/f2fs.h             |  5 ++++
 fsck/fsck.c             | 74 ++++++++++++++++++++++++++++++++++++++++++++++++-
 fsck/mount.c            |  3 ++
 fsck/segment.c          |  2 +-
 include/f2fs_fs.h       | 13 +++++++--
 lib/libf2fs.c           | 22 +++++++++------
 mkfs/f2fs_format.c      |  4 +--
 mkfs/f2fs_format_main.c |  4 +++
 9 files changed, 113 insertions(+), 16 deletions(-)

diff --git a/fsck/dir.c b/fsck/dir.c
index b2ea18f083fb..c6bab894895e 100644
--- a/fsck/dir.c
+++ b/fsck/dir.c
@@ -455,7 +455,7 @@ static void init_inode_block(struct f2fs_sb_info *sbi,
 
        if (c.feature & cpu_to_le32(F2FS_FEATURE_INODE_CHKSUM))
                node_blk->i.i_inode_checksum =
-                       cpu_to_le32(f2fs_inode_chksum(node_blk));
+                       cpu_to_le32(f2fs_node_chksum(node_blk));
 }
 
 int convert_inline_dentry(struct f2fs_sb_info *sbi, struct f2fs_node *node,
diff --git a/fsck/f2fs.h b/fsck/f2fs.h
index 8a5ce365282d..a1de45abb3a1 100644
--- a/fsck/f2fs.h
+++ b/fsck/f2fs.h
@@ -456,6 +456,11 @@ static inline int inline_xattr_size(struct f2fs_inode 
*inode)
        return get_inline_xattr_addrs(inode) * sizeof(__le32);
 }
 
+#define F2FS_FITS_IN_NODE(extra_nsize, field)          \
+               ((offsetof(struct f2fs_node, footer) -  \
+               offsetof(struct f2fs_node, field))      \
+               <= (extra_nsize))                       \
+
 extern int lookup_nat_in_journal(struct f2fs_sb_info *sbi, u32 nid, struct 
f2fs_nat_entry *ne);
 #define IS_SUM_NODE_SEG(footer)                (footer.entry_type == 
SUM_TYPE_NODE)
 #define IS_SUM_DATA_SEG(footer)                (footer.entry_type == 
SUM_TYPE_DATA)
diff --git a/fsck/fsck.c b/fsck/fsck.c
index 6c1b9a735754..98321186991b 100644
--- a/fsck/fsck.c
+++ b/fsck/fsck.c
@@ -933,7 +933,7 @@ skip_blkcnt_fix:
                __u32 provided, calculated;
 
                provided = le32_to_cpu(node_blk->i.i_inode_checksum);
-               calculated = f2fs_inode_chksum(node_blk);
+               calculated = f2fs_node_chksum(node_blk);
 
                if (provided != calculated) {
                        ASSERT_MSG("ino: 0x%x chksum:0x%x, but calculated one 
is: 0x%x",
@@ -983,6 +983,31 @@ int fsck_chk_dnode_blk(struct f2fs_sb_info *sbi, struct 
f2fs_inode *inode,
                        FIX_MSG("[0x%x] dn.addr[%d] = 0", nid, idx);
                }
        }
+
+       if ((c.feature & cpu_to_le32(F2FS_FEATURE_EXTENDED_NODE)) &&
+                       F2FS_FITS_IN_NODE(c.extra_nsize, node_checksum)) {
+               __u32 provided, calculated;
+
+               provided = le32_to_cpu(node_blk->node_checksum);
+               calculated = f2fs_node_chksum(node_blk);
+
+               if (provided != calculated) {
+                       ASSERT_MSG("ino: 0x%x, nid: 0x%x, chksum:0x%x, but 
calculated one is: 0x%x",
+                               le32_to_cpu(node_blk->footer.ino),
+                               le32_to_cpu(node_blk->footer.nid),
+                               provided, calculated);
+                       if (c.fix_on) {
+                               node_blk->node_checksum =
+                                                       cpu_to_le32(calculated);
+                               need_fix = 1;
+                               FIX_MSG("ino: 0x%x, nid: 0x%x, recover 
node_checksum= 0x%x -> 0x%x",
+                                       le32_to_cpu(node_blk->footer.ino),
+                                       le32_to_cpu(node_blk->footer.nid),
+                                       provided, calculated);
+                       }
+               }
+       }
+
        if (need_fix && !c.ro) {
                ret = dev_write_block(node_blk, ni->blk_addr);
                ASSERT(ret >= 0);
@@ -1018,6 +1043,30 @@ skip:
                }
        }
 
+       if ((c.feature & cpu_to_le32(F2FS_FEATURE_EXTENDED_NODE)) &&
+                       F2FS_FITS_IN_NODE(c.extra_nsize, node_checksum)) {
+               __u32 provided, calculated;
+
+               provided = le32_to_cpu(node_blk->node_checksum);
+               calculated = f2fs_node_chksum(node_blk);
+
+               if (provided != calculated) {
+                       ASSERT_MSG("ino: 0x%x, nid: 0x%x, chksum:0x%x, but 
calculated one is: 0x%x",
+                               le32_to_cpu(node_blk->footer.ino),
+                               le32_to_cpu(node_blk->footer.nid),
+                               provided, calculated);
+                       if (c.fix_on) {
+                               node_blk->node_checksum =
+                                                       cpu_to_le32(calculated);
+                               need_fix = 1;
+                               FIX_MSG("ino: 0x%x, nid: 0x%x, recover 
node_checksum= 0x%x -> 0x%x",
+                                       le32_to_cpu(node_blk->footer.ino),
+                                       le32_to_cpu(node_blk->footer.nid),
+                                       provided, calculated);
+                       }
+               }
+       }
+
        if (need_fix && !c.ro) {
                struct node_info ni;
                nid_t nid = le32_to_cpu(node_blk->footer.nid);
@@ -1058,6 +1107,29 @@ skip:
                }
        }
 
+       if ((c.feature & cpu_to_le32(F2FS_FEATURE_EXTENDED_NODE)) &&
+                       F2FS_FITS_IN_NODE(c.extra_nsize, node_checksum)) {
+               __u32 provided, calculated;
+
+               provided = le32_to_cpu(node_blk->node_checksum);
+               calculated = f2fs_node_chksum(node_blk);
+
+               if (provided != calculated) {
+                       ASSERT_MSG("ino: 0x%x, nid: 0x%x, chksum:0x%x, but 
calculated one is: 0x%x",
+                               le32_to_cpu(node_blk->footer.ino),
+                               le32_to_cpu(node_blk->footer.nid),
+                               provided, calculated);
+                       if (c.fix_on) {
+                               node_blk->node_checksum =
+                                                       cpu_to_le32(calculated);
+                               need_fix = 1;
+                               FIX_MSG("ino: 0x%x, nid: 0x%x, recover 
node_checksum= 0x%x -> 0x%x",
+                                       le32_to_cpu(node_blk->footer.ino),
+                                       le32_to_cpu(node_blk->footer.nid),
+                                       provided, calculated);
+                       }
+               }
+       }
        if (need_fix && !c.ro) {
                struct node_info ni;
                nid_t nid = le32_to_cpu(node_blk->footer.nid);
diff --git a/fsck/mount.c b/fsck/mount.c
index 016e52471f11..0a99017b2aed 100644
--- a/fsck/mount.c
+++ b/fsck/mount.c
@@ -463,6 +463,9 @@ void print_sb_state(struct f2fs_super_block *sb)
        if (f & cpu_to_le32(F2FS_FEATURE_EXTENDED_NODE)) {
                MSG(0, "%s", " extended_node");
        }
+       if (f & cpu_to_le32(F2FS_FEATURE_NODE_CHECKSUM)) {
+               MSG(0, "%s", " node_checksum");
+       }
        MSG(0, "\n");
        MSG(0, "Info: superblock encrypt level = %d, salt = ",
                                        sb->encryption_level);
diff --git a/fsck/segment.c b/fsck/segment.c
index 4f8bdb4cbedd..0c4b93fd4e27 100644
--- a/fsck/segment.c
+++ b/fsck/segment.c
@@ -20,7 +20,7 @@ static void write_inode(u64 blkaddr, struct f2fs_node *inode)
 {
        if (c.feature & cpu_to_le32(F2FS_FEATURE_INODE_CHKSUM))
                inode->i.i_inode_checksum =
-                       cpu_to_le32(f2fs_inode_chksum(inode));
+                       cpu_to_le32(f2fs_node_chksum(inode));
        ASSERT(dev_write_block(inode, blkaddr) >= 0);
 }
 
diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h
index 1692cd5433ca..c92860d68c86 100644
--- a/include/f2fs_fs.h
+++ b/include/f2fs_fs.h
@@ -554,6 +554,7 @@ enum {
 #define F2FS_FEATURE_QUOTA_INO         0x0080
 #define F2FS_FEATURE_INODE_CRTIME      0x0100
 #define F2FS_FEATURE_EXTENDED_NODE     0x0200
+#define F2FS_FEATURE_NODE_CHECKSUM     0x0400
 
 #define MAX_VOLUME_NAME                512
 
@@ -847,8 +848,14 @@ struct f2fs_node {
        /* can be one of three types: inode, direct, and indirect types */
        union {
                struct f2fs_inode i;
-               struct direct_node dn;
-               struct indirect_node in;
+               union {
+                       struct {
+                               __le32 data[1017];
+                               __le32 node_checksum;
+                       };
+                       struct direct_node dn;
+                       struct indirect_node in;
+               };
        };
        struct node_footer footer;
 } __attribute__((packed));
@@ -1163,7 +1170,7 @@ extern int utf8_to_utf16(u_int16_t *, const char *, 
size_t, size_t);
 extern int utf16_to_utf8(char *, const u_int16_t *, size_t, size_t);
 extern int log_base_2(u_int32_t);
 extern unsigned int addrs_per_inode(struct f2fs_inode *);
-extern __u32 f2fs_inode_chksum(struct f2fs_node *);
+extern __u32 f2fs_node_chksum(struct f2fs_node *);
 
 extern int get_bits_in_byte(unsigned char n);
 extern int test_and_set_bit_le(u32, u8 *);
diff --git a/lib/libf2fs.c b/lib/libf2fs.c
index 61962cf7d461..5ca416e3ddb0 100644
--- a/lib/libf2fs.c
+++ b/lib/libf2fs.c
@@ -506,19 +506,25 @@ int f2fs_crc_valid(u_int32_t blk_crc, void *buf, int len)
        return 0;
 }
 
-__u32 f2fs_inode_chksum(struct f2fs_node *node)
+__u32 f2fs_node_chksum(struct f2fs_node *node)
 {
        struct f2fs_inode *ri = &node->i;
-       __le32 ino = node->footer.ino;
-       __le32 gen = ri->i_generation;
-       __u32 chksum, chksum_seed;
-       __u32 dummy_cs = 0;
-       unsigned int offset = offsetof(struct f2fs_inode, i_inode_checksum);
-       unsigned int cs_size = sizeof(dummy_cs);
+       __le32 append, ino = node->footer.ino;
+       __u32 chksum, chksum_seed, dummy_cs = 0;
+       unsigned int offset, cs_size = sizeof(dummy_cs);
+       bool is_inode = node->footer.nid == node->footer.ino;
+
+       if (is_inode) {
+               append = node->i.i_generation;
+               offset = offsetof(struct f2fs_inode, i_inode_checksum);
+       } else {
+               append = node->footer.nid;
+               offset = offsetof(struct f2fs_node, node_checksum);
+       }
 
        chksum = f2fs_cal_crc32(c.chksum_seed, (__u8 *)&ino,
                                                        sizeof(ino));
-       chksum_seed = f2fs_cal_crc32(chksum, (__u8 *)&gen, sizeof(gen));
+       chksum_seed = f2fs_cal_crc32(chksum, (__u8 *)&append, sizeof(append));
 
        chksum = f2fs_cal_crc32(chksum_seed, (__u8 *)ri, offset);
        chksum = f2fs_cal_crc32(chksum, (__u8 *)&dummy_cs, cs_size);
diff --git a/mkfs/f2fs_format.c b/mkfs/f2fs_format.c
index 51337b53a795..26a82ebe2768 100644
--- a/mkfs/f2fs_format.c
+++ b/mkfs/f2fs_format.c
@@ -1063,7 +1063,7 @@ static int f2fs_write_root_inode(void)
 
        if (c.feature & cpu_to_le32(F2FS_FEATURE_INODE_CHKSUM))
                raw_node->i.i_inode_checksum =
-                       cpu_to_le32(f2fs_inode_chksum(raw_node));
+                       cpu_to_le32(f2fs_node_chksum(raw_node));
 
        main_area_node_seg_blk_offset = get_sb(main_blkaddr);
        main_area_node_seg_blk_offset += c.cur_seg[CURSEG_HOT_NODE] *
@@ -1239,7 +1239,7 @@ static int f2fs_write_qf_inode(int qtype)
 
        if (c.feature & cpu_to_le32(F2FS_FEATURE_INODE_CHKSUM))
                raw_node->i.i_inode_checksum =
-                       cpu_to_le32(f2fs_inode_chksum(raw_node));
+                       cpu_to_le32(f2fs_node_chksum(raw_node));
 
        main_area_node_seg_blk_offset = get_sb(main_blkaddr);
        main_area_node_seg_blk_offset += c.cur_seg[CURSEG_HOT_NODE] *
diff --git a/mkfs/f2fs_format_main.c b/mkfs/f2fs_format_main.c
index 93922b0af068..46a6335e833e 100644
--- a/mkfs/f2fs_format_main.c
+++ b/mkfs/f2fs_format_main.c
@@ -97,6 +97,10 @@ static void parse_feature(const char *features)
                c.feature |= cpu_to_le32(F2FS_FEATURE_INODE_CRTIME);
        } else if (!strcmp(features, "extended_node")) {
                c.feature |= cpu_to_le32(F2FS_FEATURE_EXTENDED_NODE);
+       } else if (!strcmp(features, "node_checksum")) {
+               c.feature |= cpu_to_le32(F2FS_FEATURE_NODE_CHECKSUM);
+               c.extra_nsize = offsetof(struct f2fs_node, footer) -
+                               offsetof(struct f2fs_node, node_checksum);
        } else {
                MSG(0, "Error: Wrong features\n");
                mkfs_usage();
-- 
2.15.0.55.gc2ece9dc4de6


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Linux-f2fs-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

Reply via email to