Merge branches 'core-fixes-for-linus' and 'irq-fixes-for-linus' of git://git.kernel...
[pandora-kernel.git] / fs / ext4 / balloc.c
index 1c67139..264f694 100644 (file)
@@ -361,130 +361,6 @@ ext4_read_block_bitmap(struct super_block *sb, ext4_group_t block_group)
        return bh;
 }
 
-/**
- * ext4_add_groupblocks() -- Add given blocks to an existing group
- * @handle:                    handle to this transaction
- * @sb:                                super block
- * @block:                     start physcial block to add to the block group
- * @count:                     number of blocks to free
- *
- * This marks the blocks as free in the bitmap. We ask the
- * mballoc to reload the buddy after this by setting group
- * EXT4_GROUP_INFO_NEED_INIT_BIT flag
- */
-void ext4_add_groupblocks(handle_t *handle, struct super_block *sb,
-                        ext4_fsblk_t block, unsigned long count)
-{
-       struct buffer_head *bitmap_bh = NULL;
-       struct buffer_head *gd_bh;
-       ext4_group_t block_group;
-       ext4_grpblk_t bit;
-       unsigned int i;
-       struct ext4_group_desc *desc;
-       struct ext4_sb_info *sbi = EXT4_SB(sb);
-       int err = 0, ret, blk_free_count;
-       ext4_grpblk_t blocks_freed;
-       struct ext4_group_info *grp;
-
-       ext4_debug("Adding block(s) %llu-%llu\n", block, block + count - 1);
-
-       ext4_get_group_no_and_offset(sb, block, &block_group, &bit);
-       grp = ext4_get_group_info(sb, block_group);
-       /*
-        * Check to see if we are freeing blocks across a group
-        * boundary.
-        */
-       if (bit + count > EXT4_BLOCKS_PER_GROUP(sb)) {
-               goto error_return;
-       }
-       bitmap_bh = ext4_read_block_bitmap(sb, block_group);
-       if (!bitmap_bh)
-               goto error_return;
-       desc = ext4_get_group_desc(sb, block_group, &gd_bh);
-       if (!desc)
-               goto error_return;
-
-       if (in_range(ext4_block_bitmap(sb, desc), block, count) ||
-           in_range(ext4_inode_bitmap(sb, desc), block, count) ||
-           in_range(block, ext4_inode_table(sb, desc), sbi->s_itb_per_group) ||
-           in_range(block + count - 1, ext4_inode_table(sb, desc),
-                    sbi->s_itb_per_group)) {
-               ext4_error(sb, "Adding blocks in system zones - "
-                          "Block = %llu, count = %lu",
-                          block, count);
-               goto error_return;
-       }
-
-       /*
-        * We are about to add blocks to the bitmap,
-        * so we need undo access.
-        */
-       BUFFER_TRACE(bitmap_bh, "getting undo access");
-       err = ext4_journal_get_undo_access(handle, bitmap_bh);
-       if (err)
-               goto error_return;
-
-       /*
-        * We are about to modify some metadata.  Call the journal APIs
-        * to unshare ->b_data if a currently-committing transaction is
-        * using it
-        */
-       BUFFER_TRACE(gd_bh, "get_write_access");
-       err = ext4_journal_get_write_access(handle, gd_bh);
-       if (err)
-               goto error_return;
-       /*
-        * make sure we don't allow a parallel init on other groups in the
-        * same buddy cache
-        */
-       down_write(&grp->alloc_sem);
-       for (i = 0, blocks_freed = 0; i < count; i++) {
-               BUFFER_TRACE(bitmap_bh, "clear bit");
-               if (!ext4_clear_bit_atomic(ext4_group_lock_ptr(sb, block_group),
-                                               bit + i, bitmap_bh->b_data)) {
-                       ext4_error(sb, "bit already cleared for block %llu",
-                                  (ext4_fsblk_t)(block + i));
-                       BUFFER_TRACE(bitmap_bh, "bit already cleared");
-               } else {
-                       blocks_freed++;
-               }
-       }
-       ext4_lock_group(sb, block_group);
-       blk_free_count = blocks_freed + ext4_free_blks_count(sb, desc);
-       ext4_free_blks_set(sb, desc, blk_free_count);
-       desc->bg_checksum = ext4_group_desc_csum(sbi, block_group, desc);
-       ext4_unlock_group(sb, block_group);
-       percpu_counter_add(&sbi->s_freeblocks_counter, blocks_freed);
-
-       if (sbi->s_log_groups_per_flex) {
-               ext4_group_t flex_group = ext4_flex_group(sbi, block_group);
-               atomic_add(blocks_freed,
-                          &sbi->s_flex_groups[flex_group].free_blocks);
-       }
-       /*
-        * request to reload the buddy with the
-        * new bitmap information
-        */
-       set_bit(EXT4_GROUP_INFO_NEED_INIT_BIT, &(grp->bb_state));
-       grp->bb_free += blocks_freed;
-       up_write(&grp->alloc_sem);
-
-       /* We dirtied the bitmap block */
-       BUFFER_TRACE(bitmap_bh, "dirtied bitmap block");
-       err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh);
-
-       /* And the group descriptor block */
-       BUFFER_TRACE(gd_bh, "dirtied group descriptor block");
-       ret = ext4_handle_dirty_metadata(handle, NULL, gd_bh);
-       if (!err)
-               err = ret;
-
-error_return:
-       brelse(bitmap_bh);
-       ext4_std_error(sb, err);
-       return;
-}
-
 /**
  * ext4_has_free_blocks()
  * @sbi:       in-core super block structure.
@@ -493,7 +369,8 @@ error_return:
  * Check if filesystem has nblocks free & available for allocation.
  * On success return 1, return 0 on failure.
  */
