mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-06 10:00:17 +00:00
ext4: fix inline data error paths
commit eb5efbcb76 upstream.
The write_end() function must always unlock the page and drop its ref
count, even on an error.
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
popcornmix
parent
8218f7fe9d
commit
10bb1b2fed
@@ -933,8 +933,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
|
||||||
|
|||||||
@@ -1324,8 +1324,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,
|
||||||
@@ -1427,10 +1430,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 {
|
||||||
@@ -1465,6 +1474,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;
|
||||||
|
|||||||
Reference in New Issue
Block a user