You've already forked linux-rockchip
mirror of
https://github.com/armbian/linux-rockchip.git
synced 2026-01-06 11:08:10 -08:00
ext4: correct the error path of ext4_write_inline_data_end()
[ Upstream commit 55ce2f649b ]
Current error path of ext4_write_inline_data_end() is not correct.
Firstly, it should pass out the error value if ext4_get_inode_loc()
return fail, or else it could trigger infinite loop if we inject error
here. And then it's better to add inode to orphan list if it return fail
in ext4_journal_stop(), otherwise we could not restore inline xattr
entry after power failure. Finally, we need to reset the 'ret' value if
ext4_write_inline_data_end() return success in ext4_write_end() and
ext4_journalled_write_end(), otherwise we could not get the error return
value of ext4_journal_stop().
Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Link: https://lore.kernel.org/r/20210716122024.1105856-3-yi.zhang@huawei.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
d7a15e1e4f
commit
14cbfeeee4
@@ -733,18 +733,13 @@ int ext4_write_inline_data_end(struct inode *inode, loff_t pos, unsigned len,
|
||||
void *kaddr;
|
||||
struct ext4_iloc iloc;
|
||||
|
||||
if (unlikely(copied < len)) {
|
||||
if (!PageUptodate(page)) {
|
||||
copied = 0;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
if (unlikely(copied < len) && !PageUptodate(page))
|
||||
return 0;
|
||||
|
||||
ret = ext4_get_inode_loc(inode, &iloc);
|
||||
if (ret) {
|
||||
ext4_std_error(inode->i_sb, ret);
|
||||
copied = 0;
|
||||
goto out;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ext4_write_lock_xattr(inode, &no_expand);
|
||||
@@ -757,7 +752,7 @@ int ext4_write_inline_data_end(struct inode *inode, loff_t pos, unsigned len,
|
||||
(void) ext4_find_inline_data_nolock(inode);
|
||||
|
||||
kaddr = kmap_atomic(page);
|
||||
ext4_write_inline_data(inode, &iloc, kaddr, pos, len);
|
||||
ext4_write_inline_data(inode, &iloc, kaddr, pos, copied);
|
||||
kunmap_atomic(kaddr);
|
||||
SetPageUptodate(page);
|
||||
/* clear page dirty so that writepages wouldn't work for us. */
|
||||
@@ -766,7 +761,7 @@ int ext4_write_inline_data_end(struct inode *inode, loff_t pos, unsigned len,
|
||||
ext4_write_unlock_xattr(inode, &no_expand);
|
||||
brelse(iloc.bh);
|
||||
mark_inode_dirty(inode);
|
||||
out:
|
||||
|
||||
return copied;
|
||||
}
|
||||
|
||||
|
||||
@@ -1296,6 +1296,7 @@ static int ext4_write_end(struct file *file,
|
||||
goto errout;
|
||||
}
|
||||
copied = ret;
|
||||
ret = 0;
|
||||
} else
|
||||
copied = block_write_end(file, mapping, pos,
|
||||
len, copied, page, fsdata);
|
||||
@@ -1322,13 +1323,14 @@ static int ext4_write_end(struct file *file,
|
||||
if (i_size_changed || inline_data)
|
||||
ret = ext4_mark_inode_dirty(handle, inode);
|
||||
|
||||
errout:
|
||||
if (pos + len > inode->i_size && !verity && ext4_can_truncate(inode))
|
||||
/* if we have allocated more blocks and copied
|
||||
* less. We will have blocks allocated outside
|
||||
* inode->i_size. So truncate them
|
||||
*/
|
||||
ext4_orphan_add(handle, inode);
|
||||
errout:
|
||||
|
||||
ret2 = ext4_journal_stop(handle);
|
||||
if (!ret)
|
||||
ret = ret2;
|
||||
@@ -1411,6 +1413,7 @@ static int ext4_journalled_write_end(struct file *file,
|
||||
goto errout;
|
||||
}
|
||||
copied = ret;
|
||||
ret = 0;
|
||||
} else if (unlikely(copied < len) && !PageUptodate(page)) {
|
||||
copied = 0;
|
||||
ext4_journalled_zero_new_buffers(handle, page, from, to);
|
||||
@@ -1440,6 +1443,7 @@ static int ext4_journalled_write_end(struct file *file,
|
||||
ret = ret2;
|
||||
}
|
||||
|
||||
errout:
|
||||
if (pos + len > inode->i_size && !verity && ext4_can_truncate(inode))
|
||||
/* if we have allocated more blocks and copied
|
||||
* less. We will have blocks allocated outside
|
||||
@@ -1447,7 +1451,6 @@ static int ext4_journalled_write_end(struct file *file,
|
||||
*/
|
||||
ext4_orphan_add(handle, inode);
|
||||
|
||||
errout:
|
||||
ret2 = ext4_journal_stop(handle);
|
||||
if (!ret)
|
||||
ret = ret2;
|
||||
|
||||
Reference in New Issue
Block a user