-static int ext4_has_free_blocks(struct ext4_sb_info *sbi, s64 nblocks)
+static int ext4_has_free_blocks(struct ext4_sb_info *sbi,
+                               s64 nblocks, unsigned int flags)
 {
        s64 free_blocks, dirty_blocks, root_blocks;
        struct percpu_counter *fbc = &sbi->s_freeblocks_counter;
@@ -507,11 +384,6 @@ static int ext4_has_free_blocks(struct ext4_sb_info *sbi, s64 nblocks)
                                                EXT4_FREEBLOCKS_WATERMARK) {
                free_blocks  = percpu_counter_sum_positive(fbc);
                dirty_blocks = percpu_counter_sum_positive(dbc);
-               if (dirty_blocks < 0) {
-                       printk(KERN_CRIT "Dirty block accounting "
-                                       "went wrong %lld\n",
-                                       (long long)dirty_blocks);
-               }
        }
        /* Check whether we have space after
         * accounting for current dirty blocks & root reserved blocks.
@@ -522,7 +394,9 @@ static int ext4_has_free_blocks(struct ext4_sb_info *sbi, s64 nblocks)
        /* Hm, nope.  Are (enough) root reserved blocks available? */
        if (sbi->s_resuid == current_fsuid() ||
            ((sbi->s_resgid != 0) && in_group_p(sbi->s_resgid)) ||
-           capable(CAP_SYS_RESOURCE)) {
+           capable(CAP_SYS_RESOURCE) ||
+               (flags & EXT4_MB_USE_ROOT_BLOCKS)) {
+
                if (free_blocks >= (nblocks + dirty_blocks))
                        return 1;
        }
@@ -531,9 +405,9 @@ static int ext4_has_free_blocks(struct ext4_sb_info *sbi, s64 nblocks)
 }
 
 int ext4_claim_free_blocks(struct ext4_sb_info *sbi,
-                                               s64 nblocks)
+                          s64 nblocks, unsigned int flags)
 {
-       if (ext4_has_free_blocks(sbi, nblocks)) {
+       if (ext4_has_free_blocks(sbi, nblocks, flags)) {
                percpu_counter_add(&sbi->s_dirtyblocks_counter, nblocks);
                return 0;
        } else
@@ -554,7 +428,7 @@ int ext4_claim_free_blocks(struct ext4_sb_info *sbi,
  */
 int ext4_should_retry_alloc(struct super_block *sb, int *retries)
 {
-       if (!ext4_has_free_blocks(EXT4_SB(sb), 1) ||
+       if (!ext4_has_free_blocks(EXT4_SB(sb), 1, 0) ||
            (*retries)++ > 3 ||
            !EXT4_SB(sb)->s_journal)
                return 0;
@@ -577,7 +451,8 @@ int ext4_should_retry_alloc(struct super_block *sb, int *retries)
  * error stores in errp pointer
  */
 ext4_fsblk_t ext4_new_meta_blocks(handle_t *handle, struct inode *inode,
-               ext4_fsblk_t goal, unsigned long *count, int *errp)
+                                 ext4_fsblk_t goal, unsigned int flags,
+                                 unsigned long *count, int *errp)
 {
        struct ext4_allocation_request ar;
        ext4_fsblk_t ret;
@@ -587,6 +462,7 @@ ext4_fsblk_t ext4_new_meta_blocks(handle_t *handle, struct inode *inode,
        ar.inode = inode;
        ar.goal = goal;
        ar.len = count ? *count : 1;
+       ar.flags = flags;
 
        ret = ext4_mb_new_blocks(handle, &ar, errp);
        if (count)