diff options
author | Darrick J. Wong <djwong@us.ibm.com> | 2012-04-29 18:47:10 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2012-04-29 18:47:10 -0400 |
commit | 5c359a47e7d999a0ea7f397da2c15590d0a82815 (patch) | |
tree | f104bbabd12d6ac422bf80a6c477b803102ed3c7 | |
parent | feb0ab32a57e4e6c8b24f6fb68f0ce08efe4603c (diff) |
ext4: add checksums to the MMP block
Compute and verify a checksum for the MMP block.
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 | 3 | ||||
-rw-r--r-- | fs/ext4/mmp.c | 44 |
2 files changed, 42 insertions, 5 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 84e76bb96070..0ee9669394f5 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -2413,6 +2413,9 @@ extern int ext4_bio_write_page(struct ext4_io_submit *io, | |||
2413 | 2413 | ||
2414 | /* mmp.c */ | 2414 | /* mmp.c */ |
2415 | extern int ext4_multi_mount_protect(struct super_block *, ext4_fsblk_t); | 2415 | extern int ext4_multi_mount_protect(struct super_block *, ext4_fsblk_t); |
2416 | extern void ext4_mmp_csum_set(struct super_block *sb, struct mmp_struct *mmp); | ||
2417 | extern int ext4_mmp_csum_verify(struct super_block *sb, | ||
2418 | struct mmp_struct *mmp); | ||
2416 | 2419 | ||
2417 | /* BH_Uninit flag: blocks are allocated but uninitialized on disk */ | 2420 | /* BH_Uninit flag: blocks are allocated but uninitialized on disk */ |
2418 | enum ext4_state_bits { | 2421 | enum ext4_state_bits { |
diff --git a/fs/ext4/mmp.c b/fs/ext4/mmp.c index ed6548d89165..f99a1311e847 100644 --- a/fs/ext4/mmp.c +++ b/fs/ext4/mmp.c | |||
@@ -6,12 +6,45 @@ | |||
6 | 6 | ||
7 | #include "ext4.h" | 7 | #include "ext4.h" |
8 | 8 | ||
9 | /* Checksumming functions */ | ||
10 | static __u32 ext4_mmp_csum(struct super_block *sb, struct mmp_struct *mmp) | ||
11 | { | ||
12 | struct ext4_sb_info *sbi = EXT4_SB(sb); | ||
13 | int offset = offsetof(struct mmp_struct, mmp_checksum); | ||
14 | __u32 csum; | ||
15 | |||
16 | csum = ext4_chksum(sbi, sbi->s_csum_seed, (char *)mmp, offset); | ||
17 | |||
18 | return cpu_to_le32(csum); | ||
19 | } | ||
20 | |||
21 | int ext4_mmp_csum_verify(struct super_block *sb, struct mmp_struct *mmp) | ||
22 | { | ||
23 | if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, | ||
24 | EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) | ||
25 | return 1; | ||
26 | |||
27 | return mmp->mmp_checksum == ext4_mmp_csum(sb, mmp); | ||
28 | } | ||
29 | |||
30 | void ext4_mmp_csum_set(struct super_block *sb, struct mmp_struct *mmp) | ||
31 | { | ||
32 | if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, | ||
33 | EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) | ||
34 | return; | ||
35 | |||
36 | mmp->mmp_checksum = ext4_mmp_csum(sb, mmp); | ||
37 | } | ||
38 | |||
9 | /* | 39 | /* |
10 | * Write the MMP block using WRITE_SYNC to try to get the block on-disk | 40 | * Write the MMP block using WRITE_SYNC to try to get the block on-disk |
11 | * faster. | 41 | * faster. |
12 | */ | 42 | */ |
13 | static int write_mmp_block(struct buffer_head *bh) | 43 | static int write_mmp_block(struct super_block *sb, struct buffer_head *bh) |
14 | { | 44 | { |
45 | struct mmp_struct *mmp = (struct mmp_struct *)(bh->b_data); | ||
46 | |||
47 | ext4_mmp_csum_set(sb, mmp); | ||
15 | mark_buffer_dirty(bh); | 48 | mark_buffer_dirty(bh); |
16 | lock_buffer(bh); | 49 | lock_buffer(bh); |
17 | bh->b_end_io = end_buffer_write_sync; | 50 | bh->b_end_io = end_buffer_write_sync; |
@@ -59,7 +92,8 @@ static int read_mmp_block(struct super_block *sb, struct buffer_head **bh, | |||
59 | } | 92 | } |
60 | 93 | ||
61 | mmp = (struct mmp_struct *)((*bh)->b_data); | 94 | mmp = (struct mmp_struct *)((*bh)->b_data); |
62 | if (le32_to_cpu(mmp->mmp_magic) != EXT4_MMP_MAGIC) | 95 | if (le32_to_cpu(mmp->mmp_magic) != EXT4_MMP_MAGIC || |
96 | !ext4_mmp_csum_verify(sb, mmp)) | ||
63 | return -EINVAL; | 97 | return -EINVAL; |
64 | 98 | ||
65 | return 0; | 99 | return 0; |
@@ -120,7 +154,7 @@ static int kmmpd(void *data) | |||
120 | mmp->mmp_time = cpu_to_le64(get_seconds()); | 154 | mmp->mmp_time = cpu_to_le64(get_seconds()); |
121 | last_update_time = jiffies; | 155 | last_update_time = jiffies; |
122 | 156 | ||
123 | retval = write_mmp_block(bh); | 157 | retval = write_mmp_block(sb, bh); |
124 | /* | 158 | /* |
125 | * Don't spew too many error messages. Print one every | 159 | * Don't spew too many error messages. Print one every |
126 | * (s_mmp_update_interval * 60) seconds. | 160 | * (s_mmp_update_interval * 60) seconds. |
@@ -200,7 +234,7 @@ static int kmmpd(void *data) | |||
200 | mmp->mmp_seq = cpu_to_le32(EXT4_MMP_SEQ_CLEAN); | 234 | mmp->mmp_seq = cpu_to_le32(EXT4_MMP_SEQ_CLEAN); |
201 | mmp->mmp_time = cpu_to_le64(get_seconds()); | 235 | mmp->mmp_time = cpu_to_le64(get_seconds()); |
202 | 236 | ||
203 | retval = write_mmp_block(bh); | 237 | retval = write_mmp_block(sb, bh); |
204 | 238 | ||
205 | failed: | 239 | failed: |
206 | kfree(data); | 240 | kfree(data); |
@@ -299,7 +333,7 @@ skip: | |||
299 | seq = mmp_new_seq(); | 333 | seq = mmp_new_seq(); |
300 | mmp->mmp_seq = cpu_to_le32(seq); | 334 | mmp->mmp_seq = cpu_to_le32(seq); |
301 | 335 | ||
302 | retval = write_mmp_block(bh); | 336 | retval = write_mmp_block(sb, bh); |
303 | if (retval) | 337 | if (retval) |
304 | goto failed; | 338 | goto failed; |
305 | 339 | ||