diff options
author | Darrick J. Wong <djwong@us.ibm.com> | 2012-04-29 18:23:10 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2012-04-29 18:23:10 -0400 |
commit | e615391896064eb5a0c760d086b8e1c6ecfffeab (patch) | |
tree | 1d05a5e925579bc444468d88eacca00d633b8286 | |
parent | f84891289e62a74e9b4942eaad80617368b2d778 (diff) |
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: Darrick J. Wong <djwong@us.ibm.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
-rw-r--r-- | fs/ext4/ext4.h | 47 | ||||
-rw-r--r-- | fs/ext4/ext4_extents.h | 13 | ||||
-rw-r--r-- | fs/ext4/namei.c | 8 | ||||
-rw-r--r-- | fs/ext4/xattr.h | 4 |
4 files changed, 63 insertions, 9 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 0e01e90add8b..61dd739b64f0 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -298,7 +298,9 @@ struct ext4_group_desc | |||
298 | __le16 bg_free_inodes_count_lo;/* Free inodes count */ | 298 | __le16 bg_free_inodes_count_lo;/* Free inodes count */ |
299 | __le16 bg_used_dirs_count_lo; /* Directories count */ | 299 | __le16 bg_used_dirs_count_lo; /* Directories count */ |
300 | __le16 bg_flags; /* EXT4_BG_flags (INODE_UNINIT, etc) */ | 300 | __le16 bg_flags; /* EXT4_BG_flags (INODE_UNINIT, etc) */ |
301 | __u32 bg_reserved[2]; /* Likely block/inode bitmap checksum */ | 301 | __le32 bg_exclude_bitmap_lo; /* Exclude bitmap for snapshots */ |
302 | __le16 bg_block_bitmap_csum_lo;/* crc32c(s_uuid+grp_num+bbitmap) LE */ | ||
303 | __le16 bg_inode_bitmap_csum_lo;/* crc32c(s_uuid+grp_num+ibitmap) LE */ | ||
302 | __le16 bg_itable_unused_lo; /* Unused inodes count */ | 304 | __le16 bg_itable_unused_lo; /* Unused inodes count */ |
303 | __le16 bg_checksum; /* crc16(sb_uuid+group+desc) */ | 305 | __le16 bg_checksum; /* crc16(sb_uuid+group+desc) */ |
304 | __le32 bg_block_bitmap_hi; /* Blocks bitmap block MSB */ | 306 | __le32 bg_block_bitmap_hi; /* Blocks bitmap block MSB */ |
@@ -308,7 +310,10 @@ struct ext4_group_desc | |||
308 | __le16 bg_free_inodes_count_hi;/* Free inodes count MSB */ | 310 | __le16 bg_free_inodes_count_hi;/* Free inodes count MSB */ |
309 | __le16 bg_used_dirs_count_hi; /* Directories count MSB */ | 311 | __le16 bg_used_dirs_count_hi; /* Directories count MSB */ |
310 | __le16 bg_itable_unused_hi; /* Unused inodes count MSB */ | 312 | __le16 bg_itable_unused_hi; /* Unused inodes count MSB */ |
311 | __u32 bg_reserved2[3]; | 313 | __le32 bg_exclude_bitmap_hi; /* Exclude bitmap block MSB */ |
314 | __le16 bg_block_bitmap_csum_hi;/* crc32c(s_uuid+grp_num+bbitmap) BE */ | ||
315 | __le16 bg_inode_bitmap_csum_hi;/* crc32c(s_uuid+grp_num+ibitmap) BE */ | ||
316 | __u32 bg_reserved; | ||
312 | }; | 317 | }; |
313 | 318 | ||
314 | /* | 319 | /* |
@@ -650,7 +655,8 @@ struct ext4_inode { | |||
650 | __le16 l_i_file_acl_high; | 655 | __le16 l_i_file_acl_high; |
651 | __le16 l_i_uid_high; /* these 2 fields */ | 656 | __le16 l_i_uid_high; /* these 2 fields */ |
652 | __le16 l_i_gid_high; /* were reserved2[0] */ | 657 | __le16 l_i_gid_high; /* were reserved2[0] */ |
653 | __u32 l_i_reserved2; | 658 | __le16 l_i_checksum_lo;/* crc32c(uuid+inum+inode) LE */ |
659 | __le16 l_i_reserved; | ||
654 | } linux2; | 660 | } linux2; |
655 | struct { | 661 | struct { |
656 | __le16 h_i_reserved1; /* Obsoleted fragment number/size which are removed in ext4 */ | 662 | __le16 h_i_reserved1; /* Obsoleted fragment number/size which are removed in ext4 */ |
@@ -666,7 +672,7 @@ struct ext4_inode { | |||
666 | } masix2; | 672 | } masix2; |
667 | } osd2; /* OS dependent 2 */ | 673 | } osd2; /* OS dependent 2 */ |
668 | __le16 i_extra_isize; | 674 | __le16 i_extra_isize; |
669 | __le16 i_pad1; | 675 | __le16 i_checksum_hi; /* crc32c(uuid+inum+inode) BE */ |
670 | __le32 i_ctime_extra; /* extra Change time (nsec << 2 | epoch) */ | 676 | __le32 i_ctime_extra; /* extra Change time (nsec << 2 | epoch) */ |
671 | __le32 i_mtime_extra; /* extra Modification time(nsec << 2 | epoch) */ | 677 | __le32 i_mtime_extra; /* extra Modification time(nsec << 2 | epoch) */ |
672 | __le32 i_atime_extra; /* extra Access time (nsec << 2 | epoch) */ | 678 | __le32 i_atime_extra; /* extra Access time (nsec << 2 | epoch) */ |
@@ -768,7 +774,7 @@ do { \ | |||
768 | #define i_gid_low i_gid | 774 | #define i_gid_low i_gid |
769 | #define i_uid_high osd2.linux2.l_i_uid_high | 775 | #define i_uid_high osd2.linux2.l_i_uid_high |
770 | #define i_gid_high osd2.linux2.l_i_gid_high | 776 | #define i_gid_high osd2.linux2.l_i_gid_high |
771 | #define i_reserved2 osd2.linux2.l_i_reserved2 | 777 | #define i_checksum_lo osd2.linux2.l_i_checksum_lo |
772 | 778 | ||
773 | #elif defined(__GNU__) | 779 | #elif defined(__GNU__) |
774 | 780 | ||
@@ -1001,6 +1007,9 @@ extern void ext4_set_bits(void *bm, int cur, int len); | |||
1001 | #define EXT4_ERRORS_PANIC 3 /* Panic */ | 1007 | #define EXT4_ERRORS_PANIC 3 /* Panic */ |
1002 | #define EXT4_ERRORS_DEFAULT EXT4_ERRORS_CONTINUE | 1008 | #define EXT4_ERRORS_DEFAULT EXT4_ERRORS_CONTINUE |
1003 | 1009 | ||
1010 | /* Metadata checksum algorithm codes */ | ||
1011 | #define EXT4_CRC32C_CHKSUM 1 | ||
1012 | |||
1004 | /* | 1013 | /* |
1005 | * Structure of the super block | 1014 | * Structure of the super block |
1006 | */ | 1015 | */ |
@@ -1087,7 +1096,7 @@ struct ext4_super_block { | |||
1087 | __le64 s_mmp_block; /* Block for multi-mount protection */ | 1096 | __le64 s_mmp_block; /* Block for multi-mount protection */ |
1088 | __le32 s_raid_stripe_width; /* blocks on all data disks (N*stride)*/ | 1097 | __le32 s_raid_stripe_width; /* blocks on all data disks (N*stride)*/ |
1089 | __u8 s_log_groups_per_flex; /* FLEX_BG group size */ | 1098 | __u8 s_log_groups_per_flex; /* FLEX_BG group size */ |
1090 | __u8 s_reserved_char_pad; | 1099 | __u8 s_checksum_type; /* metadata checksum algorithm used */ |
1091 | __le16 s_reserved_pad; | 1100 | __le16 s_reserved_pad; |
1092 | __le64 s_kbytes_written; /* nr of lifetime kilobytes written */ | 1101 | __le64 s_kbytes_written; /* nr of lifetime kilobytes written */ |
1093 | __le32 s_snapshot_inum; /* Inode number of active snapshot */ | 1102 | __le32 s_snapshot_inum; /* Inode number of active snapshot */ |
@@ -1113,7 +1122,8 @@ struct ext4_super_block { | |||
1113 | __le32 s_usr_quota_inum; /* inode for tracking user quota */ | 1122 | __le32 s_usr_quota_inum; /* inode for tracking user quota */ |
1114 | __le32 s_grp_quota_inum; /* inode for tracking group quota */ | 1123 | __le32 s_grp_quota_inum; /* inode for tracking group quota */ |
1115 | __le32 s_overhead_clusters; /* overhead blocks/clusters in fs */ | 1124 | __le32 s_overhead_clusters; /* overhead blocks/clusters in fs */ |
1116 | __le32 s_reserved[109]; /* Padding to the end of the block */ | 1125 | __le32 s_reserved[108]; /* Padding to the end of the block */ |
1126 | __le32 s_checksum; /* crc32c(superblock) */ | ||
1117 | }; | 1127 | }; |
1118 | 1128 | ||
1119 | #define EXT4_S_ERR_LEN (EXT4_S_ERR_END - EXT4_S_ERR_START) | 1129 | #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 | #define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE 0x0040 | 1424 | #define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE 0x0040 |
1415 | #define EXT4_FEATURE_RO_COMPAT_QUOTA 0x0100 | 1425 | #define EXT4_FEATURE_RO_COMPAT_QUOTA 0x0100 |
1416 | #define EXT4_FEATURE_RO_COMPAT_BIGALLOC 0x0200 | 1426 | #define EXT4_FEATURE_RO_COMPAT_BIGALLOC 0x0200 |
1427 | /* | ||
1428 | * METADATA_CSUM also enables group descriptor checksums (GDT_CSUM). When | ||
1429 | * METADATA_CSUM is set, group descriptor checksums use the same algorithm as | ||
1430 | * all other data structures' checksums. However, the METADATA_CSUM and | ||
1431 | * GDT_CSUM bits are mutually exclusive. | ||
1432 | */ | ||
1417 | #define EXT4_FEATURE_RO_COMPAT_METADATA_CSUM 0x0400 | 1433 | #define EXT4_FEATURE_RO_COMPAT_METADATA_CSUM 0x0400 |
1418 | 1434 | ||
1419 | #define EXT4_FEATURE_INCOMPAT_COMPRESSION 0x0001 | 1435 | #define EXT4_FEATURE_INCOMPAT_COMPRESSION 0x0001 |
@@ -1527,6 +1543,18 @@ struct ext4_dir_entry_2 { | |||
1527 | }; | 1543 | }; |
1528 | 1544 | ||
1529 | /* | 1545 | /* |
1546 | * This is a bogus directory entry at the end of each leaf block that | ||
1547 | * records checksums. | ||
1548 | */ | ||
1549 | struct ext4_dir_entry_tail { | ||
1550 | __le32 det_reserved_zero1; /* Pretend to be unused */ | ||
1551 | __le16 det_rec_len; /* 12 */ | ||
1552 | __u8 det_reserved_zero2; /* Zero name length */ | ||
1553 | __u8 det_reserved_ft; /* 0xDE, fake file type */ | ||
1554 | __le32 det_checksum; /* crc32c(uuid+inum+dirblock) */ | ||
1555 | }; | ||
1556 | |||
1557 | /* | ||
1530 | * Ext4 directory file types. Only the low 3 bits are used. The | 1558 | * Ext4 directory file types. Only the low 3 bits are used. The |
1531 | * other bits are reserved for now. | 1559 | * other bits are reserved for now. |
1532 | */ | 1560 | */ |
@@ -1541,6 +1569,8 @@ struct ext4_dir_entry_2 { | |||
1541 | 1569 | ||
1542 | #define EXT4_FT_MAX 8 | 1570 | #define EXT4_FT_MAX 8 |
1543 | 1571 | ||
1572 | #define EXT4_FT_DIR_CSUM 0xDE | ||
1573 | |||
1544 | /* | 1574 | /* |
1545 | * EXT4_DIR_PAD defines the directory entries boundaries | 1575 | * EXT4_DIR_PAD defines the directory entries boundaries |
1546 | * | 1576 | * |
@@ -1741,7 +1771,8 @@ struct mmp_struct { | |||
1741 | __le16 mmp_check_interval; | 1771 | __le16 mmp_check_interval; |
1742 | 1772 | ||
1743 | __le16 mmp_pad1; | 1773 | __le16 mmp_pad1; |
1744 | __le32 mmp_pad2[227]; | 1774 | __le32 mmp_pad2[226]; |
1775 | __le32 mmp_checksum; /* crc32c(uuid+mmp_block) */ | ||
1745 | }; | 1776 | }; |
1746 | 1777 | ||
1747 | /* arguments passed to the mmp thread */ | 1778 | /* arguments passed to the mmp thread */ |
diff --git a/fs/ext4/ext4_extents.h b/fs/ext4/ext4_extents.h index 0f58b86e3a02..94822e74ef73 100644 --- a/fs/ext4/ext4_extents.h +++ b/fs/ext4/ext4_extents.h | |||
@@ -63,9 +63,22 @@ | |||
63 | * ext4_inode has i_block array (60 bytes total). | 63 | * ext4_inode has i_block array (60 bytes total). |
64 | * The first 12 bytes store ext4_extent_header; | 64 | * The first 12 bytes store ext4_extent_header; |
65 | * the remainder stores an array of ext4_extent. | 65 | * the remainder stores an array of ext4_extent. |
66 | * For non-inode extent blocks, ext4_extent_tail | ||
67 | * follows the array. | ||
66 | */ | 68 | */ |
67 | 69 | ||
68 | /* | 70 | /* |
71 | * This is the extent tail on-disk structure. | ||
72 | * All other extent structures are 12 bytes long. It turns out that | ||
73 | * block_size % 12 >= 4 for at least all powers of 2 greater than 512, which | ||
74 | * covers all valid ext4 block sizes. Therefore, this tail structure can be | ||
75 | * crammed into the end of the block without having to rebalance the tree. | ||
76 | */ | ||
77 | struct ext4_extent_tail { | ||
78 | __le32 et_checksum; /* crc32c(uuid+inum+extent_block) */ | ||
79 | }; | ||
80 | |||
81 | /* | ||
69 | * This is the extent on-disk structure. | 82 | * This is the extent on-disk structure. |
70 | * It's used at the bottom of the tree. | 83 | * It's used at the bottom of the tree. |
71 | */ | 84 | */ |
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 349d7b3671c8..b58bd5c8ffe7 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c | |||
@@ -145,6 +145,14 @@ struct dx_map_entry | |||
145 | u16 size; | 145 | u16 size; |
146 | }; | 146 | }; |
147 | 147 | ||
148 | /* | ||
149 | * This goes at the end of each htree block. | ||
150 | */ | ||
151 | struct dx_tail { | ||
152 | u32 dt_reserved; | ||
153 | __le32 dt_checksum; /* crc32c(uuid+inum+dirblock) */ | ||
154 | }; | ||
155 | |||
148 | static inline ext4_lblk_t dx_get_block(struct dx_entry *entry); | 156 | static inline ext4_lblk_t dx_get_block(struct dx_entry *entry); |
149 | static void dx_set_block(struct dx_entry *entry, ext4_lblk_t value); | 157 | static void dx_set_block(struct dx_entry *entry, ext4_lblk_t value); |
150 | static inline unsigned dx_get_hash(struct dx_entry *entry); | 158 | static inline unsigned dx_get_hash(struct dx_entry *entry); |
diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h index 25b7387ff183..91f31ca7d9af 100644 --- a/fs/ext4/xattr.h +++ b/fs/ext4/xattr.h | |||
@@ -27,7 +27,9 @@ struct ext4_xattr_header { | |||
27 | __le32 h_refcount; /* reference count */ | 27 | __le32 h_refcount; /* reference count */ |
28 | __le32 h_blocks; /* number of disk blocks used */ | 28 | __le32 h_blocks; /* number of disk blocks used */ |
29 | __le32 h_hash; /* hash value of all attributes */ | 29 | __le32 h_hash; /* hash value of all attributes */ |
30 | __u32 h_reserved[4]; /* zero right now */ | 30 | __le32 h_checksum; /* crc32c(uuid+id+xattrblock) */ |
31 | /* id = inum if refcount=1, blknum otherwise */ | ||
32 | __u32 h_reserved[3]; /* zero right now */ | ||
31 | }; | 33 | }; |
32 | 34 | ||
33 | struct ext4_xattr_ibody_header { | 35 | struct ext4_xattr_ibody_header { |