diff options
Diffstat (limited to 'fs/ext4/ialloc.c')
| -rw-r--r-- | fs/ext4/ialloc.c | 73 | 
1 files changed, 34 insertions, 39 deletions
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index f18e0a08a6b..3743bd849bc 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -27,7 +27,6 @@  #include "ext4_jbd2.h"  #include "xattr.h"  #include "acl.h" -#include "group.h"  /*   * ialloc.c contains the inodes allocation and deallocation routines @@ -123,16 +122,16 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)  		unlock_buffer(bh);  		return bh;  	} -	spin_lock(sb_bgl_lock(EXT4_SB(sb), block_group)); +	ext4_lock_group(sb, block_group);  	if (desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) {  		ext4_init_inode_bitmap(sb, bh, block_group, desc);  		set_bitmap_uptodate(bh);  		set_buffer_uptodate(bh); -		spin_unlock(sb_bgl_lock(EXT4_SB(sb), block_group)); +		ext4_unlock_group(sb, block_group);  		unlock_buffer(bh);  		return bh;  	} -	spin_unlock(sb_bgl_lock(EXT4_SB(sb), block_group)); +	ext4_unlock_group(sb, block_group);  	if (buffer_uptodate(bh)) {  		/*  		 * if not uninit if bh is uptodate, @@ -247,9 +246,8 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)  		goto error_return;  	/* Ok, now we can actually update the inode bitmaps.. */ -	spin_lock(sb_bgl_lock(sbi, block_group)); -	cleared = ext4_clear_bit(bit, bitmap_bh->b_data); -	spin_unlock(sb_bgl_lock(sbi, block_group)); +	cleared = ext4_clear_bit_atomic(ext4_group_lock_ptr(sb, block_group), +					bit, bitmap_bh->b_data);  	if (!cleared)  		ext4_error(sb, "ext4_free_inode",  			   "bit already cleared for inode %lu", ino); @@ -261,7 +259,7 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)  		if (fatal) goto error_return;  		if (gdp) { -			spin_lock(sb_bgl_lock(sbi, block_group)); +			ext4_lock_group(sb, block_group);  			count = ext4_free_inodes_count(sb, gdp) + 1;  			ext4_free_inodes_set(sb, gdp, count);  			if (is_directory) { @@ -277,7 +275,7 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)  			}  			gdp->bg_checksum = ext4_group_desc_csum(sbi,  							block_group, gdp); -			spin_unlock(sb_bgl_lock(sbi, block_group)); +			ext4_unlock_group(sb, block_group);  			percpu_counter_inc(&sbi->s_freeinodes_counter);  			if (is_directory)  				percpu_counter_dec(&sbi->s_dirs_counter); @@ -316,7 +314,7 @@ error_return:  static int find_group_dir(struct super_block *sb, struct inode *parent,  				ext4_group_t *best_group)  { -	ext4_group_t ngroups = EXT4_SB(sb)->s_groups_count; +	ext4_group_t ngroups = ext4_get_groups_count(sb);  	unsigned int freei, avefreei;  	struct ext4_group_desc *desc, *best_desc = NULL;  	ext4_group_t group; @@ -349,11 +347,10 @@ static int find_group_flex(struct super_block *sb, struct inode *parent,  {  	struct ext4_sb_info *sbi = EXT4_SB(sb);  	struct ext4_group_desc *desc; -	struct buffer_head *bh;  	struct flex_groups *flex_group = sbi->s_flex_groups;  	ext4_group_t parent_group = EXT4_I(parent)->i_block_group;  	ext4_group_t parent_fbg_group = ext4_flex_group(sbi, parent_group); -	ext4_group_t ngroups = sbi->s_groups_count; +	ext4_group_t ngroups = ext4_get_groups_count(sb);  	int flex_size = ext4_flex_bg_size(sbi);  	ext4_group_t best_flex = parent_fbg_group;  	int blocks_per_flex = sbi->s_blocks_per_group * flex_size; @@ -362,7 +359,7 @@ static int find_group_flex(struct super_block *sb, struct inode *parent,  	ext4_group_t n_fbg_groups;  	ext4_group_t i; -	n_fbg_groups = (sbi->s_groups_count + flex_size - 1) >> +	n_fbg_groups = (ngroups + flex_size - 1) >>  		sbi->s_log_groups_per_flex;  find_close_to_parent: @@ -404,7 +401,7 @@ find_close_to_parent:  found_flexbg:  	for (i = best_flex * flex_size; i < ngroups &&  		     i < (best_flex + 1) * flex_size; i++) { -		desc = ext4_get_group_desc(sb, i, &bh); +		desc = ext4_get_group_desc(sb, i, NULL);  		if (ext4_free_inodes_count(sb, desc)) {  			*best_group = i;  			goto out; @@ -478,20 +475,21 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,  {  	ext4_group_t parent_group = EXT4_I(parent)->i_block_group;  	struct ext4_sb_info *sbi = EXT4_SB(sb); -	ext4_group_t ngroups = sbi->s_groups_count; +	ext4_group_t real_ngroups = ext4_get_groups_count(sb);  	int inodes_per_group = EXT4_INODES_PER_GROUP(sb);  	unsigned int freei, avefreei;  	ext4_fsblk_t freeb, avefreeb;  	unsigned int ndirs;  	int max_dirs, min_inodes;  	ext4_grpblk_t min_blocks; -	ext4_group_t i, grp, g; +	ext4_group_t i, grp, g, ngroups;  	struct ext4_group_desc *desc;  	struct orlov_stats stats;  	int flex_size = ext4_flex_bg_size(sbi); +	ngroups = real_ngroups;  	if (flex_size > 1) { -		ngroups = (ngroups + flex_size - 1) >> +		ngroups = (real_ngroups + flex_size - 1) >>  			sbi->s_log_groups_per_flex;  		parent_group >>= sbi->s_log_groups_per_flex;  	} @@ -543,7 +541,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,  		 */  		grp *= flex_size;  		for (i = 0; i < flex_size; i++) { -			if (grp+i >= sbi->s_groups_count) +			if (grp+i >= real_ngroups)  				break;  			desc = ext4_get_group_desc(sb, grp+i, NULL);  			if (desc && ext4_free_inodes_count(sb, desc)) { @@ -583,7 +581,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,  	}  fallback: -	ngroups = sbi->s_groups_count; +	ngroups = real_ngroups;  	avefreei = freei / ngroups;  fallback_retry:  	parent_group = EXT4_I(parent)->i_block_group; @@ -613,9 +611,8 @@ static int find_group_other(struct super_block *sb, struct inode *parent,  			    ext4_group_t *group, int mode)  {  	ext4_group_t parent_group = EXT4_I(parent)->i_block_group; -	ext4_group_t ngroups = EXT4_SB(sb)->s_groups_count; +	ext4_group_t i, last, ngroups = ext4_get_groups_count(sb);  	struct ext4_group_desc *desc; -	ext4_group_t i, last;  	int flex_size = ext4_flex_bg_size(EXT4_SB(sb));  	/* @@ -708,10 +705,10 @@ static int find_group_other(struct super_block *sb, struct inode *parent,  /*   * claim the inode from the inode bitmap. If the group - * is uninit we need to take the groups's sb_bgl_lock + * is uninit we need to take the groups's ext4_group_lock   * and clear the uninit flag. The inode bitmap update   * and group desc uninit flag clear should be done - * after holding sb_bgl_lock so that ext4_read_inode_bitmap + * after holding ext4_group_lock so that ext4_read_inode_bitmap   * doesn't race with the ext4_claim_inode   */  static int ext4_claim_inode(struct super_block *sb, @@ -722,7 +719,7 @@ static int ext4_claim_inode(struct super_block *sb,  	struct ext4_sb_info *sbi = EXT4_SB(sb);  	struct ext4_group_desc *gdp = ext4_get_group_desc(sb, group, NULL); -	spin_lock(sb_bgl_lock(sbi, group)); +	ext4_lock_group(sb, group);  	if (ext4_set_bit(ino, inode_bitmap_bh->b_data)) {  		/* not a free inode */  		retval = 1; @@ -731,7 +728,7 @@ static int ext4_claim_inode(struct super_block *sb,  	ino++;  	if ((group == 0 && ino < EXT4_FIRST_INO(sb)) ||  			ino > EXT4_INODES_PER_GROUP(sb)) { -		spin_unlock(sb_bgl_lock(sbi, group)); +		ext4_unlock_group(sb, group);  		ext4_error(sb, __func__,  			   "reserved inode or inode > inodes count - "  			   "block_group = %u, inode=%lu", group, @@ -780,7 +777,7 @@ static int ext4_claim_inode(struct super_block *sb,  	}  	gdp->bg_checksum = ext4_group_desc_csum(sbi, group, gdp);  err_ret: -	spin_unlock(sb_bgl_lock(sbi, group)); +	ext4_unlock_group(sb, group);  	return retval;  } @@ -799,11 +796,10 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode)  	struct super_block *sb;  	struct buffer_head *inode_bitmap_bh = NULL;  	struct buffer_head *group_desc_bh; -	ext4_group_t group = 0; +	ext4_group_t ngroups, group = 0;  	unsigned long ino = 0;  	struct inode *inode;  	struct ext4_group_desc *gdp = NULL; -	struct ext4_super_block *es;  	struct ext4_inode_info *ei;  	struct ext4_sb_info *sbi;  	int ret2, err = 0; @@ -818,15 +814,14 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode)  		return ERR_PTR(-EPERM);  	sb = dir->i_sb; +	ngroups = ext4_get_groups_count(sb);  	trace_mark(ext4_request_inode, "dev %s dir %lu mode %d", sb->s_id,  		   dir->i_ino, mode);  	inode = new_inode(sb);  	if (!inode)  		return ERR_PTR(-ENOMEM);  	ei = EXT4_I(inode); -  	sbi = EXT4_SB(sb); -	es = sbi->s_es;  	if (sbi->s_log_groups_per_flex && test_opt(sb, OLDALLOC)) {  		ret2 = find_group_flex(sb, dir, &group); @@ -856,7 +851,7 @@ got_group:  	if (ret2 == -1)  		goto out; -	for (i = 0; i < sbi->s_groups_count; i++) { +	for (i = 0; i < ngroups; i++) {  		err = -EIO;  		gdp = ext4_get_group_desc(sb, group, &group_desc_bh); @@ -917,7 +912,7 @@ repeat_in_this_group:  		 * group descriptor metadata has not yet been updated.  		 * So we just go onto the next blockgroup.  		 */ -		if (++group == sbi->s_groups_count) +		if (++group == ngroups)  			group = 0;  	}  	err = -ENOSPC; @@ -938,7 +933,7 @@ got:  		}  		free = 0; -		spin_lock(sb_bgl_lock(sbi, group)); +		ext4_lock_group(sb, group);  		/* recheck and clear flag under lock if we still need to */  		if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {  			free = ext4_free_blocks_after_init(sb, group, gdp); @@ -947,7 +942,7 @@ got:  			gdp->bg_checksum = ext4_group_desc_csum(sbi, group,  								gdp);  		} -		spin_unlock(sb_bgl_lock(sbi, group)); +		ext4_unlock_group(sb, group);  		/* Don't need to dirty bitmap block if we didn't change it */  		if (free) { @@ -1158,7 +1153,7 @@ unsigned long ext4_count_free_inodes(struct super_block *sb)  {  	unsigned long desc_count;  	struct ext4_group_desc *gdp; -	ext4_group_t i; +	ext4_group_t i, ngroups = ext4_get_groups_count(sb);  #ifdef EXT4FS_DEBUG  	struct ext4_super_block *es;  	unsigned long bitmap_count, x; @@ -1168,7 +1163,7 @@ unsigned long ext4_count_free_inodes(struct super_block *sb)  	desc_count = 0;  	bitmap_count = 0;  	gdp = NULL; -	for (i = 0; i < EXT4_SB(sb)->s_groups_count; i++) { +	for (i = 0; i < ngroups; i++) {  		gdp = ext4_get_group_desc(sb, i, NULL);  		if (!gdp)  			continue; @@ -1190,7 +1185,7 @@ unsigned long ext4_count_free_inodes(struct super_block *sb)  	return desc_count;  #else  	desc_count = 0; -	for (i = 0; i < EXT4_SB(sb)->s_groups_count; i++) { +	for (i = 0; i < ngroups; i++) {  		gdp = ext4_get_group_desc(sb, i, NULL);  		if (!gdp)  			continue; @@ -1205,9 +1200,9 @@ unsigned long ext4_count_free_inodes(struct super_block *sb)  unsigned long ext4_count_dirs(struct super_block * sb)  {  	unsigned long count = 0; -	ext4_group_t i; +	ext4_group_t i, ngroups = ext4_get_groups_count(sb); -	for (i = 0; i < EXT4_SB(sb)->s_groups_count; i++) { +	for (i = 0; i < ngroups; i++) {  		struct ext4_group_desc *gdp = ext4_get_group_desc(sb, i, NULL);  		if (!gdp)  			continue;  |