diff options
-rw-r--r-- | fs/ext4/mballoc.c | 35 |
1 files changed, 18 insertions, 17 deletions
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 307d447bbc43..65329f148da5 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c | |||
@@ -4706,9 +4706,7 @@ error_return: | |||
4706 | * @block: start physcial block to add to the block group | 4706 | * @block: start physcial block to add to the block group |
4707 | * @count: number of blocks to free | 4707 | * @count: number of blocks to free |
4708 | * | 4708 | * |
4709 | * This marks the blocks as free in the bitmap. We ask the | 4709 | * This marks the blocks as free in the bitmap and buddy. |
4710 | * mballoc to reload the buddy after this by setting group | ||
4711 | * EXT4_GROUP_INFO_NEED_INIT_BIT flag | ||
4712 | */ | 4710 | */ |
4713 | void ext4_add_groupblocks(handle_t *handle, struct super_block *sb, | 4711 | void ext4_add_groupblocks(handle_t *handle, struct super_block *sb, |
4714 | ext4_fsblk_t block, unsigned long count) | 4712 | ext4_fsblk_t block, unsigned long count) |
@@ -4720,6 +4718,7 @@ void ext4_add_groupblocks(handle_t *handle, struct super_block *sb, | |||
4720 | unsigned int i; | 4718 | unsigned int i; |
4721 | struct ext4_group_desc *desc; | 4719 | struct ext4_group_desc *desc; |
4722 | struct ext4_sb_info *sbi = EXT4_SB(sb); | 4720 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
4721 | struct ext4_buddy e4b; | ||
4723 | int err = 0, ret, blk_free_count; | 4722 | int err = 0, ret, blk_free_count; |
4724 | ext4_grpblk_t blocks_freed; | 4723 | ext4_grpblk_t blocks_freed; |
4725 | struct ext4_group_info *grp; | 4724 | struct ext4_group_info *grp; |
@@ -4767,15 +4766,10 @@ void ext4_add_groupblocks(handle_t *handle, struct super_block *sb, | |||
4767 | err = ext4_journal_get_write_access(handle, gd_bh); | 4766 | err = ext4_journal_get_write_access(handle, gd_bh); |
4768 | if (err) | 4767 | if (err) |
4769 | goto error_return; | 4768 | goto error_return; |
4770 | /* | 4769 | |
4771 | * make sure we don't allow a parallel init on other groups in the | ||
4772 | * same buddy cache | ||
4773 | */ | ||
4774 | down_write(&grp->alloc_sem); | ||
4775 | for (i = 0, blocks_freed = 0; i < count; i++) { | 4770 | for (i = 0, blocks_freed = 0; i < count; i++) { |
4776 | BUFFER_TRACE(bitmap_bh, "clear bit"); | 4771 | BUFFER_TRACE(bitmap_bh, "clear bit"); |
4777 | if (!ext4_clear_bit_atomic(ext4_group_lock_ptr(sb, block_group), | 4772 | if (!mb_test_bit(bit + i, bitmap_bh->b_data)) { |
4778 | bit + i, bitmap_bh->b_data)) { | ||
4779 | ext4_error(sb, "bit already cleared for block %llu", | 4773 | ext4_error(sb, "bit already cleared for block %llu", |
4780 | (ext4_fsblk_t)(block + i)); | 4774 | (ext4_fsblk_t)(block + i)); |
4781 | BUFFER_TRACE(bitmap_bh, "bit already cleared"); | 4775 | BUFFER_TRACE(bitmap_bh, "bit already cleared"); |
@@ -4783,7 +4777,19 @@ void ext4_add_groupblocks(handle_t *handle, struct super_block *sb, | |||
4783 | blocks_freed++; | 4777 | blocks_freed++; |
4784 | } | 4778 | } |
4785 | } | 4779 | } |
4780 | |||
4781 | err = ext4_mb_load_buddy(sb, block_group, &e4b); | ||
4782 | if (err) | ||
4783 | goto error_return; | ||
4784 | |||
4785 | /* | ||
4786 | * need to update group_info->bb_free and bitmap | ||
4787 | * with group lock held. generate_buddy look at | ||
4788 | * them with group lock_held | ||
4789 | */ | ||
4786 | ext4_lock_group(sb, block_group); | 4790 | ext4_lock_group(sb, block_group); |
4791 | mb_clear_bits(bitmap_bh->b_data, bit, count); | ||
4792 | mb_free_blocks(NULL, &e4b, bit, count); | ||
4787 | blk_free_count = blocks_freed + ext4_free_blks_count(sb, desc); | 4793 | blk_free_count = blocks_freed + ext4_free_blks_count(sb, desc); |
4788 | ext4_free_blks_set(sb, desc, blk_free_count); | 4794 | ext4_free_blks_set(sb, desc, blk_free_count); |
4789 | desc->bg_checksum = ext4_group_desc_csum(sbi, block_group, desc); | 4795 | desc->bg_checksum = ext4_group_desc_csum(sbi, block_group, desc); |
@@ -4795,13 +4801,8 @@ void ext4_add_groupblocks(handle_t *handle, struct super_block *sb, | |||
4795 | atomic_add(blocks_freed, | 4801 | atomic_add(blocks_freed, |
4796 | &sbi->s_flex_groups[flex_group].free_blocks); | 4802 | &sbi->s_flex_groups[flex_group].free_blocks); |
4797 | } | 4803 | } |
4798 | /* | 4804 | |
4799 | * request to reload the buddy with the | 4805 | ext4_mb_unload_buddy(&e4b); |
4800 | * new bitmap information | ||
4801 | */ | ||
4802 | set_bit(EXT4_GROUP_INFO_NEED_INIT_BIT, &(grp->bb_state)); | ||
4803 | grp->bb_free += blocks_freed; | ||
4804 | up_write(&grp->alloc_sem); | ||
4805 | 4806 | ||
4806 | /* We dirtied the bitmap block */ | 4807 | /* We dirtied the bitmap block */ |
4807 | BUFFER_TRACE(bitmap_bh, "dirtied bitmap block"); | 4808 | BUFFER_TRACE(bitmap_bh, "dirtied bitmap block"); |