Refactoring superblock features getters
[lwext4.git] / lwext4 / ext4_super.c
index 0258ca79750e8510cb6af20a3340fff2ed03b267..bcb460a904541429d6a5b64993f75affb6b1e3d2 100644 (file)
@@ -41,6 +41,7 @@
 
 #include "ext4_config.h"
 #include "ext4_super.h"
+#include "ext4_crc32c.h"
 
 uint32_t ext4_block_group_cnt(struct ext4_sblock *s)
 {
@@ -79,8 +80,34 @@ uint32_t ext4_inodes_in_group_cnt(struct ext4_sblock *s, uint32_t bgid)
        return (total_inodes - ((block_group_count - 1) * inodes_per_group));
 }
 
+static uint32_t ext4_sb_csum(struct ext4_sblock *s)
+{
+       return ext4_crc32c(~0, s,
+                       ext4_offsetof(struct ext4_sblock, checksum));
+}
+
+static bool ext4_sb_verify_csum(struct ext4_sblock *s)
+{
+       if (!ext4_sb_feature_ro_com(s, EXT4_FRO_COM_METADATA_CSUM))
+               return true;
+
+       if (s->checksum_type != to_le32(EXT4_CHECKSUM_CRC32C))
+               return false;
+
+       return s->checksum == to_le32(ext4_sb_csum(s));
+}
+
+static void ext4_sb_set_csum(struct ext4_sblock *s)
+{
+       if (!ext4_sb_feature_ro_com(s, EXT4_FRO_COM_METADATA_CSUM))
+               return;
+
+       s->checksum = to_le32(ext4_sb_csum(s));
+}
+
 int ext4_sb_write(struct ext4_blockdev *bdev, struct ext4_sblock *s)
 {
+       ext4_sb_set_csum(s);
        return ext4_block_writebytes(bdev, EXT4_SUPERBLOCK_OFFSET, s,
                                     EXT4_SUPERBLOCK_SIZE);
 }
@@ -120,10 +147,13 @@ bool ext4_sb_check(struct ext4_sblock *s)
        if (ext4_sb_get_desc_size(s) > EXT4_MAX_BLOCK_GROUP_DESCRIPTOR_SIZE)
                return false;
 
+       if (!ext4_sb_verify_csum(s))
+               return false;
+
        return true;
 }
 
-static inline int is_multiple(uint32_t a, uint32_t b)
+static inline int is_power_of(uint32_t a, uint32_t b)
 {
        while (1) {
                if (a < b)
@@ -136,7 +166,7 @@ static inline int is_multiple(uint32_t a, uint32_t b)
        }
 }
 
-static int ext4_sb_sparse(uint32_t group)
+bool ext4_sb_sparse(uint32_t group)
 {
        if (group <= 1)
                return 1;
@@ -144,14 +174,13 @@ static int ext4_sb_sparse(uint32_t group)
        if (!(group & 1))
                return 0;
 
-       return (is_multiple(group, 7) || is_multiple(group, 5) ||
-               is_multiple(group, 3));
+       return (is_power_of(group, 7) || is_power_of(group, 5) ||
+               is_power_of(group, 3));
 }
 
 bool ext4_sb_is_super_in_bg(struct ext4_sblock *s, uint32_t group)
 {
-       if (ext4_sb_has_feature_read_only(
-               s, EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER) &&
+       if (ext4_sb_feature_ro_com(s, EXT4_FRO_COM_SPARSE_SUPER) &&
            !ext4_sb_sparse(group))
                return false;
        return true;
@@ -181,7 +210,7 @@ static uint32_t ext4_bg_num_gdb_nometa(struct ext4_sblock *s, uint32_t group)
        uint32_t db_count =
            (ext4_block_group_cnt(s) + dsc_per_block - 1) / dsc_per_block;
 
-       if (ext4_sb_has_feature_incompatible(s, EXT4_FEATURE_INCOMPAT_META_BG))
+       if (ext4_sb_feature_incom(s, EXT4_FINCOM_META_BG))
                return ext4_sb_first_meta_bg(s);
 
        return db_count;
@@ -194,8 +223,7 @@ uint32_t ext4_bg_num_gdb(struct ext4_sblock *s, uint32_t group)
        uint32_t first_meta_bg = ext4_sb_first_meta_bg(s);
        uint32_t metagroup = group / dsc_per_block;
 
-       if (!ext4_sb_has_feature_incompatible(s,
-                                             EXT4_FEATURE_INCOMPAT_META_BG) ||
+       if (!ext4_sb_feature_incom(s,EXT4_FINCOM_META_BG) ||
            metagroup < first_meta_bg)
                return ext4_bg_num_gdb_nometa(s, group);
 
@@ -211,8 +239,7 @@ uint32_t ext4_num_base_meta_clusters(struct ext4_sblock *s,
 
        num = ext4_sb_is_super_in_bg(s, block_group);
 
-       if (!ext4_sb_has_feature_incompatible(s,
-                                             EXT4_FEATURE_INCOMPAT_META_BG) ||
+       if (!ext4_sb_feature_incom(s, EXT4_FINCOM_META_BG) ||
            block_group < ext4_sb_first_meta_bg(s) * dsc_per_block) {
                if (num) {
                        num += ext4_bg_num_gdb(s, block_group);