aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
authorAmir Goldstein <amir73il@users.sf.net>2011-05-09 21:40:01 -0400
committerTheodore Ts'o <tytso@mit.edu>2011-05-09 21:40:01 -0400
commite73a347b7723757bb5fb5c502814dc205a7f496d (patch)
treed65cf4e0fe070c46bdd4a6748bab549a11e0ef0b /fs/ext4
parent2cd05cc39347ddd8994b7f63ab5cb886f042477f (diff)
ext4: implement ext4_add_groupblocks() by freeing blocks
The old imlementation used to take grp->alloc_sem and set the GROUP_NEED_INIT flag, so that the buddy cache would be reloaded. The new implementation updates the buddy cache by freeing the added blocks and making them available for use, so there is no need to reload the buddy cache and there is no need to take grp->alloc_sem. Signed-off-by: Amir Goldstein <amir73il@users.sf.net> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4')
-rw-r--r--fs/ext4/mballoc.c35
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 */
4713void ext4_add_groupblocks(handle_t *handle, struct super_block *sb, 4711void 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");