Commit eb5efbcb authored by Theodore Ts'o's avatar Theodore Ts'o
Browse files

ext4: fix inline data error paths



The write_end() function must always unlock the page and drop its ref
count, even on an error.

Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
Cc: stable@vger.kernel.org
parent 1c83a9aa
Loading
Loading
Loading
Loading
+8 −1
Original line number Original line Diff line number Diff line
@@ -943,8 +943,15 @@ int ext4_da_write_inline_data_end(struct inode *inode, loff_t pos,
				  struct page *page)
				  struct page *page)
{
{
	int i_size_changed = 0;
	int i_size_changed = 0;
	int ret;


	copied = ext4_write_inline_data_end(inode, pos, len, copied, page);
	ret = ext4_write_inline_data_end(inode, pos, len, copied, page);
	if (ret < 0) {
		unlock_page(page);
		put_page(page);
		return ret;
	}
	copied = ret;


	/*
	/*
	 * No need to use i_size_read() here, the i_size
	 * No need to use i_size_read() here, the i_size
+15 −5
Original line number Original line Diff line number Diff line
@@ -1330,8 +1330,11 @@ static int ext4_write_end(struct file *file,
	if (ext4_has_inline_data(inode)) {
	if (ext4_has_inline_data(inode)) {
		ret = ext4_write_inline_data_end(inode, pos, len,
		ret = ext4_write_inline_data_end(inode, pos, len,
						 copied, page);
						 copied, page);
		if (ret < 0)
		if (ret < 0) {
			unlock_page(page);
			put_page(page);
			goto errout;
			goto errout;
		}
		copied = ret;
		copied = ret;
	} else
	} else
		copied = block_write_end(file, mapping, pos,
		copied = block_write_end(file, mapping, pos,
@@ -1433,10 +1436,16 @@ static int ext4_journalled_write_end(struct file *file,


	BUG_ON(!ext4_handle_valid(handle));
	BUG_ON(!ext4_handle_valid(handle));


	if (ext4_has_inline_data(inode))
	if (ext4_has_inline_data(inode)) {
		copied = ext4_write_inline_data_end(inode, pos, len,
		ret = ext4_write_inline_data_end(inode, pos, len,
						 copied, page);
						 copied, page);
	else if (unlikely(copied < len) && !PageUptodate(page)) {
		if (ret < 0) {
			unlock_page(page);
			put_page(page);
			goto errout;
		}
		copied = ret;
	} else if (unlikely(copied < len) && !PageUptodate(page)) {
		copied = 0;
		copied = 0;
		ext4_journalled_zero_new_buffers(handle, page, from, to);
		ext4_journalled_zero_new_buffers(handle, page, from, to);
	} else {
	} else {
@@ -1471,6 +1480,7 @@ static int ext4_journalled_write_end(struct file *file,
		 */
		 */
		ext4_orphan_add(handle, inode);
		ext4_orphan_add(handle, inode);


errout:
	ret2 = ext4_journal_stop(handle);
	ret2 = ext4_journal_stop(handle);
	if (!ret)
	if (!ret)
		ret = ret2;
		ret = ret2;