libext2fs: change ext4 on-disk layout to support metadata checksumming

Define flags and extend ext4 structure definitions to support metadata
checksumming.  Ted Ts'o covered many of these fields in an earlier
patch, but there are more required changes to the disk layout.

Signed-off-by: Darrick J. Wong <djwong@us.ibm.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
This commit is contained in:
Darrick J. Wong 2012-07-30 17:44:15 -04:00 committed by Theodore Ts'o
parent 91db7e206d
commit 5d914d721a
6 changed files with 55 additions and 4 deletions

View File

@ -110,6 +110,7 @@ struct ext2_super_block {
#define EXT4_FEATURE_RO_COMPAT_DIR_NLINK 0x0020
#define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE 0x0040
#define EXT4_FEATURE_RO_COMPAT_QUOTA 0x0100
#define EXT4_FEATURE_RO_COMPAT_METADATA_CSUM 0x0400
/* for s_feature_incompat */
#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002

View File

@ -20,7 +20,9 @@ struct ext2_ext_attr_header {
__u32 h_refcount; /* reference count */
__u32 h_blocks; /* number of disk blocks used */
__u32 h_hash; /* hash value of all attributes */
__u32 h_reserved[4]; /* zero right now */
__u32 h_checksum; /* crc32c(uuid+id+xattrs) */
/* id = inum if refcount = 1, else blknum */
__u32 h_reserved[3]; /* zero right now */
};
struct ext2_ext_attr_entry {

View File

@ -235,6 +235,13 @@ struct ext2_dx_countlimit {
__u16 count;
};
/*
* This goes at the end of each htree block.
*/
struct ext2_dx_tail {
__u32 dt_reserved;
__u32 dt_checksum; /* crc32c(uuid+inum+dxblock) */
};
/*
* Macro-instructions used to manage group descriptors
@ -464,6 +471,7 @@ struct ext2_inode_large {
#define i_gid_low i_gid
#define i_uid_high osd2.linux2.l_i_uid_high
#define i_gid_high osd2.linux2.l_i_gid_high
#define i_checksum_lo osd2.linux2.l_i_checksum_lo
#else
#if defined(__GNU__)
@ -535,6 +543,9 @@ struct ext2_inode_large {
#define ext4_offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif
/* Metadata checksum algorithms */
#define EXT2_CRC32C_CHKSUM 1
/*
* Structure of the super block
*/
@ -620,7 +631,7 @@ struct ext2_super_block {
__u64 s_mmp_block; /* Block for multi-mount protection */
__u32 s_raid_stripe_width; /* blocks on all data disks (N*stride)*/
__u8 s_log_groups_per_flex; /* FLEX_BG group size */
__u8 s_reserved_char_pad;
__u8 s_checksum_type; /* metadata checksum algorithm */
__u16 s_reserved_pad; /* Padding to next 32bits */
__u64 s_kbytes_written; /* nr of lifetime kilobytes written */
__u32 s_snapshot_inum; /* Inode number of active snapshot */
@ -708,6 +719,11 @@ struct ext2_super_block {
#define EXT4_FEATURE_RO_COMPAT_HAS_SNAPSHOT 0x0080
#define EXT4_FEATURE_RO_COMPAT_QUOTA 0x0100
#define EXT4_FEATURE_RO_COMPAT_BIGALLOC 0x0200
/*
* METADATA_CSUM implies GDT_CSUM. When METADATA_CSUM is set, group
* descriptor checksums use the same algorithm as all other data
* structures' checksums.
*/
#define EXT4_FEATURE_RO_COMPAT_METADATA_CSUM 0x0400
#define EXT4_FEATURE_RO_COMPAT_REPLICA 0x0800
@ -783,6 +799,17 @@ struct ext2_dir_entry_2 {
char name[EXT2_NAME_LEN]; /* File name */
};
/*
* This is a bogus directory entry at the end of each leaf block that
* records checksums.
*/
struct ext2_dir_entry_tail {
__u32 det_reserved_zero1; /* Pretend to be unused */
__u16 det_rec_len; /* 12 */
__u16 det_reserved_name_len; /* 0xDE00, fake namelen/filetype */
__u32 det_checksum; /* crc32c(uuid+inode+dirent) */
};
/*
* Ext2 directory file types. Only the low 3 bits are used. The
* other bits are reserved for now.
@ -798,6 +825,14 @@ struct ext2_dir_entry_2 {
#define EXT2_FT_MAX 8
/*
* Annoyingly, e2fsprogs always swab16s ext2_dir_entry.name_len, so we
* have to build ext2_dir_entry_tail with that assumption too. This
* constant helps to build the dir_entry_tail to look like it has an
* "invalid" file type.
*/
#define EXT2_DIR_NAME_LEN_CSUM 0xDE00
/*
* EXT2_DIR_PAD defines the directory entries boundaries
*
@ -839,7 +874,8 @@ struct mmp_struct {
char mmp_bdevname[32]; /* Bdev which last updated MMP block */
__u16 mmp_check_interval; /* Changed mmp_check_interval */
__u16 mmp_pad1;
__u32 mmp_pad2[227];
__u32 mmp_pad2[226];
__u32 mmp_checksum; /* crc32c(uuid+mmp_block) */
};
/*

View File

@ -185,6 +185,7 @@ typedef struct ext2_file *ext2_file_t;
#define EXT2_FLAG_PRINT_PROGRESS 0x40000
#define EXT2_FLAG_DIRECT_IO 0x80000
#define EXT2_FLAG_SKIP_MMP 0x100000
#define EXT2_FLAG_IGNORE_CSUM_ERRORS 0x200000
/*
* Special flag in the ext2 inode i_flag field that means that this is

View File

@ -18,6 +18,17 @@
* - number of alive extents in the inode
*/
/*
* This is extent tail on-disk structure.
* All other extent structures are 12 bytes long. It turns out that
* block_size % 12 >= 4 for at least all powers of 2 greater than 512, which
* covers all valid ext4 block sizes. Therefore, this tail structure can be
* crammed into the end of the block without having to rebalance the tree.
*/
struct ext3_extent_tail {
__u32 et_checksum; /* crc32c(uuid+inum+extent_block) */
};
/*
* this is extent on-disk structure
* it's used at the bottom of the tree

View File

@ -110,7 +110,7 @@ int main(int argc, char **argv)
check_field(s_mmp_block, 8);
check_field(s_raid_stripe_width, 4);
check_field(s_log_groups_per_flex, 1);
check_field(s_reserved_char_pad, 1);
check_field(s_checksum_type, 1);
check_field(s_reserved_pad, 2);
check_field(s_kbytes_written, 8);
check_field(s_snapshot_inum, 4);