diff options
Diffstat (limited to 'fs/ext4/ialloc.c')
| -rw-r--r-- | fs/ext4/ialloc.c | 85 | 
1 files changed, 49 insertions, 36 deletions
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 4c358f711ce..18d36d85f5c 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -666,6 +666,23 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir,  	ei = EXT4_I(inode);  	sbi = EXT4_SB(sb); +	/* +	 * Initalize owners and quota early so that we don't have to account +	 * for quota initialization worst case in standard inode creating +	 * transaction +	 */ +	if (owner) { +		inode->i_mode = mode; +		i_uid_write(inode, owner[0]); +		i_gid_write(inode, owner[1]); +	} else if (test_opt(sb, GRPID)) { +		inode->i_mode = mode; +		inode->i_uid = current_fsuid(); +		inode->i_gid = dir->i_gid; +	} else +		inode_init_owner(inode, dir, mode); +	dquot_initialize(inode); +  	if (!goal)  		goal = sbi->s_inode_goal; @@ -697,7 +714,7 @@ got_group:  		gdp = ext4_get_group_desc(sb, group, &group_desc_bh);  		if (!gdp) -			goto fail; +			goto out;  		/*  		 * Check free inodes count before loading bitmap. @@ -711,7 +728,7 @@ got_group:  		brelse(inode_bitmap_bh);  		inode_bitmap_bh = ext4_read_inode_bitmap(sb, group);  		if (!inode_bitmap_bh) -			goto fail; +			goto out;  repeat_in_this_group:  		ino = ext4_find_next_zero_bit((unsigned long *) @@ -733,13 +750,16 @@ repeat_in_this_group:  							 handle_type, nblocks);  			if (IS_ERR(handle)) {  				err = PTR_ERR(handle); -				goto fail; +				ext4_std_error(sb, err); +				goto out;  			}  		}  		BUFFER_TRACE(inode_bitmap_bh, "get_write_access");  		err = ext4_journal_get_write_access(handle, inode_bitmap_bh); -		if (err) -			goto fail; +		if (err) { +			ext4_std_error(sb, err); +			goto out; +		}  		ext4_lock_group(sb, group);  		ret2 = ext4_test_and_set_bit(ino, inode_bitmap_bh->b_data);  		ext4_unlock_group(sb, group); @@ -755,8 +775,10 @@ repeat_in_this_group:  got:  	BUFFER_TRACE(inode_bitmap_bh, "call ext4_handle_dirty_metadata");  	err = ext4_handle_dirty_metadata(handle, NULL, inode_bitmap_bh); -	if (err) -		goto fail; +	if (err) { +		ext4_std_error(sb, err); +		goto out; +	}  	/* We may have to initialize the block bitmap if it isn't already */  	if (ext4_has_group_desc_csum(sb) && @@ -768,7 +790,8 @@ got:  		err = ext4_journal_get_write_access(handle, block_bitmap_bh);  		if (err) {  			brelse(block_bitmap_bh); -			goto fail; +			ext4_std_error(sb, err); +			goto out;  		}  		BUFFER_TRACE(block_bitmap_bh, "dirty block bitmap"); @@ -787,14 +810,18 @@ got:  		ext4_unlock_group(sb, group);  		brelse(block_bitmap_bh); -		if (err) -			goto fail; +		if (err) { +			ext4_std_error(sb, err); +			goto out; +		}  	}  	BUFFER_TRACE(group_desc_bh, "get_write_access");  	err = ext4_journal_get_write_access(handle, group_desc_bh); -	if (err) -		goto fail; +	if (err) { +		ext4_std_error(sb, err); +		goto out; +	}  	/* Update the relevant bg descriptor fields */  	if (ext4_has_group_desc_csum(sb)) { @@ -840,8 +867,10 @@ got:  	BUFFER_TRACE(group_desc_bh, "call ext4_handle_dirty_metadata");  	err = ext4_handle_dirty_metadata(handle, NULL, group_desc_bh); -	if (err) -		goto fail; +	if (err) { +		ext4_std_error(sb, err); +		goto out; +	}  	percpu_counter_dec(&sbi->s_freeinodes_counter);  	if (S_ISDIR(mode)) @@ -851,16 +880,6 @@ got:  		flex_group = ext4_flex_group(sbi, group);  		atomic_dec(&sbi->s_flex_groups[flex_group].free_inodes);  	} -	if (owner) { -		inode->i_mode = mode; -		i_uid_write(inode, owner[0]); -		i_gid_write(inode, owner[1]); -	} else if (test_opt(sb, GRPID)) { -		inode->i_mode = mode; -		inode->i_uid = current_fsuid(); -		inode->i_gid = dir->i_gid; -	} else -		inode_init_owner(inode, dir, mode);  	inode->i_ino = ino + group * EXT4_INODES_PER_GROUP(sb);  	/* This is the optimal IO size (for stat), not the fs block size */ @@ -889,7 +908,9 @@ got:  		 * twice.  		 */  		err = -EIO; -		goto fail; +		ext4_error(sb, "failed to insert inode %lu: doubly allocated?", +			   inode->i_ino); +		goto out;  	}  	spin_lock(&sbi->s_next_gen_lock);  	inode->i_generation = sbi->s_next_generation++; @@ -917,7 +938,6 @@ got:  		ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);  	ret = inode; -	dquot_initialize(inode);  	err = dquot_alloc_inode(inode);  	if (err)  		goto fail_drop; @@ -951,24 +971,17 @@ got:  	ext4_debug("allocating inode %lu\n", inode->i_ino);  	trace_ext4_allocate_inode(inode, dir, mode); -	goto really_out; -fail: -	ext4_std_error(sb, err); -out: -	iput(inode); -	ret = ERR_PTR(err); -really_out:  	brelse(inode_bitmap_bh);  	return ret;  fail_free_drop:  	dquot_free_inode(inode); -  fail_drop: -	dquot_drop(inode); -	inode->i_flags |= S_NOQUOTA;  	clear_nlink(inode);  	unlock_new_inode(inode); +out: +	dquot_drop(inode); +	inode->i_flags |= S_NOQUOTA;  	iput(inode);  	brelse(inode_bitmap_bh);  	return ERR_PTR(err);  |