diff options
Diffstat (limited to 'fs/ext4/ialloc.c')
| -rw-r--r-- | fs/ext4/ialloc.c | 85 | 
1 files changed, 39 insertions, 46 deletions
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 1a0e183a2f04..25c4b3173fd9 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -240,56 +240,49 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)  	if (fatal)  		goto error_return; -	/* Ok, now we can actually update the inode bitmaps.. */ -	cleared = ext4_clear_bit_atomic(ext4_group_lock_ptr(sb, block_group), -					bit, bitmap_bh->b_data); -	if (!cleared) -		ext4_error(sb, "bit already cleared for inode %lu", ino); -	else { -		gdp = ext4_get_group_desc(sb, block_group, &bh2); - +	fatal = -ESRCH; +	gdp = ext4_get_group_desc(sb, block_group, &bh2); +	if (gdp) {  		BUFFER_TRACE(bh2, "get_write_access");  		fatal = ext4_journal_get_write_access(handle, bh2); -		if (fatal) goto error_return; - -		if (gdp) { -			ext4_lock_group(sb, block_group); -			count = ext4_free_inodes_count(sb, gdp) + 1; -			ext4_free_inodes_set(sb, gdp, count); -			if (is_directory) { -				count = ext4_used_dirs_count(sb, gdp) - 1; -				ext4_used_dirs_set(sb, gdp, count); -				if (sbi->s_log_groups_per_flex) { -					ext4_group_t f; - -					f = ext4_flex_group(sbi, block_group); -					atomic_dec(&sbi->s_flex_groups[f].used_dirs); -				} +	} +	ext4_lock_group(sb, block_group); +	cleared = ext4_clear_bit(bit, bitmap_bh->b_data); +	if (fatal || !cleared) { +		ext4_unlock_group(sb, block_group); +		goto out; +	} -			} -			gdp->bg_checksum = ext4_group_desc_csum(sbi, -							block_group, gdp); -			ext4_unlock_group(sb, block_group); -			percpu_counter_inc(&sbi->s_freeinodes_counter); -			if (is_directory) -				percpu_counter_dec(&sbi->s_dirs_counter); +	count = ext4_free_inodes_count(sb, gdp) + 1; +	ext4_free_inodes_set(sb, gdp, count); +	if (is_directory) { +		count = ext4_used_dirs_count(sb, gdp) - 1; +		ext4_used_dirs_set(sb, gdp, count); +		percpu_counter_dec(&sbi->s_dirs_counter); +	} +	gdp->bg_checksum = ext4_group_desc_csum(sbi, block_group, gdp); +	ext4_unlock_group(sb, block_group); -			if (sbi->s_log_groups_per_flex) { -				ext4_group_t f; +	percpu_counter_inc(&sbi->s_freeinodes_counter); +	if (sbi->s_log_groups_per_flex) { +		ext4_group_t f = ext4_flex_group(sbi, block_group); -				f = ext4_flex_group(sbi, block_group); -				atomic_inc(&sbi->s_flex_groups[f].free_inodes); -			} -		} -		BUFFER_TRACE(bh2, "call ext4_handle_dirty_metadata"); -		err = ext4_handle_dirty_metadata(handle, NULL, bh2); -		if (!fatal) fatal = err; +		atomic_inc(&sbi->s_flex_groups[f].free_inodes); +		if (is_directory) +			atomic_dec(&sbi->s_flex_groups[f].used_dirs);  	} -	BUFFER_TRACE(bitmap_bh, "call ext4_handle_dirty_metadata"); -	err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh); -	if (!fatal) -		fatal = err; -	sb->s_dirt = 1; +	BUFFER_TRACE(bh2, "call ext4_handle_dirty_metadata"); +	fatal = ext4_handle_dirty_metadata(handle, NULL, bh2); +out: +	if (cleared) { +		BUFFER_TRACE(bitmap_bh, "call ext4_handle_dirty_metadata"); +		err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh); +		if (!fatal) +			fatal = err; +		sb->s_dirt = 1; +	} else +		ext4_error(sb, "bit already cleared for inode %lu", ino); +  error_return:  	brelse(bitmap_bh);  	ext4_std_error(sb, fatal); @@ -499,7 +492,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,  	if (S_ISDIR(mode) &&  	    ((parent == sb->s_root->d_inode) || -	     (EXT4_I(parent)->i_flags & EXT4_TOPDIR_FL))) { +	     (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) {  		int best_ndir = inodes_per_group;  		int ret = -1; @@ -1041,7 +1034,7 @@ got:  	if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS)) {  		/* set extent flag only for directory, file and normal symlink*/  		if (S_ISDIR(mode) || S_ISREG(mode) || S_ISLNK(mode)) { -			EXT4_I(inode)->i_flags |= EXT4_EXTENTS_FL; +			ext4_set_inode_flag(inode, EXT4_INODE_EXTENTS);  			ext4_ext_tree_init(handle, inode);  		}  	}  | 
