Whamcloud - gitweb
libext2fs: create the block bitmap checksum
authorDarrick J. Wong <djwong@us.ibm.com>
Mon, 30 Jul 2012 23:04:04 +0000 (19:04 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Mon, 30 Jul 2012 23:04:04 +0000 (19:04 -0400)
Calculate and verify the block bitmap checksum.

Signed-off-by: Darrick J. Wong <djwong@us.ibm.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
lib/ext2fs/blknum.c
lib/ext2fs/csum.c
lib/ext2fs/ext2_fs.h
lib/ext2fs/ext2fs.h
lib/ext2fs/rw_bitmaps.c

index 212ad48..b3eef6c 100644 (file)
@@ -203,6 +203,21 @@ static struct ext4_group_desc *ext4fs_group_desc(ext2_filsys fs,
 }
 
 /*
+ * Return the block bitmap checksum of a group
+ */
+__u32 ext2fs_block_bitmap_checksum(ext2_filsys fs, dgrp_t group)
+{
+       struct ext4_group_desc *gdp;
+       __u32 csum;
+
+       gdp = ext4fs_group_desc(fs, fs->group_desc, group);
+       csum = gdp->bg_block_bitmap_csum_lo;
+       if (fs->super->s_desc_size >= EXT4_BG_BLOCK_BITMAP_CSUM_HI_LOCATION)
+               csum |= ((__u32)gdp->bg_block_bitmap_csum_hi << 16);
+       return csum;
+}
+
+/*
  * Return the block bitmap block of a group
  */
 blk64_t ext2fs_block_bitmap_loc(ext2_filsys fs, dgrp_t group)
@@ -239,7 +254,7 @@ __u32 ext2fs_inode_bitmap_checksum(ext2_filsys fs, dgrp_t group)
 
        gdp = ext4fs_group_desc(fs, fs->group_desc, group);
        csum = gdp->bg_inode_bitmap_csum_lo;
-       if (fs->super->s_desc_size < EXT4_BG_INODE_BITMAP_CSUM_HI_END)
+       if (fs->super->s_desc_size >= EXT4_BG_INODE_BITMAP_CSUM_HI_END)
                csum |= ((__u32)gdp->bg_inode_bitmap_csum_hi << 16);
        return csum;
 }
index 951000a..3918a4a 100644 (file)
@@ -70,6 +70,46 @@ errcode_t ext2fs_inode_bitmap_csum_set(ext2_filsys fs, dgrp_t group,
        return 0;
 }
 
+int ext2fs_block_bitmap_csum_verify(ext2_filsys fs, dgrp_t group,
+                                   char *bitmap, int size)
+{
+       struct ext4_group_desc *gdp = (struct ext4_group_desc *)
+                       ext2fs_group_desc(fs, fs->group_desc, group);
+       __u32 provided, calculated;
+
+       if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
+                                       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+               return 1;
+       provided = gdp->bg_block_bitmap_csum_lo;
+       calculated = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)bitmap,
+                                     size);
+       if (fs->super->s_desc_size >= EXT4_BG_BLOCK_BITMAP_CSUM_HI_LOCATION)
+               provided |= (__u32)gdp->bg_block_bitmap_csum_hi << 16;
+       else
+               calculated &= 0xFFFF;
+
+       return provided == calculated;
+}
+
+errcode_t ext2fs_block_bitmap_csum_set(ext2_filsys fs, dgrp_t group,
+                                      char *bitmap, int size)
+{
+       __u32 crc;
+       struct ext4_group_desc *gdp = (struct ext4_group_desc *)
+                       ext2fs_group_desc(fs, fs->group_desc, group);
+
+       if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
+                                       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+               return 0;
+
+       crc = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)bitmap, size);
+       gdp->bg_block_bitmap_csum_lo = crc & 0xFFFF;
+       if (fs->super->s_desc_size >= EXT4_BG_BLOCK_BITMAP_CSUM_HI_LOCATION)
+               gdp->bg_block_bitmap_csum_hi = crc >> 16;
+
+       return 0;
+}
+
 static errcode_t ext2fs_inode_csum(ext2_filsys fs, ext2_ino_t inum,
                               struct ext2_inode_large *inode,
                               __u32 *crc, int has_hi)
