ext3: fix wrong gfp type under transaction
[sfrench/cifs-2.6.git] / fs / ext3 / resize.c
index 2c97e09c6c6b2a3048898f69d76cb0522061f389..0e97b6e07cb03556437c55924003d103efd44f17 100644 (file)
@@ -153,6 +153,34 @@ static void mark_bitmap_end(int start_bit, int end_bit, char *bitmap)
                memset(bitmap + (i >> 3), 0xff, (end_bit - i) >> 3);
 }
 
+/*
+ * If we have fewer than thresh credits, extend by EXT3_MAX_TRANS_DATA.
+ * If that fails, restart the transaction & regain write access for the
+ * buffer head which is used for block_bitmap modifications.
+ */
+static int extend_or_restart_transaction(handle_t *handle, int thresh,
+                                        struct buffer_head *bh)
+{
+       int err;
+
+       if (handle->h_buffer_credits >= thresh)
+               return 0;
+
+       err = ext3_journal_extend(handle, EXT3_MAX_TRANS_DATA);
+       if (err < 0)
+               return err;
+       if (err) {
+               err = ext3_journal_restart(handle, EXT3_MAX_TRANS_DATA);
+               if (err)
+                       return err;
+               err = ext3_journal_get_write_access(handle, bh);
+               if (err)
+                       return err;
+       }
+
+       return 0;
+}
+
 /*
  * Set up the block and inode bitmaps, and the inode table for the new group.
  * This doesn't need to be part of the main transaction, since we are only
@@ -175,8 +203,9 @@ static int setup_new_group_blocks(struct super_block *sb,
        int i;
        int err = 0, err2;
 
-       handle = ext3_journal_start_sb(sb, reserved_gdb + gdblocks +
-                                      2 + sbi->s_itb_per_group);
+       /* This transaction may be extended/restarted along the way */
+       handle = ext3_journal_start_sb(sb, EXT3_MAX_TRANS_DATA);
+
        if (IS_ERR(handle))
                return PTR_ERR(handle);
 
@@ -203,6 +232,10 @@ static int setup_new_group_blocks(struct super_block *sb,
 
                ext3_debug("update backup group %#04lx (+%d)\n", block, bit);
 
+               err = extend_or_restart_transaction(handle, 1, bh);
+               if (err)
+                       goto exit_bh;
+
                gdb = sb_getblk(sb, block);
                if (!gdb) {
                        err = -EIO;
@@ -212,10 +245,10 @@ static int setup_new_group_blocks(struct super_block *sb,
                        brelse(gdb);
                        goto exit_bh;
                }
-               lock_buffer(bh);
-               memcpy(gdb->b_data, sbi->s_group_desc[i]->b_data, bh->b_size);
+               lock_buffer(gdb);
+               memcpy(gdb->b_data, sbi->s_group_desc[i]->b_data, gdb->b_size);
                set_buffer_uptodate(gdb);
-               unlock_buffer(bh);
+               unlock_buffer(gdb);
                ext3_journal_dirty_metadata(handle, gdb);
                ext3_set_bit(bit, bh->b_data);
                brelse(gdb);
@@ -228,6 +261,10 @@ static int setup_new_group_blocks(struct super_block *sb,
 
                ext3_debug("clear reserved block %#04lx (+%d)\n", block, bit);
 
+               err = extend_or_restart_transaction(handle, 1, bh);
+               if (err)
+                       goto exit_bh;
+
                if (IS_ERR(gdb = bclean(handle, sb, block))) {
                        err = PTR_ERR(bh);
                        goto exit_bh;
@@ -249,6 +286,11 @@ static int setup_new_group_blocks(struct super_block *sb,
                struct buffer_head *it;
 
                ext3_debug("clear inode block %#04lx (+%d)\n", block, bit);
+
+               err = extend_or_restart_transaction(handle, 1, bh);
+               if (err)
+                       goto exit_bh;
+
                if (IS_ERR(it = bclean(handle, sb, block))) {
                        err = PTR_ERR(it);
                        goto exit_bh;
@@ -257,6 +299,11 @@ static int setup_new_group_blocks(struct super_block *sb,
                brelse(it);
                ext3_set_bit(bit, bh->b_data);
        }
+
+       err = extend_or_restart_transaction(handle, 2, bh);
+       if (err)
+               goto exit_bh;
+
        mark_bitmap_end(input->blocks_count, EXT3_BLOCKS_PER_GROUP(sb),
                        bh->b_data);
        ext3_journal_dirty_metadata(handle, bh);
@@ -438,7 +485,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
                goto exit_dindj;
 
        n_group_desc = kmalloc((gdb_num + 1) * sizeof(struct buffer_head *),
-                       GFP_KERNEL);
+                       GFP_NOFS);
        if (!n_group_desc) {
                err = -ENOMEM;
                ext3_warning (sb, __FUNCTION__,
@@ -471,8 +518,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
        EXT3_SB(sb)->s_gdb_count++;
        kfree(o_group_desc);
 
-       es->s_reserved_gdt_blocks =
-               cpu_to_le16(le16_to_cpu(es->s_reserved_gdt_blocks) - 1);
+       le16_add_cpu(&es->s_reserved_gdt_blocks, -1);
        ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
 
        return 0;
@@ -522,7 +568,7 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode,
        int res, i;
        int err;
 
-       primary = kmalloc(reserved_gdb * sizeof(*primary), GFP_KERNEL);
+       primary = kmalloc(reserved_gdb * sizeof(*primary), GFP_NOFS);
        if (!primary)
                return -ENOMEM;
 
@@ -748,12 +794,11 @@ int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input)
                                     "No reserved GDT blocks, can't resize");
                        return -EPERM;
                }
-               inode = iget(sb, EXT3_RESIZE_INO);
-               if (!inode || is_bad_inode(inode)) {
+               inode = ext3_iget(sb, EXT3_RESIZE_INO);
+               if (IS_ERR(inode)) {
                        ext3_warning(sb, __FUNCTION__,
                                     "Error opening resize inode");
-                       iput(inode);
-                       return -ENOENT;
+                       return PTR_ERR(inode);
                }
        }
 
@@ -844,10 +889,8 @@ int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input)
         * blocks/inodes before the group is live won't actually let us
         * allocate the new space yet.
         */
-       es->s_blocks_count = cpu_to_le32(le32_to_cpu(es->s_blocks_count) +
-               input->blocks_count);
-       es->s_inodes_count = cpu_to_le32(le32_to_cpu(es->s_inodes_count) +
-               EXT3_INODES_PER_GROUP(sb));
+       le32_add_cpu(&es->s_blocks_count, input->blocks_count);
+       le32_add_cpu(&es->s_inodes_count, EXT3_INODES_PER_GROUP(sb));
 
        /*
         * We need to protect s_groups_count against other CPUs seeing
@@ -880,13 +923,12 @@ int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input)
 
        /* Update the reserved block counts only once the new group is
         * active. */
-       es->s_r_blocks_count = cpu_to_le32(le32_to_cpu(es->s_r_blocks_count) +
-               input->reserved_blocks);
+       le32_add_cpu(&es->s_r_blocks_count, input->reserved_blocks);
 
        /* Update the free space counts */
-       percpu_counter_mod(&sbi->s_freeblocks_counter,
+       percpu_counter_add(&sbi->s_freeblocks_counter,
                           input->free_blocks_count);
-       percpu_counter_mod(&sbi->s_freeinodes_counter,
+       percpu_counter_add(&sbi->s_freeinodes_counter,
                           EXT3_INODES_PER_GROUP(sb));
 
        ext3_journal_dirty_metadata(handle, sbi->s_sbh);