summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZhang Yi <yi.zhang@huawei.com>2021-07-16 20:20:22 +0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-10-17 10:43:32 +0200
commit14cbfeeee41b83167bc308f01983618cc5851b53 (patch)
tree7fd0708b7bf72c636b9c05596a5fcb55e5851f66
parentd7a15e1e4fd7db751739d04141390fa6699fd870 (diff)
downloadlinux-stable-14cbfeeee41b83167bc308f01983618cc5851b53.tar.gz
linux-stable-14cbfeeee41b83167bc308f01983618cc5851b53.tar.bz2
linux-stable-14cbfeeee41b83167bc308f01983618cc5851b53.zip
ext4: correct the error path of ext4_write_inline_data_end()
[ Upstream commit 55ce2f649b9e88111270333a8127e23f4f8f42d7 ] 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>
-rw-r--r--fs/ext4/inline.c15
-rw-r--r--fs/ext4/inode.c7
2 files changed, 10 insertions, 12 deletions
diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
index 0f7b53d5edea..a96b688a0410 100644
--- a/fs/ext4/inline.c
+++ b/fs/ext4/inline.c
@@ -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;
}
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index f0dcc09e220b..317aa1b90fb9 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -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;