index 821e991..2799dc2 100644 (file)
@@ -195,6 +195,9 @@ struct ext4_group_desc
 #define EXT4_BG_INODE_BITMAP_CSUM_HI_END       \
        (offsetof(struct ext4_group_desc, bg_inode_bitmap_csum_hi) + \
         sizeof(__u16))
+#define EXT4_BG_BLOCK_BITMAP_CSUM_HI_LOCATION  \
+       (offsetof(struct ext4_group_desc, bg_block_bitmap_csum_hi) + \
+        sizeof(__u16))
 
 #define EXT2_BG_INODE_UNINIT   0x0001 /* Inode table/bitmap not initialized */
 #define EXT2_BG_BLOCK_UNINIT   0x0002 /* Block bitmap not initialized */
index c423c3b..5f4983f 100644 (file)
@@ -801,6 +801,7 @@ extern errcode_t ext2fs_get_block_bitmap_range2(ext2fs_block_bitmap bmap,
 
 /* blknum.c */
 extern __u32 ext2fs_inode_bitmap_checksum(ext2_filsys fs, dgrp_t group);
+extern __u32 ext2fs_block_bitmap_checksum(ext2_filsys fs, dgrp_t group);
 extern dgrp_t ext2fs_group_of_blk2(ext2_filsys fs, blk64_t);
 extern blk64_t ext2fs_group_first_block2(ext2_filsys fs, dgrp_t group);
 extern blk64_t ext2fs_group_last_block2(ext2_filsys fs, dgrp_t group);
@@ -828,6 +829,7 @@ extern void ext2fs_free_blocks_count_add(struct ext2_super_block *super,
 extern struct ext2_group_desc *ext2fs_group_desc(ext2_filsys fs,
                                          struct opaque_ext2_group_desc *gdp,
                                          dgrp_t group);
+extern blk64_t ext2fs_block_bitmap_csum(ext2_filsys fs, dgrp_t group);
 extern blk64_t ext2fs_block_bitmap_loc(ext2_filsys fs, dgrp_t group);
 extern void ext2fs_block_bitmap_loc_set(ext2_filsys fs, dgrp_t group,
                                        blk64_t blk);
@@ -941,6 +943,10 @@ extern __u32 ext2fs_crc32c_be(__u32 crc, unsigned char const *p, size_t len);
 extern __u32 ext2fs_crc32c_le(__u32 crc, unsigned char const *p, size_t len);
 
 /* csum.c */
+extern errcode_t ext2fs_block_bitmap_csum_set(ext2_filsys fs, dgrp_t group,
+                                             char *bitmap, int size);
+extern int ext2fs_block_bitmap_csum_verify(ext2_filsys fs, dgrp_t group,
+                                          char *bitmap, int size);
 extern errcode_t ext2fs_inode_bitmap_csum_set(ext2_filsys fs, dgrp_t group,
                                              char *bitmap, int size);
 extern int ext2fs_inode_bitmap_csum_verify(ext2_filsys fs, dgrp_t group,
index ea506cb..d58cda4 100644 (file)
@@ -90,6 +90,13 @@ static errcode_t write_bitmaps(ext2_filsys fs, int do_inode, int do_block)
                                for (j = nbits; j < fs->blocksize * 8; j++)
                                        ext2fs_set_bit(j, block_buf);
                }
+
+               retval = ext2fs_block_bitmap_csum_set(fs, i, block_buf,
+                                                     block_nbytes);
+               if (retval)
+                       return retval;
+               ext2fs_group_desc_csum_set(fs, i);
+
                blk = ext2fs_block_bitmap_loc(fs, i);
                if (blk) {
                        retval = io_channel_write_blk64(fs->io, blk, 1,
@@ -266,6 +273,15 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
                                        retval = EXT2_ET_BLOCK_BITMAP_READ;
                                        goto cleanup;
                                }
+                               /* verify block bitmap checksum */
+                               if (!(fs->flags &
+                                     EXT2_FLAG_IGNORE_CSUM_ERRORS) &&
+                                   !ext2fs_block_bitmap_csum_verify(fs, i,
+                                               block_bitmap, block_nbytes)) {
+                                       retval =
+                                       EXT2_ET_BLOCK_BITMAP_READ;
+                                       goto cleanup;
+                               }
                        } else
                                memset(block_bitmap, 0, block_nbytes);
                        cnt = block_nbytes << 3;