aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/mballoc.c
diff options
context:
space:
mode:
authorAmir Goldstein <amir73il@users.sf.net>2011-05-09 10:46:41 -0400
committerTheodore Ts'o <tytso@mit.edu>2011-05-09 10:46:41 -0400
commit2846e82004a8d5ef0a63cd3209c84ea5cd796f11 (patch)
tree3b20c08ce64e918d4217bb95228fc597c63bf0e0 /fs/ext4/mballoc.c
parent66bb82798d9ff896271d13f5020f7fb9b7d88e1a (diff)
ext4: move ext4_add_groupblocks() to mballoc.c
In preparation for the next patch, the function ext4_add_groupblocks() is moved to mballoc.c, where it could use some static functions. Signed-off-by: Amir Goldstein <amir73il@users.sf.net> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/mballoc.c')
-rw-r--r--fs/ext4/mballoc.c124
1 files changed, 124 insertions, 0 deletions
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index 730c1a72a959..92aa05ddef66 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -4700,6 +4700,130 @@ error_return:
4700} 4700}
4701 4701
4702/** 4702/**
4703 * ext4_add_groupblocks() -- Add given blocks to an existing group
4704 * @handle: handle to this transaction
4705 * @sb: super block
4706 * @block: start physcial block to add to the block group
4707 * @count: number of blocks to free
4708 *
4709 * This marks the blocks as free in the bitmap. We ask the
4710 * mballoc to reload the buddy after this by setting group
4711 * EXT4_GROUP_INFO_NEED_INIT_BIT flag
4712 */
4713void ext4_add_groupblocks(handle_t *handle, struct super_block *sb,
4714 ext4_fsblk_t block, unsigned long count)
4715{
4716 struct buffer_head *bitmap_bh = NULL;
4717 struct buffer_head *gd_bh;
4718 ext4_group_t block_group;
4719 ext4_grpblk_t bit;
4720 unsigned int i;
4721 struct ext4_group_desc *desc;
4722 struct ext4_sb_info *sbi = EXT4_SB(sb);
4723 int err = 0, ret, blk_free_count;
4724 ext4_grpblk_t blocks_freed;
4725 struct ext4_group_info *grp;
4726
4727 ext4_debug("Adding block(s) %llu-%llu\n", block, block + count - 1);
4728
4729 ext4_get_group_no_and_offset(sb, block, &block_group, &bit);
4730 grp = ext4_get_group_info(sb, block_group);
4731 /*
4732 * Check to see if we are freeing blocks across a group
4733 * boundary.
4734 */
4735 if (bit + count > EXT4_BLOCKS_PER_GROUP(sb)) {
4736 goto error_return;
4737 }
4738 bitmap_bh = ext4_read_block_bitmap(sb, block_group);
4739 if (!bitmap_bh)
4740 goto error_return;
4741 desc = ext4_get_group_desc(sb, block_group, &gd_bh);
4742 if (!desc)
4743 goto error_return;
4744
4745 if (in_range(ext4_block_bitmap(sb, desc), block, count) ||
4746 in_range(ext4_inode_bitmap(sb, desc), block, count) ||
4747 in_range(block, ext4_inode_table(sb, desc), sbi->s_itb_per_group) ||
4748 in_range(block + count - 1, ext4_inode_table(sb, desc),
4749 sbi->s_itb_per_group)) {
4750 ext4_error(sb, "Adding blocks in system zones - "
4751 "Block = %llu, count = %lu",
4752 block, count);
4753 goto error_return;
4754 }
4755
4756 /*
4757 * We are about to add blocks to the bitmap,
4758 * so we need undo access.
4759 */
4760 BUFFER_TRACE(bitmap_bh, "getting undo access");
4761 err = ext4_journal_get_undo_access(handle, bitmap_bh);
4762 if (err)
4763 goto error_return;
4764
4765 /*
4766 * We are about to modify some metadata. Call the journal APIs
4767 * to unshare ->b_data if a currently-committing transaction is
4768 * using it
4769 */
4770 BUFFER_TRACE(gd_bh, "get_write_access");
4771 err = ext4_journal_get_write_access(handle, gd_bh);
4772 if (err)
4773 goto error_return;
4774 /*
4775 * make sure we don't allow a parallel init on other groups in the
4776 * same buddy cache
4777 */
4778 down_write(&grp->alloc_sem);
4779 for (i = 0, blocks_freed = 0; i < count; i++) {
4780 BUFFER_TRACE(bitmap_bh, "clear bit");
4781 if (!ext4_clear_bit_atomic(ext4_group_lock_ptr(sb, block_group),
4782 bit + i, bitmap_bh->b_data)) {
4783 ext4_error(sb, "bit already cleared for block %llu",
4784 (ext4_fsblk_t)(block + i));
4785 BUFFER_TRACE(bitmap_bh, "bit already cleared");
4786 } else {
4787 blocks_freed++;
4788 }
4789 }
4790 ext4_lock_group(sb, block_group);
4791 blk_free_count = blocks_freed + ext4_free_blks_count(sb, desc);
4792 ext4_free_blks_set(sb, desc, blk_free_count);
4793 desc->bg_checksum = ext4_group_desc_csum(sbi, block_group, desc);
4794 ext4_unlock_group(sb, block_group);
4795 percpu_counter_add(&sbi->s_freeblocks_counter, blocks_freed);
4796
4797 if (sbi->s_log_groups_per_flex) {
4798 ext4_group_t flex_group = ext4_flex_group(sbi, block_group);
4799 atomic_add(blocks_freed,
4800 &sbi->s_flex_groups[flex_group].free_blocks);
4801 }
4802 /*
4803 * request to reload the buddy with the
4804 * new bitmap information
4805 */
4806 set_bit(EXT4_GROUP_INFO_NEED_INIT_BIT, &(grp->bb_state));
4807 grp->bb_free += blocks_freed;
4808 up_write(&grp->alloc_sem);
4809
4810 /* We dirtied the bitmap block */
4811 BUFFER_TRACE(bitmap_bh, "dirtied bitmap block");
4812 err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh);
4813
4814 /* And the group descriptor block */
4815 BUFFER_TRACE(gd_bh, "dirtied group descriptor block");
4816 ret = ext4_handle_dirty_metadata(handle, NULL, gd_bh);
4817 if (!err)
4818 err = ret;
4819
4820error_return:
4821 brelse(bitmap_bh);
4822 ext4_std_error(sb, err);
4823 return;
4824}
4825
4826/**
4703 * ext4_trim_extent -- function to TRIM one single free extent in the group 4827 * ext4_trim_extent -- function to TRIM one single free extent in the group
4704 * @sb: super block for the file system 4828 * @sb: super block for the file system
4705 * @start: starting block of the free extent in the alloc. group 4829 * @start: starting block of the free extent in the alloc. group