diff options
Diffstat (limited to 'fs/ext4/resize.c')
| -rw-r--r-- | fs/ext4/resize.c | 49 | 
1 files changed, 35 insertions, 14 deletions
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index c5adbb318a9..bb0e80f03e2 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c @@ -42,7 +42,7 @@ int ext4_resize_begin(struct super_block *sb)  void ext4_resize_end(struct super_block *sb)  {  	clear_bit_unlock(EXT4_RESIZING, &EXT4_SB(sb)->s_resize_flags); -	smp_mb__after_clear_bit(); +	smp_mb__after_atomic();  }  static ext4_group_t ext4_meta_bg_first_group(struct super_block *sb, @@ -243,6 +243,7 @@ static int ext4_alloc_group_tables(struct super_block *sb,  	ext4_group_t group;  	ext4_group_t last_group;  	unsigned overhead; +	__u16 uninit_mask = (flexbg_size > 1) ? ~EXT4_BG_BLOCK_UNINIT : ~0;  	BUG_ON(flex_gd->count == 0 || group_data == NULL); @@ -266,7 +267,7 @@ next_group:  	src_group++;  	for (; src_group <= last_group; src_group++) {  		overhead = ext4_group_overhead_blocks(sb, src_group); -		if (overhead != 0) +		if (overhead == 0)  			last_blk += group_data[src_group - group].blocks_count;  		else  			break; @@ -280,8 +281,7 @@ next_group:  		group = ext4_get_group_number(sb, start_blk - 1);  		group -= group_data[0].group;  		group_data[group].free_blocks_count--; -		if (flexbg_size > 1) -			flex_gd->bg_flags[group] &= ~EXT4_BG_BLOCK_UNINIT; +		flex_gd->bg_flags[group] &= uninit_mask;  	}  	/* Allocate inode bitmaps */ @@ -292,22 +292,30 @@ next_group:  		group = ext4_get_group_number(sb, start_blk - 1);  		group -= group_data[0].group;  		group_data[group].free_blocks_count--; -		if (flexbg_size > 1) -			flex_gd->bg_flags[group] &= ~EXT4_BG_BLOCK_UNINIT; +		flex_gd->bg_flags[group] &= uninit_mask;  	}  	/* Allocate inode tables */  	for (; it_index < flex_gd->count; it_index++) { -		if (start_blk + EXT4_SB(sb)->s_itb_per_group > last_blk) +		unsigned int itb = EXT4_SB(sb)->s_itb_per_group; +		ext4_fsblk_t next_group_start; + +		if (start_blk + itb > last_blk)  			goto next_group;  		group_data[it_index].inode_table = start_blk; -		group = ext4_get_group_number(sb, start_blk - 1); +		group = ext4_get_group_number(sb, start_blk); +		next_group_start = ext4_group_first_block_no(sb, group + 1);  		group -= group_data[0].group; -		group_data[group].free_blocks_count -= -					EXT4_SB(sb)->s_itb_per_group; -		if (flexbg_size > 1) -			flex_gd->bg_flags[group] &= ~EXT4_BG_BLOCK_UNINIT; +		if (start_blk + itb > next_group_start) { +			flex_gd->bg_flags[group + 1] &= uninit_mask; +			overhead = start_blk + itb - next_group_start; +			group_data[group + 1].free_blocks_count -= overhead; +			itb -= overhead; +		} + +		group_data[group].free_blocks_count -= itb; +		flex_gd->bg_flags[group] &= uninit_mask;  		start_blk += EXT4_SB(sb)->s_itb_per_group;  	} @@ -340,6 +348,7 @@ static struct buffer_head *bclean(handle_t *handle, struct super_block *sb,  	bh = sb_getblk(sb, blk);  	if (unlikely(!bh))  		return ERR_PTR(-ENOMEM); +	BUFFER_TRACE(bh, "get_write_access");  	if ((err = ext4_journal_get_write_access(handle, bh))) {  		brelse(bh);  		bh = ERR_PTR(err); @@ -401,7 +410,7 @@ static int set_flexbg_block_bitmap(struct super_block *sb, handle_t *handle,  		start = ext4_group_first_block_no(sb, group);  		group -= flex_gd->groups[0].group; -		count2 = sb->s_blocksize * 8 - (block - start); +		count2 = EXT4_BLOCKS_PER_GROUP(sb) - (block - start);  		if (count2 > count)  			count2 = count; @@ -418,6 +427,7 @@ static int set_flexbg_block_bitmap(struct super_block *sb, handle_t *handle,  		if (unlikely(!bh))  			return -ENOMEM; +		BUFFER_TRACE(bh, "get_write_access");  		err = ext4_journal_get_write_access(handle, bh);  		if (err)  			return err; @@ -510,6 +520,7 @@ static int setup_new_flex_group_blocks(struct super_block *sb,  				goto out;  			} +			BUFFER_TRACE(gdb, "get_write_access");  			err = ext4_journal_get_write_access(handle, gdb);  			if (err) {  				brelse(gdb); @@ -620,7 +631,7 @@ handle_ib:  			if (err)  				goto out;  			count = group_table_count[j]; -			start = group_data[i].block_bitmap; +			start = (&group_data[i].block_bitmap)[j];  			block = start;  		} @@ -782,14 +793,17 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,  		goto exit_dind;  	} +	BUFFER_TRACE(EXT4_SB(sb)->s_sbh, "get_write_access");  	err = ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh);  	if (unlikely(err))  		goto exit_dind; +	BUFFER_TRACE(gdb_bh, "get_write_access");  	err = ext4_journal_get_write_access(handle, gdb_bh);  	if (unlikely(err))  		goto exit_dind; +	BUFFER_TRACE(dind, "get_write_access");  	err = ext4_journal_get_write_access(handle, dind);  	if (unlikely(err))  		ext4_std_error(sb, err); @@ -894,6 +908,7 @@ static int add_new_gdb_meta_bg(struct super_block *sb,  	EXT4_SB(sb)->s_group_desc = n_group_desc;  	EXT4_SB(sb)->s_gdb_count++;  	ext4_kvfree(o_group_desc); +	BUFFER_TRACE(gdb_bh, "get_write_access");  	err = ext4_journal_get_write_access(handle, gdb_bh);  	if (unlikely(err))  		brelse(gdb_bh); @@ -969,6 +984,7 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode,  	}  	for (i = 0; i < reserved_gdb; i++) { +		BUFFER_TRACE(primary[i], "get_write_access");  		if ((err = ext4_journal_get_write_access(handle, primary[i])))  			goto exit_bh;  	} @@ -1076,6 +1092,7 @@ static void update_backups(struct super_block *sb, int blk_off, char *data,  		ext4_debug("update metadata backup %llu(+%llu)\n",  			   backup_block, backup_block -  			   ext4_group_first_block_no(sb, group)); +		BUFFER_TRACE(bh, "get_write_access");  		if ((err = ext4_journal_get_write_access(handle, bh)))  			break;  		lock_buffer(bh); @@ -1155,6 +1172,7 @@ static int ext4_add_new_descs(handle_t *handle, struct super_block *sb,  		 */  		if (gdb_off) {  			gdb_bh = sbi->s_group_desc[gdb_num]; +			BUFFER_TRACE(gdb_bh, "get_write_access");  			err = ext4_journal_get_write_access(handle, gdb_bh);  			if (!err && reserved_gdb && ext4_bg_num_gdb(sb, group)) @@ -1425,6 +1443,7 @@ static int ext4_flex_group_add(struct super_block *sb,  		goto exit;  	} +	BUFFER_TRACE(sbi->s_sbh, "get_write_access");  	err = ext4_journal_get_write_access(handle, sbi->s_sbh);  	if (err)  		goto exit_journal; @@ -1637,6 +1656,7 @@ static int ext4_group_extend_no_check(struct super_block *sb,  		return err;  	} +	BUFFER_TRACE(EXT4_SB(sb)->s_sbh, "get_write_access");  	err = ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh);  	if (err) {  		ext4_warning(sb, "error %d on journal write access", err); @@ -1796,6 +1816,7 @@ static int ext4_convert_meta_bg(struct super_block *sb, struct inode *inode)  	if (IS_ERR(handle))  		return PTR_ERR(handle); +	BUFFER_TRACE(sbi->s_sbh, "get_write_access");  	err = ext4_journal_get_write_access(handle, sbi->s_sbh);  	if (err)  		goto errout;  | 
