diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-06-01 13:12:15 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-06-01 13:12:15 -0400 |
commit | 4edebed86690eb8db9af3ab85baf4a34e73266cc (patch) | |
tree | 8ab144b08f490f239fa62be52470860c9311664d /fs/ext4/resize.c | |
parent | 51eab603f5c86dd1eae4c525df3e7f7eeab401d6 (diff) | |
parent | 5e44f8c374dc4f8eadf61cd18b2c0d46bc87c1b7 (diff) |
Merge tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
Pull Ext4 updates from Theodore Ts'o:
"The major new feature added in this update is Darrick J Wong's
metadata checksum feature, which adds crc32 checksums to ext4's
metadata fields.
There is also the usual set of cleanups and bug fixes."
* tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: (44 commits)
ext4: hole-punch use truncate_pagecache_range
jbd2: use kmem_cache_zalloc wrapper instead of flag
ext4: remove mb_groups before tearing down the buddy_cache
ext4: add ext4_mb_unload_buddy in the error path
ext4: don't trash state flags in EXT4_IOC_SETFLAGS
ext4: let getattr report the right blocks in delalloc+bigalloc
ext4: add missing save_error_info() to ext4_error()
ext4: add debugging trigger for ext4_error()
ext4: protect group inode free counting with group lock
ext4: use consistent ssize_t type in ext4_file_write()
ext4: fix format flag in ext4_ext_binsearch_idx()
ext4: cleanup in ext4_discard_allocated_blocks()
ext4: return ENOMEM when mounts fail due to lack of memory
ext4: remove redundundant "(char *) bh->b_data" casts
ext4: disallow hard-linked directory in ext4_lookup
ext4: fix potential integer overflow in alloc_flex_gd()
ext4: remove needs_recovery in ext4_mb_init()
ext4: force ro mount if ext4_setup_super() fails
ext4: fix potential NULL dereference in ext4_free_inodes_counts()
ext4/jbd2: add metadata checksumming to the list of supported features
...
Diffstat (limited to 'fs/ext4/resize.c')
-rw-r--r-- | fs/ext4/resize.c | 71 |
1 files changed, 63 insertions, 8 deletions
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 59fa0be27251..7ea6cbb44121 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c | |||
@@ -161,6 +161,8 @@ static struct ext4_new_flex_group_data *alloc_flex_gd(unsigned long flexbg_size) | |||
161 | if (flex_gd == NULL) | 161 | if (flex_gd == NULL) |
162 | goto out3; | 162 | goto out3; |
163 | 163 | ||
164 | if (flexbg_size >= UINT_MAX / sizeof(struct ext4_new_flex_group_data)) | ||
165 | goto out2; | ||
164 | flex_gd->count = flexbg_size; | 166 | flex_gd->count = flexbg_size; |
165 | 167 | ||
166 | flex_gd->groups = kmalloc(sizeof(struct ext4_new_group_data) * | 168 | flex_gd->groups = kmalloc(sizeof(struct ext4_new_group_data) * |
@@ -796,7 +798,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode, | |||
796 | ext4_kvfree(o_group_desc); | 798 | ext4_kvfree(o_group_desc); |
797 | 799 | ||
798 | le16_add_cpu(&es->s_reserved_gdt_blocks, -1); | 800 | le16_add_cpu(&es->s_reserved_gdt_blocks, -1); |
799 | err = ext4_handle_dirty_metadata(handle, NULL, EXT4_SB(sb)->s_sbh); | 801 | err = ext4_handle_dirty_super_now(handle, sb); |
800 | if (err) | 802 | if (err) |
801 | ext4_std_error(sb, err); | 803 | ext4_std_error(sb, err); |
802 | 804 | ||
@@ -968,6 +970,8 @@ static void update_backups(struct super_block *sb, | |||
968 | goto exit_err; | 970 | goto exit_err; |
969 | } | 971 | } |
970 | 972 | ||
973 | ext4_superblock_csum_set(sb, (struct ext4_super_block *)data); | ||
974 | |||
971 | while ((group = ext4_list_backups(sb, &three, &five, &seven)) < last) { | 975 | while ((group = ext4_list_backups(sb, &three, &five, &seven)) < last) { |
972 | struct buffer_head *bh; | 976 | struct buffer_head *bh; |
973 | 977 | ||
@@ -1067,6 +1071,54 @@ static int ext4_add_new_descs(handle_t *handle, struct super_block *sb, | |||
1067 | return err; | 1071 | return err; |
1068 | } | 1072 | } |
1069 | 1073 | ||
1074 | static struct buffer_head *ext4_get_bitmap(struct super_block *sb, __u64 block) | ||
1075 | { | ||
1076 | struct buffer_head *bh = sb_getblk(sb, block); | ||
1077 | if (!bh) | ||
1078 | return NULL; | ||
1079 | |||
1080 | if (bitmap_uptodate(bh)) | ||
1081 | return bh; | ||
1082 | |||
1083 | lock_buffer(bh); | ||
1084 | if (bh_submit_read(bh) < 0) { | ||
1085 | unlock_buffer(bh); | ||
1086 | brelse(bh); | ||
1087 | return NULL; | ||
1088 | } | ||
1089 | unlock_buffer(bh); | ||
1090 | |||
1091 | return bh; | ||
1092 | } | ||
1093 | |||
1094 | static int ext4_set_bitmap_checksums(struct super_block *sb, | ||
1095 | ext4_group_t group, | ||
1096 | struct ext4_group_desc *gdp, | ||
1097 | struct ext4_new_group_data *group_data) | ||
1098 | { | ||
1099 | struct buffer_head *bh; | ||
1100 | |||
1101 | if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, | ||
1102 | EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) | ||
1103 | return 0; | ||
1104 | |||
1105 | bh = ext4_get_bitmap(sb, group_data->inode_bitmap); | ||
1106 | if (!bh) | ||
1107 | return -EIO; | ||
1108 | ext4_inode_bitmap_csum_set(sb, group, gdp, bh, | ||
1109 | EXT4_INODES_PER_GROUP(sb) / 8); | ||
1110 | brelse(bh); | ||
1111 | |||
1112 | bh = ext4_get_bitmap(sb, group_data->block_bitmap); | ||
1113 | if (!bh) | ||
1114 | return -EIO; | ||
1115 | ext4_block_bitmap_csum_set(sb, group, gdp, bh, | ||
1116 | EXT4_BLOCKS_PER_GROUP(sb) / 8); | ||
1117 | brelse(bh); | ||
1118 | |||
1119 | return 0; | ||
1120 | } | ||
1121 | |||
1070 | /* | 1122 | /* |
1071 | * ext4_setup_new_descs() will set up the group descriptor descriptors of a flex bg | 1123 | * ext4_setup_new_descs() will set up the group descriptor descriptors of a flex bg |
1072 | */ | 1124 | */ |
@@ -1093,18 +1145,24 @@ static int ext4_setup_new_descs(handle_t *handle, struct super_block *sb, | |||
1093 | */ | 1145 | */ |
1094 | gdb_bh = sbi->s_group_desc[gdb_num]; | 1146 | gdb_bh = sbi->s_group_desc[gdb_num]; |
1095 | /* Update group descriptor block for new group */ | 1147 | /* Update group descriptor block for new group */ |
1096 | gdp = (struct ext4_group_desc *)((char *)gdb_bh->b_data + | 1148 | gdp = (struct ext4_group_desc *)(gdb_bh->b_data + |
1097 | gdb_off * EXT4_DESC_SIZE(sb)); | 1149 | gdb_off * EXT4_DESC_SIZE(sb)); |
1098 | 1150 | ||
1099 | memset(gdp, 0, EXT4_DESC_SIZE(sb)); | 1151 | memset(gdp, 0, EXT4_DESC_SIZE(sb)); |
1100 | ext4_block_bitmap_set(sb, gdp, group_data->block_bitmap); | 1152 | ext4_block_bitmap_set(sb, gdp, group_data->block_bitmap); |
1101 | ext4_inode_bitmap_set(sb, gdp, group_data->inode_bitmap); | 1153 | ext4_inode_bitmap_set(sb, gdp, group_data->inode_bitmap); |
1154 | err = ext4_set_bitmap_checksums(sb, group, gdp, group_data); | ||
1155 | if (err) { | ||
1156 | ext4_std_error(sb, err); | ||
1157 | break; | ||
1158 | } | ||
1159 | |||
1102 | ext4_inode_table_set(sb, gdp, group_data->inode_table); | 1160 | ext4_inode_table_set(sb, gdp, group_data->inode_table); |
1103 | ext4_free_group_clusters_set(sb, gdp, | 1161 | ext4_free_group_clusters_set(sb, gdp, |
1104 | EXT4_B2C(sbi, group_data->free_blocks_count)); | 1162 | EXT4_B2C(sbi, group_data->free_blocks_count)); |
1105 | ext4_free_inodes_set(sb, gdp, EXT4_INODES_PER_GROUP(sb)); | 1163 | ext4_free_inodes_set(sb, gdp, EXT4_INODES_PER_GROUP(sb)); |
1106 | gdp->bg_flags = cpu_to_le16(*bg_flags); | 1164 | gdp->bg_flags = cpu_to_le16(*bg_flags); |
1107 | gdp->bg_checksum = ext4_group_desc_csum(sbi, group, gdp); | 1165 | ext4_group_desc_csum_set(sb, group, gdp); |
1108 | 1166 | ||
1109 | err = ext4_handle_dirty_metadata(handle, NULL, gdb_bh); | 1167 | err = ext4_handle_dirty_metadata(handle, NULL, gdb_bh); |
1110 | if (unlikely(err)) { | 1168 | if (unlikely(err)) { |
@@ -1343,17 +1401,14 @@ static int ext4_setup_next_flex_gd(struct super_block *sb, | |||
1343 | (1 + ext4_bg_num_gdb(sb, group + i) + | 1401 | (1 + ext4_bg_num_gdb(sb, group + i) + |
1344 | le16_to_cpu(es->s_reserved_gdt_blocks)) : 0; | 1402 | le16_to_cpu(es->s_reserved_gdt_blocks)) : 0; |
1345 | group_data[i].free_blocks_count = blocks_per_group - overhead; | 1403 | group_data[i].free_blocks_count = blocks_per_group - overhead; |
1346 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, | 1404 | if (ext4_has_group_desc_csum(sb)) |
1347 | EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) | ||
1348 | flex_gd->bg_flags[i] = EXT4_BG_BLOCK_UNINIT | | 1405 | flex_gd->bg_flags[i] = EXT4_BG_BLOCK_UNINIT | |
1349 | EXT4_BG_INODE_UNINIT; | 1406 | EXT4_BG_INODE_UNINIT; |
1350 | else | 1407 | else |
1351 | flex_gd->bg_flags[i] = EXT4_BG_INODE_ZEROED; | 1408 | flex_gd->bg_flags[i] = EXT4_BG_INODE_ZEROED; |
1352 | } | 1409 | } |
1353 | 1410 | ||
1354 | if (last_group == n_group && | 1411 | if (last_group == n_group && ext4_has_group_desc_csum(sb)) |
1355 | EXT4_HAS_RO_COMPAT_FEATURE(sb, | ||
1356 | EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) | ||
1357 | /* We need to initialize block bitmap of last group. */ | 1412 | /* We need to initialize block bitmap of last group. */ |
1358 | flex_gd->bg_flags[i - 1] &= ~EXT4_BG_BLOCK_UNINIT; | 1413 | flex_gd->bg_flags[i - 1] &= ~EXT4_BG_BLOCK_UNINIT; |
1359 | 1414 | ||