aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/resize.c
diff options
context:
space:
mode:
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>2009-01-05 21:36:19 -0500
committerTheodore Ts'o <tytso@mit.edu>2009-01-05 21:36:19 -0500
commit920313a726e04fef0f2c0bcb04ad8229c0e700d8 (patch)
tree7e7644a2fd48586ec2f455e56525565174798e4a /fs/ext4/resize.c
parente21675d4b63975d09eb75c443c48ebe663d23e18 (diff)
ext4: Use EXT4_GROUP_INFO_NEED_INIT_BIT during resize
The new groups added during resize are flagged as need_init group. Make sure we properly initialize these groups. When we have block size < page size and we are adding new groups the page may still be marked uptodate even though we haven't initialized the group. While forcing the init of buddy cache we need to make sure other groups part of the same page of buddy cache is not using the cache. group_info->alloc_sem is added to ensure the same. Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> cc: stable@kernel.org
Diffstat (limited to 'fs/ext4/resize.c')
-rw-r--r--fs/ext4/resize.c49
1 files changed, 8 insertions, 41 deletions
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
index 526db73701b4..92034d2c8a73 100644
--- a/fs/ext4/resize.c
+++ b/fs/ext4/resize.c
@@ -748,6 +748,7 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
748 struct inode *inode = NULL; 748 struct inode *inode = NULL;
749 handle_t *handle; 749 handle_t *handle;
750 int gdb_off, gdb_num; 750 int gdb_off, gdb_num;
751 int num_grp_locked = 0;
751 int err, err2; 752 int err, err2;
752 753
753 gdb_num = input->group / EXT4_DESC_PER_BLOCK(sb); 754 gdb_num = input->group / EXT4_DESC_PER_BLOCK(sb);
@@ -788,6 +789,7 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
788 } 789 }
789 } 790 }
790 791
792
791 if ((err = verify_group_input(sb, input))) 793 if ((err = verify_group_input(sb, input)))
792 goto exit_put; 794 goto exit_put;
793 795
@@ -856,6 +858,7 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
856 * using the new disk blocks. 858 * using the new disk blocks.
857 */ 859 */
858 860
861 num_grp_locked = ext4_mb_get_buddy_cache_lock(sb, input->group);
859 /* Update group descriptor block for new group */ 862 /* Update group descriptor block for new group */
860 gdp = (struct ext4_group_desc *)((char *)primary->b_data + 863 gdp = (struct ext4_group_desc *)((char *)primary->b_data +
861 gdb_off * EXT4_DESC_SIZE(sb)); 864 gdb_off * EXT4_DESC_SIZE(sb));
@@ -872,9 +875,11 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
872 * We can allocate memory for mb_alloc based on the new group 875 * We can allocate memory for mb_alloc based on the new group
873 * descriptor 876 * descriptor
874 */ 877 */
875 err = ext4_mb_add_more_groupinfo(sb, input->group, gdp); 878 err = ext4_mb_add_groupinfo(sb, input->group, gdp);
876 if (err) 879 if (err) {
880 ext4_mb_put_buddy_cache_lock(sb, input->group, num_grp_locked);
877 goto exit_journal; 881 goto exit_journal;
882 }
878 883
879 /* 884 /*
880 * Make the new blocks and inodes valid next. We do this before 885 * Make the new blocks and inodes valid next. We do this before
@@ -916,6 +921,7 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
916 921
917 /* Update the global fs size fields */ 922 /* Update the global fs size fields */
918 sbi->s_groups_count++; 923 sbi->s_groups_count++;
924 ext4_mb_put_buddy_cache_lock(sb, input->group, num_grp_locked);
919 925
920 ext4_handle_dirty_metadata(handle, NULL, primary); 926 ext4_handle_dirty_metadata(handle, NULL, primary);
921 927
@@ -1082,45 +1088,6 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
1082 if ((err = ext4_journal_stop(handle))) 1088 if ((err = ext4_journal_stop(handle)))
1083 goto exit_put; 1089 goto exit_put;
1084 1090
1085 /*
1086 * Mark mballoc pages as not up to date so that they will be updated
1087 * next time they are loaded by ext4_mb_load_buddy.
1088 *
1089 * XXX Bad, Bad, BAD!!! We should not be overloading the
1090 * Uptodate flag, particularly on thte bitmap bh, as way of
1091 * hinting to ext4_mb_load_buddy() that it needs to be
1092 * overloaded. A user could take a LVM snapshot, then do an
1093 * on-line fsck, and clear the uptodate flag, and this would
1094 * not be a bug in userspace, but a bug in the kernel. FIXME!!!
1095 */
1096 {
1097 struct ext4_sb_info *sbi = EXT4_SB(sb);
1098 struct inode *inode = sbi->s_buddy_cache;
1099 int blocks_per_page;
1100 int block;
1101 int pnum;
1102 struct page *page;
1103
1104 /* Set buddy page as not up to date */
1105 blocks_per_page = PAGE_CACHE_SIZE / sb->s_blocksize;
1106 block = group * 2;
1107 pnum = block / blocks_per_page;
1108 page = find_get_page(inode->i_mapping, pnum);
1109 if (page != NULL) {
1110 ClearPageUptodate(page);
1111 page_cache_release(page);
1112 }
1113
1114 /* Set bitmap page as not up to date */
1115 block++;
1116 pnum = block / blocks_per_page;
1117 page = find_get_page(inode->i_mapping, pnum);
1118 if (page != NULL) {
1119 ClearPageUptodate(page);
1120 page_cache_release(page);
1121 }
1122 }
1123
1124 if (test_opt(sb, DEBUG)) 1091 if (test_opt(sb, DEBUG))
1125 printk(KERN_DEBUG "EXT4-fs: extended group to %llu blocks\n", 1092 printk(KERN_DEBUG "EXT4-fs: extended group to %llu blocks\n",
1126 ext4_blocks_count(es)); 1093 ext4_blocks_count(es));