diff options
Diffstat (limited to 'fs/ext4/resize.c')
-rw-r--r-- | fs/ext4/resize.c | 113 |
1 files changed, 36 insertions, 77 deletions
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index b6ec1843a015..c328be5d6885 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c | |||
@@ -50,7 +50,7 @@ static int verify_group_input(struct super_block *sb, | |||
50 | ext4_get_group_no_and_offset(sb, start, NULL, &offset); | 50 | ext4_get_group_no_and_offset(sb, start, NULL, &offset); |
51 | if (group != sbi->s_groups_count) | 51 | if (group != sbi->s_groups_count) |
52 | ext4_warning(sb, __func__, | 52 | ext4_warning(sb, __func__, |
53 | "Cannot add at group %u (only %lu groups)", | 53 | "Cannot add at group %u (only %u groups)", |
54 | input->group, sbi->s_groups_count); | 54 | input->group, sbi->s_groups_count); |
55 | else if (offset != 0) | 55 | else if (offset != 0) |
56 | ext4_warning(sb, __func__, "Last group not full"); | 56 | ext4_warning(sb, __func__, "Last group not full"); |
@@ -149,7 +149,7 @@ static int extend_or_restart_transaction(handle_t *handle, int thresh, | |||
149 | { | 149 | { |
150 | int err; | 150 | int err; |
151 | 151 | ||
152 | if (handle->h_buffer_credits >= thresh) | 152 | if (ext4_handle_has_enough_credits(handle, thresh)) |
153 | return 0; | 153 | return 0; |
154 | 154 | ||
155 | err = ext4_journal_extend(handle, EXT4_MAX_TRANS_DATA); | 155 | err = ext4_journal_extend(handle, EXT4_MAX_TRANS_DATA); |
@@ -232,7 +232,7 @@ static int setup_new_group_blocks(struct super_block *sb, | |||
232 | memcpy(gdb->b_data, sbi->s_group_desc[i]->b_data, gdb->b_size); | 232 | memcpy(gdb->b_data, sbi->s_group_desc[i]->b_data, gdb->b_size); |
233 | set_buffer_uptodate(gdb); | 233 | set_buffer_uptodate(gdb); |
234 | unlock_buffer(gdb); | 234 | unlock_buffer(gdb); |
235 | ext4_journal_dirty_metadata(handle, gdb); | 235 | ext4_handle_dirty_metadata(handle, NULL, gdb); |
236 | ext4_set_bit(bit, bh->b_data); | 236 | ext4_set_bit(bit, bh->b_data); |
237 | brelse(gdb); | 237 | brelse(gdb); |
238 | } | 238 | } |
@@ -251,7 +251,7 @@ static int setup_new_group_blocks(struct super_block *sb, | |||
251 | err = PTR_ERR(bh); | 251 | err = PTR_ERR(bh); |
252 | goto exit_bh; | 252 | goto exit_bh; |
253 | } | 253 | } |
254 | ext4_journal_dirty_metadata(handle, gdb); | 254 | ext4_handle_dirty_metadata(handle, NULL, gdb); |
255 | ext4_set_bit(bit, bh->b_data); | 255 | ext4_set_bit(bit, bh->b_data); |
256 | brelse(gdb); | 256 | brelse(gdb); |
257 | } | 257 | } |
@@ -276,7 +276,7 @@ static int setup_new_group_blocks(struct super_block *sb, | |||
276 | err = PTR_ERR(it); | 276 | err = PTR_ERR(it); |
277 | goto exit_bh; | 277 | goto exit_bh; |
278 | } | 278 | } |
279 | ext4_journal_dirty_metadata(handle, it); | 279 | ext4_handle_dirty_metadata(handle, NULL, it); |
280 | brelse(it); | 280 | brelse(it); |
281 | ext4_set_bit(bit, bh->b_data); | 281 | ext4_set_bit(bit, bh->b_data); |
282 | } | 282 | } |
@@ -284,11 +284,9 @@ static int setup_new_group_blocks(struct super_block *sb, | |||
284 | if ((err = extend_or_restart_transaction(handle, 2, bh))) | 284 | if ((err = extend_or_restart_transaction(handle, 2, bh))) |
285 | goto exit_bh; | 285 | goto exit_bh; |
286 | 286 | ||
287 | mark_bitmap_end(input->blocks_count, EXT4_BLOCKS_PER_GROUP(sb), | 287 | mark_bitmap_end(input->blocks_count, sb->s_blocksize * 8, bh->b_data); |
288 | bh->b_data); | 288 | ext4_handle_dirty_metadata(handle, NULL, bh); |
289 | ext4_journal_dirty_metadata(handle, bh); | ||
290 | brelse(bh); | 289 | brelse(bh); |
291 | |||
292 | /* Mark unused entries in inode bitmap used */ | 290 | /* Mark unused entries in inode bitmap used */ |
293 | ext4_debug("clear inode bitmap %#04llx (+%llu)\n", | 291 | ext4_debug("clear inode bitmap %#04llx (+%llu)\n", |
294 | input->inode_bitmap, input->inode_bitmap - start); | 292 | input->inode_bitmap, input->inode_bitmap - start); |
@@ -297,9 +295,9 @@ static int setup_new_group_blocks(struct super_block *sb, | |||
297 | goto exit_journal; | 295 | goto exit_journal; |
298 | } | 296 | } |
299 | 297 | ||
300 | mark_bitmap_end(EXT4_INODES_PER_GROUP(sb), EXT4_BLOCKS_PER_GROUP(sb), | 298 | mark_bitmap_end(EXT4_INODES_PER_GROUP(sb), sb->s_blocksize * 8, |
301 | bh->b_data); | 299 | bh->b_data); |
302 | ext4_journal_dirty_metadata(handle, bh); | 300 | ext4_handle_dirty_metadata(handle, NULL, bh); |
303 | exit_bh: | 301 | exit_bh: |
304 | brelse(bh); | 302 | brelse(bh); |
305 | 303 | ||
@@ -486,12 +484,12 @@ static int add_new_gdb(handle_t *handle, struct inode *inode, | |||
486 | * reserved inode, and will become GDT blocks (primary and backup). | 484 | * reserved inode, and will become GDT blocks (primary and backup). |
487 | */ | 485 | */ |
488 | data[gdb_num % EXT4_ADDR_PER_BLOCK(sb)] = 0; | 486 | data[gdb_num % EXT4_ADDR_PER_BLOCK(sb)] = 0; |
489 | ext4_journal_dirty_metadata(handle, dind); | 487 | ext4_handle_dirty_metadata(handle, NULL, dind); |
490 | brelse(dind); | 488 | brelse(dind); |
491 | inode->i_blocks -= (gdbackups + 1) * sb->s_blocksize >> 9; | 489 | inode->i_blocks -= (gdbackups + 1) * sb->s_blocksize >> 9; |
492 | ext4_mark_iloc_dirty(handle, inode, &iloc); | 490 | ext4_mark_iloc_dirty(handle, inode, &iloc); |
493 | memset((*primary)->b_data, 0, sb->s_blocksize); | 491 | memset((*primary)->b_data, 0, sb->s_blocksize); |
494 | ext4_journal_dirty_metadata(handle, *primary); | 492 | ext4_handle_dirty_metadata(handle, NULL, *primary); |
495 | 493 | ||
496 | o_group_desc = EXT4_SB(sb)->s_group_desc; | 494 | o_group_desc = EXT4_SB(sb)->s_group_desc; |
497 | memcpy(n_group_desc, o_group_desc, | 495 | memcpy(n_group_desc, o_group_desc, |
@@ -502,7 +500,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode, | |||
502 | kfree(o_group_desc); | 500 | kfree(o_group_desc); |
503 | 501 | ||
504 | le16_add_cpu(&es->s_reserved_gdt_blocks, -1); | 502 | le16_add_cpu(&es->s_reserved_gdt_blocks, -1); |
505 | ext4_journal_dirty_metadata(handle, EXT4_SB(sb)->s_sbh); | 503 | ext4_handle_dirty_metadata(handle, NULL, EXT4_SB(sb)->s_sbh); |
506 | 504 | ||
507 | return 0; | 505 | return 0; |
508 | 506 | ||
@@ -618,7 +616,7 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode, | |||
618 | primary[i]->b_blocknr, gdbackups, | 616 | primary[i]->b_blocknr, gdbackups, |
619 | blk + primary[i]->b_blocknr); */ | 617 | blk + primary[i]->b_blocknr); */ |
620 | data[gdbackups] = cpu_to_le32(blk + primary[i]->b_blocknr); | 618 | data[gdbackups] = cpu_to_le32(blk + primary[i]->b_blocknr); |
621 | err2 = ext4_journal_dirty_metadata(handle, primary[i]); | 619 | err2 = ext4_handle_dirty_metadata(handle, NULL, primary[i]); |
622 | if (!err) | 620 | if (!err) |
623 | err = err2; | 621 | err = err2; |
624 | } | 622 | } |
@@ -676,7 +674,8 @@ static void update_backups(struct super_block *sb, | |||
676 | struct buffer_head *bh; | 674 | struct buffer_head *bh; |
677 | 675 | ||
678 | /* Out of journal space, and can't get more - abort - so sad */ | 676 | /* Out of journal space, and can't get more - abort - so sad */ |
679 | if (handle->h_buffer_credits == 0 && | 677 | if (ext4_handle_valid(handle) && |
678 | handle->h_buffer_credits == 0 && | ||
680 | ext4_journal_extend(handle, EXT4_MAX_TRANS_DATA) && | 679 | ext4_journal_extend(handle, EXT4_MAX_TRANS_DATA) && |
681 | (err = ext4_journal_restart(handle, EXT4_MAX_TRANS_DATA))) | 680 | (err = ext4_journal_restart(handle, EXT4_MAX_TRANS_DATA))) |
682 | break; | 681 | break; |
@@ -696,7 +695,7 @@ static void update_backups(struct super_block *sb, | |||
696 | memset(bh->b_data + size, 0, rest); | 695 | memset(bh->b_data + size, 0, rest); |
697 | set_buffer_uptodate(bh); | 696 | set_buffer_uptodate(bh); |
698 | unlock_buffer(bh); | 697 | unlock_buffer(bh); |
699 | ext4_journal_dirty_metadata(handle, bh); | 698 | ext4_handle_dirty_metadata(handle, NULL, bh); |
700 | brelse(bh); | 699 | brelse(bh); |
701 | } | 700 | } |
702 | if ((err2 = ext4_journal_stop(handle)) && !err) | 701 | if ((err2 = ext4_journal_stop(handle)) && !err) |
@@ -715,7 +714,7 @@ static void update_backups(struct super_block *sb, | |||
715 | exit_err: | 714 | exit_err: |
716 | if (err) { | 715 | if (err) { |
717 | ext4_warning(sb, __func__, | 716 | ext4_warning(sb, __func__, |
718 | "can't update backup for group %lu (err %d), " | 717 | "can't update backup for group %u (err %d), " |
719 | "forcing fsck on next reboot", group, err); | 718 | "forcing fsck on next reboot", group, err); |
720 | sbi->s_mount_state &= ~EXT4_VALID_FS; | 719 | sbi->s_mount_state &= ~EXT4_VALID_FS; |
721 | sbi->s_es->s_state &= cpu_to_le16(~EXT4_VALID_FS); | 720 | sbi->s_es->s_state &= cpu_to_le16(~EXT4_VALID_FS); |
@@ -747,6 +746,7 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input) | |||
747 | struct inode *inode = NULL; | 746 | struct inode *inode = NULL; |
748 | handle_t *handle; | 747 | handle_t *handle; |
749 | int gdb_off, gdb_num; | 748 | int gdb_off, gdb_num; |
749 | int num_grp_locked = 0; | ||
750 | int err, err2; | 750 | int err, err2; |
751 | 751 | ||
752 | gdb_num = input->group / EXT4_DESC_PER_BLOCK(sb); | 752 | gdb_num = input->group / EXT4_DESC_PER_BLOCK(sb); |
@@ -761,13 +761,13 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input) | |||
761 | 761 | ||
762 | if (ext4_blocks_count(es) + input->blocks_count < | 762 | if (ext4_blocks_count(es) + input->blocks_count < |
763 | ext4_blocks_count(es)) { | 763 | ext4_blocks_count(es)) { |
764 | ext4_warning(sb, __func__, "blocks_count overflow\n"); | 764 | ext4_warning(sb, __func__, "blocks_count overflow"); |
765 | return -EINVAL; | 765 | return -EINVAL; |
766 | } | 766 | } |
767 | 767 | ||
768 | if (le32_to_cpu(es->s_inodes_count) + EXT4_INODES_PER_GROUP(sb) < | 768 | if (le32_to_cpu(es->s_inodes_count) + EXT4_INODES_PER_GROUP(sb) < |
769 | le32_to_cpu(es->s_inodes_count)) { | 769 | le32_to_cpu(es->s_inodes_count)) { |
770 | ext4_warning(sb, __func__, "inodes_count overflow\n"); | 770 | ext4_warning(sb, __func__, "inodes_count overflow"); |
771 | return -EINVAL; | 771 | return -EINVAL; |
772 | } | 772 | } |
773 | 773 | ||
@@ -787,6 +787,7 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input) | |||
787 | } | 787 | } |
788 | } | 788 | } |
789 | 789 | ||
790 | |||
790 | if ((err = verify_group_input(sb, input))) | 791 | if ((err = verify_group_input(sb, input))) |
791 | goto exit_put; | 792 | goto exit_put; |
792 | 793 | ||
@@ -855,6 +856,7 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input) | |||
855 | * using the new disk blocks. | 856 | * using the new disk blocks. |
856 | */ | 857 | */ |
857 | 858 | ||
859 | num_grp_locked = ext4_mb_get_buddy_cache_lock(sb, input->group); | ||
858 | /* Update group descriptor block for new group */ | 860 | /* Update group descriptor block for new group */ |
859 | gdp = (struct ext4_group_desc *)((char *)primary->b_data + | 861 | gdp = (struct ext4_group_desc *)((char *)primary->b_data + |
860 | gdb_off * EXT4_DESC_SIZE(sb)); | 862 | gdb_off * EXT4_DESC_SIZE(sb)); |
@@ -862,17 +864,20 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input) | |||
862 | ext4_block_bitmap_set(sb, gdp, input->block_bitmap); /* LV FIXME */ | 864 | ext4_block_bitmap_set(sb, gdp, input->block_bitmap); /* LV FIXME */ |
863 | ext4_inode_bitmap_set(sb, gdp, input->inode_bitmap); /* LV FIXME */ | 865 | ext4_inode_bitmap_set(sb, gdp, input->inode_bitmap); /* LV FIXME */ |
864 | ext4_inode_table_set(sb, gdp, input->inode_table); /* LV FIXME */ | 866 | ext4_inode_table_set(sb, gdp, input->inode_table); /* LV FIXME */ |
865 | gdp->bg_free_blocks_count = cpu_to_le16(input->free_blocks_count); | 867 | ext4_free_blks_set(sb, gdp, input->free_blocks_count); |
866 | gdp->bg_free_inodes_count = cpu_to_le16(EXT4_INODES_PER_GROUP(sb)); | 868 | ext4_free_inodes_set(sb, gdp, EXT4_INODES_PER_GROUP(sb)); |
869 | gdp->bg_flags |= cpu_to_le16(EXT4_BG_INODE_ZEROED); | ||
867 | gdp->bg_checksum = ext4_group_desc_csum(sbi, input->group, gdp); | 870 | gdp->bg_checksum = ext4_group_desc_csum(sbi, input->group, gdp); |
868 | 871 | ||
869 | /* | 872 | /* |
870 | * We can allocate memory for mb_alloc based on the new group | 873 | * We can allocate memory for mb_alloc based on the new group |
871 | * descriptor | 874 | * descriptor |
872 | */ | 875 | */ |
873 | err = ext4_mb_add_more_groupinfo(sb, input->group, gdp); | 876 | err = ext4_mb_add_groupinfo(sb, input->group, gdp); |
874 | if (err) | 877 | if (err) { |
878 | ext4_mb_put_buddy_cache_lock(sb, input->group, num_grp_locked); | ||
875 | goto exit_journal; | 879 | goto exit_journal; |
880 | } | ||
876 | 881 | ||
877 | /* | 882 | /* |
878 | * Make the new blocks and inodes valid next. We do this before | 883 | * Make the new blocks and inodes valid next. We do this before |
@@ -914,8 +919,9 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input) | |||
914 | 919 | ||
915 | /* Update the global fs size fields */ | 920 | /* Update the global fs size fields */ |
916 | sbi->s_groups_count++; | 921 | sbi->s_groups_count++; |
922 | ext4_mb_put_buddy_cache_lock(sb, input->group, num_grp_locked); | ||
917 | 923 | ||
918 | ext4_journal_dirty_metadata(handle, primary); | 924 | ext4_handle_dirty_metadata(handle, NULL, primary); |
919 | 925 | ||
920 | /* Update the reserved block counts only once the new group is | 926 | /* Update the reserved block counts only once the new group is |
921 | * active. */ | 927 | * active. */ |
@@ -937,7 +943,7 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input) | |||
937 | EXT4_INODES_PER_GROUP(sb); | 943 | EXT4_INODES_PER_GROUP(sb); |
938 | } | 944 | } |
939 | 945 | ||
940 | ext4_journal_dirty_metadata(handle, sbi->s_sbh); | 946 | ext4_handle_dirty_metadata(handle, NULL, sbi->s_sbh); |
941 | sb->s_dirt = 1; | 947 | sb->s_dirt = 1; |
942 | 948 | ||
943 | exit_journal: | 949 | exit_journal: |
@@ -975,9 +981,7 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es, | |||
975 | struct buffer_head *bh; | 981 | struct buffer_head *bh; |
976 | handle_t *handle; | 982 | handle_t *handle; |
977 | int err; | 983 | int err; |
978 | unsigned long freed_blocks; | ||
979 | ext4_group_t group; | 984 | ext4_group_t group; |
980 | struct ext4_group_info *grp; | ||
981 | 985 | ||
982 | /* We don't need to worry about locking wrt other resizers just | 986 | /* We don't need to worry about locking wrt other resizers just |
983 | * yet: we're going to revalidate es->s_blocks_count after | 987 | * yet: we're going to revalidate es->s_blocks_count after |
@@ -997,8 +1001,7 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es, | |||
997 | " too large to resize to %llu blocks safely\n", | 1001 | " too large to resize to %llu blocks safely\n", |
998 | sb->s_id, n_blocks_count); | 1002 | sb->s_id, n_blocks_count); |
999 | if (sizeof(sector_t) < 8) | 1003 | if (sizeof(sector_t) < 8) |
1000 | ext4_warning(sb, __func__, | 1004 | ext4_warning(sb, __func__, "CONFIG_LBD not enabled"); |
1001 | "CONFIG_LBD not enabled\n"); | ||
1002 | return -EINVAL; | 1005 | return -EINVAL; |
1003 | } | 1006 | } |
1004 | 1007 | ||
@@ -1071,62 +1074,18 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es, | |||
1071 | goto exit_put; | 1074 | goto exit_put; |
1072 | } | 1075 | } |
1073 | ext4_blocks_count_set(es, o_blocks_count + add); | 1076 | ext4_blocks_count_set(es, o_blocks_count + add); |
1074 | ext4_journal_dirty_metadata(handle, EXT4_SB(sb)->s_sbh); | 1077 | ext4_handle_dirty_metadata(handle, NULL, EXT4_SB(sb)->s_sbh); |
1075 | sb->s_dirt = 1; | 1078 | sb->s_dirt = 1; |
1076 | unlock_super(sb); | 1079 | unlock_super(sb); |
1077 | ext4_debug("freeing blocks %llu through %llu\n", o_blocks_count, | 1080 | ext4_debug("freeing blocks %llu through %llu\n", o_blocks_count, |
1078 | o_blocks_count + add); | 1081 | o_blocks_count + add); |
1079 | ext4_free_blocks_sb(handle, sb, o_blocks_count, add, &freed_blocks); | 1082 | /* We add the blocks to the bitmap and set the group need init bit */ |
1083 | ext4_add_groupblocks(handle, sb, o_blocks_count, add); | ||
1080 | ext4_debug("freed blocks %llu through %llu\n", o_blocks_count, | 1084 | ext4_debug("freed blocks %llu through %llu\n", o_blocks_count, |
1081 | o_blocks_count + add); | 1085 | o_blocks_count + add); |
1082 | if ((err = ext4_journal_stop(handle))) | 1086 | if ((err = ext4_journal_stop(handle))) |
1083 | goto exit_put; | 1087 | goto exit_put; |
1084 | 1088 | ||
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 | /* Get the info on the last group */ | ||
1124 | grp = ext4_get_group_info(sb, group); | ||
1125 | |||
1126 | /* Update free blocks in group info */ | ||
1127 | ext4_mb_update_group_info(grp, add); | ||
1128 | } | ||
1129 | |||
1130 | if (test_opt(sb, DEBUG)) | 1089 | if (test_opt(sb, DEBUG)) |
1131 | printk(KERN_DEBUG "EXT4-fs: extended group to %llu blocks\n", | 1090 | printk(KERN_DEBUG "EXT4-fs: extended group to %llu blocks\n", |
1132 | ext4_blocks_count(es)); | 1091 | ext4_blocks_count(es)); |