aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/resize.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-06-01 13:12:15 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-06-01 13:12:15 -0400
commit4edebed86690eb8db9af3ab85baf4a34e73266cc (patch)
tree8ab144b08f490f239fa62be52470860c9311664d /fs/ext4/resize.c
parent51eab603f5c86dd1eae4c525df3e7f7eeab401d6 (diff)
parent5e44f8c374dc4f8eadf61cd18b2c0d46bc87c1b7 (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.c71
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
1074static 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
1094static 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