Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3b10fdc6 authored by Miao Xie's avatar Miao Xie Committed by Theodore Ts'o
Browse files

ext4: fix forgetten xattr lock protection in ext4_expand_extra_isize



We should avoid the contention between the i_extra_isize update and
the inline data insertion, so move the xattr trylock in front of
i_extra_isize update.

Signed-off-by: default avatarMiao Xie <miaoxie@huawei.com>
Reviewed-by: default avatarWang Shilong <wshilong@ddn.com>
parent 9699d4f9
Loading
Loading
Loading
Loading
+16 −2
Original line number Diff line number Diff line
@@ -5713,10 +5713,15 @@ static int ext4_expand_extra_isize(struct inode *inode,
{
	struct ext4_inode *raw_inode;
	struct ext4_xattr_ibody_header *header;
	int no_expand;
	int error;

	if (EXT4_I(inode)->i_extra_isize >= new_extra_isize)
		return 0;

	if (ext4_write_trylock_xattr(inode, &no_expand) == 0)
		return 0;

	raw_inode = ext4_raw_inode(&iloc);

	header = IHDR(inode, raw_inode);
@@ -5728,12 +5733,21 @@ static int ext4_expand_extra_isize(struct inode *inode,
		       EXT4_I(inode)->i_extra_isize, 0,
		       new_extra_isize - EXT4_I(inode)->i_extra_isize);
		EXT4_I(inode)->i_extra_isize = new_extra_isize;
		ext4_write_unlock_xattr(inode, &no_expand);
		return 0;
	}

	/* try to expand with EAs present */
	return ext4_expand_extra_isize_ea(inode, new_extra_isize,
	error = ext4_expand_extra_isize_ea(inode, new_extra_isize,
					   raw_inode, handle);
	if (error) {
		/*
		 * Inode size expansion failed; don't try again
		 */
		no_expand = 1;
	}
	ext4_write_unlock_xattr(inode, &no_expand);
	return error;
}

/*
+0 −10
Original line number Diff line number Diff line
@@ -2645,10 +2645,6 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
	int error = 0, tried_min_extra_isize = 0;
	int s_min_extra_isize = le16_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_min_extra_isize);
	int isize_diff;	/* How much do we need to grow i_extra_isize */
	int no_expand;

	if (ext4_write_trylock_xattr(inode, &no_expand) == 0)
		return 0;

retry:
	isize_diff = new_extra_isize - EXT4_I(inode)->i_extra_isize;
@@ -2731,16 +2727,10 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
	EXT4_I(inode)->i_extra_isize = new_extra_isize;
	brelse(bh);
out:
	ext4_write_unlock_xattr(inode, &no_expand);
	return 0;

cleanup:
	brelse(bh);
	/*
	 * Inode size expansion failed; don't try again
	 */
	no_expand = 1;
	ext4_write_unlock_xattr(inode, &no_expand);
	return error;
}