diff options
author | Darrick J. Wong <djwong@us.ibm.com> | 2012-04-29 18:35:10 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2012-04-29 18:35:10 -0400 |
commit | fa77dcfafeaa6bc73293c646bfc3d5192dcf0be2 (patch) | |
tree | 66c4232c2e5c1f59666e05164b77539a9b1dd290 /fs/ext4/balloc.c | |
parent | 41a246d1ff75a95d2be3191ca6e6db139dc0f430 (diff) |
ext4: calculate and verify block bitmap checksum
Compute and verify the checksum of the block bitmap; this checksum is
stored in the block group descriptor.
Signed-off-by: Darrick J. Wong <djwong@us.ibm.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/balloc.c')
-rw-r--r-- | fs/ext4/balloc.c | 39 |
1 files changed, 32 insertions, 7 deletions
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index 4bbd07a6fa18..0a64e4d5dbad 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c | |||
@@ -174,6 +174,8 @@ void ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh, | |||
174 | ext4_free_inodes_set(sb, gdp, 0); | 174 | ext4_free_inodes_set(sb, gdp, 0); |
175 | ext4_itable_unused_set(sb, gdp, 0); | 175 | ext4_itable_unused_set(sb, gdp, 0); |
176 | memset(bh->b_data, 0xff, sb->s_blocksize); | 176 | memset(bh->b_data, 0xff, sb->s_blocksize); |
177 | ext4_block_bitmap_csum_set(sb, block_group, gdp, bh, | ||
178 | EXT4_BLOCKS_PER_GROUP(sb) / 8); | ||
177 | return; | 179 | return; |
178 | } | 180 | } |
179 | memset(bh->b_data, 0, sb->s_blocksize); | 181 | memset(bh->b_data, 0, sb->s_blocksize); |
@@ -210,6 +212,9 @@ void ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh, | |||
210 | */ | 212 | */ |
211 | ext4_mark_bitmap_end(num_clusters_in_group(sb, block_group), | 213 | ext4_mark_bitmap_end(num_clusters_in_group(sb, block_group), |
212 | sb->s_blocksize * 8, bh->b_data); | 214 | sb->s_blocksize * 8, bh->b_data); |
215 | ext4_block_bitmap_csum_set(sb, block_group, gdp, bh, | ||
216 | EXT4_BLOCKS_PER_GROUP(sb) / 8); | ||
217 | gdp->bg_checksum = ext4_group_desc_csum(sbi, block_group, gdp); | ||
213 | } | 218 | } |
214 | 219 | ||
215 | /* Return the number of free blocks in a block group. It is used when | 220 | /* Return the number of free blocks in a block group. It is used when |
@@ -276,9 +281,9 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb, | |||
276 | } | 281 | } |
277 | 282 | ||
278 | static int ext4_valid_block_bitmap(struct super_block *sb, | 283 | static int ext4_valid_block_bitmap(struct super_block *sb, |
279 | struct ext4_group_desc *desc, | 284 | struct ext4_group_desc *desc, |
280 | unsigned int block_group, | 285 | unsigned int block_group, |
281 | struct buffer_head *bh) | 286 | struct buffer_head *bh) |
282 | { | 287 | { |
283 | ext4_grpblk_t offset; | 288 | ext4_grpblk_t offset; |
284 | ext4_grpblk_t next_zero_bit; | 289 | ext4_grpblk_t next_zero_bit; |
@@ -325,6 +330,23 @@ err_out: | |||
325 | block_group, bitmap_blk); | 330 | block_group, bitmap_blk); |
326 | return 0; | 331 | return 0; |
327 | } | 332 | } |
333 | |||
334 | void ext4_validate_block_bitmap(struct super_block *sb, | ||
335 | struct ext4_group_desc *desc, | ||
336 | unsigned int block_group, | ||
337 | struct buffer_head *bh) | ||
338 | { | ||
339 | if (buffer_verified(bh)) | ||
340 | return; | ||
341 | |||
342 | ext4_lock_group(sb, block_group); | ||
343 | if (ext4_valid_block_bitmap(sb, desc, block_group, bh) && | ||
344 | ext4_block_bitmap_csum_verify(sb, block_group, desc, bh, | ||
345 | EXT4_BLOCKS_PER_GROUP(sb) / 8)) | ||
346 | set_buffer_verified(bh); | ||
347 | ext4_unlock_group(sb, block_group); | ||
348 | } | ||
349 | |||
328 | /** | 350 | /** |
329 | * ext4_read_block_bitmap() | 351 | * ext4_read_block_bitmap() |
330 | * @sb: super block | 352 | * @sb: super block |
@@ -355,12 +377,12 @@ ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group) | |||
355 | } | 377 | } |
356 | 378 | ||
357 | if (bitmap_uptodate(bh)) | 379 | if (bitmap_uptodate(bh)) |
358 | return bh; | 380 | goto verify; |
359 | 381 | ||
360 | lock_buffer(bh); | 382 | lock_buffer(bh); |
361 | if (bitmap_uptodate(bh)) { | 383 | if (bitmap_uptodate(bh)) { |
362 | unlock_buffer(bh); | 384 | unlock_buffer(bh); |
363 | return bh; | 385 | goto verify; |
364 | } | 386 | } |
365 | ext4_lock_group(sb, block_group); | 387 | ext4_lock_group(sb, block_group); |
366 | if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { | 388 | if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { |
@@ -379,7 +401,7 @@ ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group) | |||
379 | */ | 401 | */ |
380 | set_bitmap_uptodate(bh); | 402 | set_bitmap_uptodate(bh); |
381 | unlock_buffer(bh); | 403 | unlock_buffer(bh); |
382 | return bh; | 404 | goto verify; |
383 | } | 405 | } |
384 | /* | 406 | /* |
385 | * submit the buffer_head for reading | 407 | * submit the buffer_head for reading |
@@ -390,6 +412,9 @@ ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group) | |||
390 | get_bh(bh); | 412 | get_bh(bh); |
391 | submit_bh(READ, bh); | 413 | submit_bh(READ, bh); |
392 | return bh; | 414 | return bh; |
415 | verify: | ||
416 | ext4_validate_block_bitmap(sb, desc, block_group, bh); | ||
417 | return bh; | ||
393 | } | 418 | } |
394 | 419 | ||
395 | /* Returns 0 on success, 1 on error */ | 420 | /* Returns 0 on success, 1 on error */ |
@@ -412,7 +437,7 @@ int ext4_wait_block_bitmap(struct super_block *sb, ext4_group_t block_group, | |||
412 | } | 437 | } |
413 | clear_buffer_new(bh); | 438 | clear_buffer_new(bh); |
414 | /* Panic or remount fs read-only if block bitmap is invalid */ | 439 | /* Panic or remount fs read-only if block bitmap is invalid */ |
415 | ext4_valid_block_bitmap(sb, desc, block_group, bh); | 440 | ext4_validate_block_bitmap(sb, desc, block_group, bh); |
416 | return 0; | 441 | return 0; |
417 | } | 442 | } |
418 | 443 | ||