Commit e6153918 authored by Darrick J. Wong's avatar Darrick J. Wong Committed by Theodore Ts'o

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

Define flags and change structure definitions to allow checksumming of
ext4 metadata.
Signed-off-by: default avatarDarrick J. Wong <djwong@us.ibm.com>
Signed-off-by: default avatar"Theodore Ts'o" <tytso@mit.edu>
parent f8489128
...@@ -298,7 +298,9 @@ struct ext4_group_desc ...@@ -298,7 +298,9 @@ struct ext4_group_desc
__le16 bg_free_inodes_count_lo;/* Free inodes count */ __le16 bg_free_inodes_count_lo;/* Free inodes count */
__le16 bg_used_dirs_count_lo; /* Directories count */ __le16 bg_used_dirs_count_lo; /* Directories count */
__le16 bg_flags; /* EXT4_BG_flags (INODE_UNINIT, etc) */ __le16 bg_flags; /* EXT4_BG_flags (INODE_UNINIT, etc) */
__u32 bg_reserved[2]; /* Likely block/inode bitmap checksum */ __le32 bg_exclude_bitmap_lo; /* Exclude bitmap for snapshots */
__le16 bg_block_bitmap_csum_lo;/* crc32c(s_uuid+grp_num+bbitmap) LE */
__le16 bg_inode_bitmap_csum_lo;/* crc32c(s_uuid+grp_num+ibitmap) LE */
__le16 bg_itable_unused_lo; /* Unused inodes count */ __le16 bg_itable_unused_lo; /* Unused inodes count */
__le16 bg_checksum; /* crc16(sb_uuid+group+desc) */ __le16 bg_checksum; /* crc16(sb_uuid+group+desc) */
__le32 bg_block_bitmap_hi; /* Blocks bitmap block MSB */ __le32 bg_block_bitmap_hi; /* Blocks bitmap block MSB */
...@@ -308,7 +310,10 @@ struct ext4_group_desc ...@@ -308,7 +310,10 @@ struct ext4_group_desc
__le16 bg_free_inodes_count_hi;/* Free inodes count MSB */ __le16 bg_free_inodes_count_hi;/* Free inodes count MSB */
__le16 bg_used_dirs_count_hi; /* Directories count MSB */ __le16 bg_used_dirs_count_hi; /* Directories count MSB */
__le16 bg_itable_unused_hi; /* Unused inodes count MSB */ __le16 bg_itable_unused_hi; /* Unused inodes count MSB */
__u32 bg_reserved2[3]; __le32 bg_exclude_bitmap_hi; /* Exclude bitmap block MSB */
__le16 bg_block_bitmap_csum_hi;/* crc32c(s_uuid+grp_num+bbitmap) BE */
__le16 bg_inode_bitmap_csum_hi;/* crc32c(s_uuid+grp_num+ibitmap) BE */
__u32 bg_reserved;
}; };
/* /*
...@@ -650,7 +655,8 @@ struct ext4_inode { ...@@ -650,7 +655,8 @@ struct ext4_inode {
__le16 l_i_file_acl_high; __le16 l_i_file_acl_high;
__le16 l_i_uid_high; /* these 2 fields */ __le16 l_i_uid_high; /* these 2 fields */
__le16 l_i_gid_high; /* were reserved2[0] */ __le16 l_i_gid_high; /* were reserved2[0] */
__u32 l_i_reserved2; __le16 l_i_checksum_lo;/* crc32c(uuid+inum+inode) LE */
__le16 l_i_reserved;
} linux2; } linux2;
struct { struct {
__le16 h_i_reserved1; /* Obsoleted fragment number/size which are removed in ext4 */ __le16 h_i_reserved1; /* Obsoleted fragment number/size which are removed in ext4 */
...@@ -666,7 +672,7 @@ struct ext4_inode { ...@@ -666,7 +672,7 @@ struct ext4_inode {
} masix2; } masix2;
} osd2; /* OS dependent 2 */ } osd2; /* OS dependent 2 */
__le16 i_extra_isize; __le16 i_extra_isize;
__le16 i_pad1; __le16 i_checksum_hi; /* crc32c(uuid+inum+inode) BE */
__le32 i_ctime_extra; /* extra Change time (nsec << 2 | epoch) */ __le32 i_ctime_extra; /* extra Change time (nsec << 2 | epoch) */
__le32 i_mtime_extra; /* extra Modification time(nsec << 2 | epoch) */ __le32 i_mtime_extra; /* extra Modification time(nsec << 2 | epoch) */
__le32 i_atime_extra; /* extra Access time (nsec << 2 | epoch) */ __le32 i_atime_extra; /* extra Access time (nsec << 2 | epoch) */
...@@ -768,7 +774,7 @@ do { \ ...@@ -768,7 +774,7 @@ do { \
#define i_gid_low i_gid #define i_gid_low i_gid
#define i_uid_high osd2.linux2.l_i_uid_high #define i_uid_high osd2.linux2.l_i_uid_high
#define i_gid_high osd2.linux2.l_i_gid_high #define i_gid_high osd2.linux2.l_i_gid_high
#define i_reserved2 osd2.linux2.l_i_reserved2 #define i_checksum_lo osd2.linux2.l_i_checksum_lo
#elif defined(__GNU__) #elif defined(__GNU__)
...@@ -1001,6 +1007,9 @@ extern void ext4_set_bits(void *bm, int cur, int len); ...@@ -1001,6 +1007,9 @@ extern void ext4_set_bits(void *bm, int cur, int len);
#define EXT4_ERRORS_PANIC 3 /* Panic */ #define EXT4_ERRORS_PANIC 3 /* Panic */
#define EXT4_ERRORS_DEFAULT EXT4_ERRORS_CONTINUE #define EXT4_ERRORS_DEFAULT EXT4_ERRORS_CONTINUE
/* Metadata checksum algorithm codes */
#define EXT4_CRC32C_CHKSUM 1
/* /*
* Structure of the super block * Structure of the super block
*/ */
...@@ -1087,7 +1096,7 @@ struct ext4_super_block { ...@@ -1087,7 +1096,7 @@ struct ext4_super_block {
__le64 s_mmp_block; /* Block for multi-mount protection */ __le64 s_mmp_block; /* Block for multi-mount protection */
__le32 s_raid_stripe_width; /* blocks on all data disks (N*stride)*/ __le32 s_raid_stripe_width; /* blocks on all data disks (N*stride)*/
__u8 s_log_groups_per_flex; /* FLEX_BG group size */ __u8 s_log_groups_per_flex; /* FLEX_BG group size */
__u8 s_reserved_char_pad; __u8 s_checksum_type; /* metadata checksum algorithm used */
__le16 s_reserved_pad; __le16 s_reserved_pad;
__le64 s_kbytes_written; /* nr of lifetime kilobytes written */ __le64 s_kbytes_written; /* nr of lifetime kilobytes written */
__le32 s_snapshot_inum; /* Inode number of active snapshot */ __le32 s_snapshot_inum; /* Inode number of active snapshot */
...@@ -1113,7 +1122,8 @@ struct ext4_super_block { ...@@ -1113,7 +1122,8 @@ struct ext4_super_block {
__le32 s_usr_quota_inum; /* inode for tracking user quota */ __le32 s_usr_quota_inum; /* inode for tracking user quota */
__le32 s_grp_quota_inum; /* inode for tracking group quota */ __le32 s_grp_quota_inum; /* inode for tracking group quota */
__le32 s_overhead_clusters; /* overhead blocks/clusters in fs */ __le32 s_overhead_clusters; /* overhead blocks/clusters in fs */
__le32 s_reserved[109]; /* Padding to the end of the block */ __le32 s_reserved[108]; /* Padding to the end of the block */
__le32 s_checksum; /* crc32c(superblock) */
}; };
#define EXT4_S_ERR_LEN (EXT4_S_ERR_END - EXT4_S_ERR_START) #define EXT4_S_ERR_LEN (EXT4_S_ERR_END - EXT4_S_ERR_START)
...@@ -1414,6 +1424,12 @@ static inline void ext4_clear_state_flags(struct ext4_inode_info *ei) ...@@ -1414,6 +1424,12 @@ static inline void ext4_clear_state_flags(struct ext4_inode_info *ei)
#define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE 0x0040 #define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE 0x0040
#define EXT4_FEATURE_RO_COMPAT_QUOTA 0x0100 #define EXT4_FEATURE_RO_COMPAT_QUOTA 0x0100
#define EXT4_FEATURE_RO_COMPAT_BIGALLOC 0x0200 #define EXT4_FEATURE_RO_COMPAT_BIGALLOC 0x0200
/*
* METADATA_CSUM also enables group descriptor checksums (GDT_CSUM). When
* METADATA_CSUM is set, group descriptor checksums use the same algorithm as
* all other data structures' checksums. However, the METADATA_CSUM and
* GDT_CSUM bits are mutually exclusive.
*/
#define EXT4_FEATURE_RO_COMPAT_METADATA_CSUM 0x0400 #define EXT4_FEATURE_RO_COMPAT_METADATA_CSUM 0x0400
#define EXT4_FEATURE_INCOMPAT_COMPRESSION 0x0001 #define EXT4_FEATURE_INCOMPAT_COMPRESSION 0x0001
...@@ -1526,6 +1542,18 @@ struct ext4_dir_entry_2 { ...@@ -1526,6 +1542,18 @@ struct ext4_dir_entry_2 {
char name[EXT4_NAME_LEN]; /* File name */ char name[EXT4_NAME_LEN]; /* File name */
}; };
/*
* This is a bogus directory entry at the end of each leaf block that
* records checksums.
*/
struct ext4_dir_entry_tail {
__le32 det_reserved_zero1; /* Pretend to be unused */
__le16 det_rec_len; /* 12 */
__u8 det_reserved_zero2; /* Zero name length */
__u8 det_reserved_ft; /* 0xDE, fake file type */
__le32 det_checksum; /* crc32c(uuid+inum+dirblock) */
};
/* /*
* Ext4 directory file types. Only the low 3 bits are used. The * Ext4 directory file types. Only the low 3 bits are used. The
* other bits are reserved for now. * other bits are reserved for now.
...@@ -1541,6 +1569,8 @@ struct ext4_dir_entry_2 { ...@@ -1541,6 +1569,8 @@ struct ext4_dir_entry_2 {
#define EXT4_FT_MAX 8 #define EXT4_FT_MAX 8
#define EXT4_FT_DIR_CSUM 0xDE
/* /*
* EXT4_DIR_PAD defines the directory entries boundaries * EXT4_DIR_PAD defines the directory entries boundaries
* *
...@@ -1741,7 +1771,8 @@ struct mmp_struct { ...@@ -1741,7 +1771,8 @@ struct mmp_struct {
__le16 mmp_check_interval; __le16 mmp_check_interval;
__le16 mmp_pad1; __le16 mmp_pad1;
__le32 mmp_pad2[227]; __le32 mmp_pad2[226];
__le32 mmp_checksum; /* crc32c(uuid+mmp_block) */
}; };
/* arguments passed to the mmp thread */ /* arguments passed to the mmp thread */
......
...@@ -63,8 +63,21 @@ ...@@ -63,8 +63,21 @@
* ext4_inode has i_block array (60 bytes total). * ext4_inode has i_block array (60 bytes total).
* The first 12 bytes store ext4_extent_header; * The first 12 bytes store ext4_extent_header;
* the remainder stores an array of ext4_extent. * the remainder stores an array of ext4_extent.
* For non-inode extent blocks, ext4_extent_tail
* follows the array.
*/ */
/*
* This is the 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 ext4_extent_tail {
__le32 et_checksum; /* crc32c(uuid+inum+extent_block) */
};
/* /*
* This is the extent on-disk structure. * This is the extent on-disk structure.
* It's used at the bottom of the tree. * It's used at the bottom of the tree.
......
...@@ -145,6 +145,14 @@ struct dx_map_entry ...@@ -145,6 +145,14 @@ struct dx_map_entry
u16 size; u16 size;
}; };
/*
* This goes at the end of each htree block.
*/
struct dx_tail {
u32 dt_reserved;
__le32 dt_checksum; /* crc32c(uuid+inum+dirblock) */
};
static inline ext4_lblk_t dx_get_block(struct dx_entry *entry); static inline ext4_lblk_t dx_get_block(struct dx_entry *entry);
static void dx_set_block(struct dx_entry *entry, ext4_lblk_t value); static void dx_set_block(struct dx_entry *entry, ext4_lblk_t value);
static inline unsigned dx_get_hash(struct dx_entry *entry); static inline unsigned dx_get_hash(struct dx_entry *entry);
......
...@@ -27,7 +27,9 @@ struct ext4_xattr_header { ...@@ -27,7 +27,9 @@ struct ext4_xattr_header {
__le32 h_refcount; /* reference count */ __le32 h_refcount; /* reference count */
__le32 h_blocks; /* number of disk blocks used */ __le32 h_blocks; /* number of disk blocks used */
__le32 h_hash; /* hash value of all attributes */ __le32 h_hash; /* hash value of all attributes */
__u32 h_reserved[4]; /* zero right now */ __le32 h_checksum; /* crc32c(uuid+id+xattrblock) */
/* id = inum if refcount=1, blknum otherwise */
__u32 h_reserved[3]; /* zero right now */
}; };
struct ext4_xattr_ibody_header { struct ext4_xattr_ibody_header {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment