X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=fs%2Fext3%2Fresize.c;h=9397d779c43de16283369293df8bbdcd65c4a796;hb=3bf8f5a92cd4b04e3f1e162a1b4b99759a882b5d;hp=ecf89904c1134800e609486cee2c74ff489e1f90;hpb=9cdd79c9b99873d600d397fda012fc3f57cc2776;p=linux-2.6-omap-h63xx.git diff --git a/fs/ext3/resize.c b/fs/ext3/resize.c index ecf89904c11..9397d779c43 100644 --- a/fs/ext3/resize.c +++ b/fs/ext3/resize.c @@ -11,7 +11,6 @@ #define EXT3FS_DEBUG -#include #include #include @@ -154,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 @@ -176,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); @@ -204,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; @@ -213,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); @@ -229,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; @@ -250,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; @@ -258,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); @@ -472,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; @@ -749,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); } } @@ -845,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 @@ -881,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);