]> err.no Git - linux-2.6/blobdiff - fs/ext4/balloc.c
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
[linux-2.6] / fs / ext4 / balloc.c
index 6369bacf0dcb8594bb2e7bd469696b2b56d511e7..1ae5004e93fc20ffd99a652efa6be9897a0518c1 100644 (file)
@@ -314,25 +314,28 @@ ext4_read_block_bitmap(struct super_block *sb, ext4_group_t block_group)
        if (unlikely(!bh)) {
                ext4_error(sb, __func__,
                            "Cannot read block bitmap - "
-                           "block_group = %d, block_bitmap = %llu",
-                           (int)block_group, (unsigned long long)bitmap_blk);
+                           "block_group = %lu, block_bitmap = %llu",
+                           block_group, bitmap_blk);
                return NULL;
        }
        if (bh_uptodate_or_lock(bh))
                return bh;
 
+       spin_lock(sb_bgl_lock(EXT4_SB(sb), block_group));
        if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
                ext4_init_block_bitmap(sb, bh, block_group, desc);
                set_buffer_uptodate(bh);
                unlock_buffer(bh);
+               spin_unlock(sb_bgl_lock(EXT4_SB(sb), block_group));
                return bh;
        }
+       spin_unlock(sb_bgl_lock(EXT4_SB(sb), block_group));
        if (bh_submit_read(bh) < 0) {
                put_bh(bh);
                ext4_error(sb, __func__,
                            "Cannot read block bitmap - "
-                           "block_group = %d, block_bitmap = %llu",
-                           (int)block_group, (unsigned long long)bitmap_blk);
+                           "block_group = %lu, block_bitmap = %llu",
+                           block_group, bitmap_blk);
                return NULL;
        }
        ext4_valid_block_bitmap(sb, desc, block_group, bh);
@@ -1701,7 +1704,12 @@ ext4_fsblk_t ext4_old_new_blocks(handle_t *handle, struct inode *inode,
        }
 
        sbi = EXT4_SB(sb);
-       *count = ext4_has_free_blocks(sbi, *count);
+       if (!EXT4_I(inode)->i_delalloc_reserved_flag) {
+               /*
+                * With delalloc we already reserved the blocks
+                */
+               *count = ext4_has_free_blocks(sbi, *count);
+       }
        if (*count == 0) {
                *errp = -ENOSPC;
                return 0;       /*return with ENOSPC error */
@@ -1902,7 +1910,8 @@ allocated:
        le16_add_cpu(&gdp->bg_free_blocks_count, -num);
        gdp->bg_checksum = ext4_group_desc_csum(sbi, group_no, gdp);
        spin_unlock(sb_bgl_lock(sbi, group_no));
-       percpu_counter_sub(&sbi->s_freeblocks_counter, num);
+       if (!EXT4_I(inode)->i_delalloc_reserved_flag)
+               percpu_counter_sub(&sbi->s_freeblocks_counter, num);
 
        if (sbi->s_log_groups_per_flex) {
                ext4_group_t flex_group = ext4_flex_group(sbi, group_no);
@@ -1976,40 +1985,49 @@ static ext4_fsblk_t do_blk_alloc(handle_t *handle, struct inode *inode,
 }
 
 /*
- * ext4_new_meta_block() -- allocate block for meta data (indexing) blocks
+ * ext4_new_meta_blocks() -- allocate block for meta data (indexing) blocks
  *
  * @handle:             handle to this transaction
  * @inode:              file inode
  * @goal:               given target block(filesystem wide)
+ * @count:             total number of blocks need
  * @errp:               error code
  *
- * Return allocated block number on success
+ * Return 1st allocated block numberon success, *count stores total account
+ * error stores in errp pointer
  */
-ext4_fsblk_t ext4_new_meta_block(handle_t *handle, struct inode *inode,
-               ext4_fsblk_t goal, int *errp)
+ext4_fsblk_t ext4_new_meta_blocks(handle_t *handle, struct inode *inode,
+               ext4_fsblk_t goal, unsigned long *count, int *errp)
 {
-       unsigned long count = 1;
-       return do_blk_alloc(handle, inode, 0, goal,
-                       &count, errp, EXT4_META_BLOCK);
+       ext4_fsblk_t ret;
+       ret = do_blk_alloc(handle, inode, 0, goal,
+                               count, errp, EXT4_META_BLOCK);
+       /*
+        * Account for the allocated meta blocks
+        */
+       if (!(*errp)) {
+               spin_lock(&EXT4_I(inode)->i_block_reservation_lock);
+               EXT4_I(inode)->i_allocated_meta_blocks += *count;
+               spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
+       }
+       return ret;
 }
 
 /*
- * ext4_new_meta_blocks() -- allocate block for meta data (indexing) blocks
+ * ext4_new_meta_block() -- allocate block for meta data (indexing) blocks
  *
  * @handle:             handle to this transaction
  * @inode:              file inode
  * @goal:               given target block(filesystem wide)
- * @count:             total number of blocks need
  * @errp:               error code
  *
- * Return 1st allocated block numberon success, *count stores total account
- * error stores in errp pointer
+ * Return allocated block number on success
  */
-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 ext4_new_meta_block(handle_t *handle, struct inode *inode,
+               ext4_fsblk_t goal, int *errp)
 {
-       return do_blk_alloc(handle, inode, 0, goal,
-                       count, errp, EXT4_META_BLOCK);
+       unsigned long count = 1;
+       return ext4_new_meta_blocks(handle, inode, goal, &count, errp);
 }
 
 /*