[<prev] [next>] [day] [month] [year] [list]
Message-ID: <C932196342E85337+20240720160420.578940-3-wangyuli@uniontech.com>
Date: Sun, 21 Jul 2024 00:04:08 +0800
From: WangYuli <wangyuli@...ontech.com>
To: stable@...r.kernel.org,
gregkh@...uxfoundation.org,
sashal@...nel.org,
yi.zhang@...wei.com
Cc: jack@...e.cz,
tytso@....edu,
adilger.kernel@...ger.ca,
linux-ext4@...r.kernel.org,
linux-kernel@...r.kernel.org,
yukuai3@...wei.com,
niecheng1@...ontech.com,
zhangdandan@...ontech.com,
guanwentao@...ontech.com,
WangYuli <wangyuli@...ontech.com>
Subject: [PATCH v2 4.19 2/4] ext4: correct the error path of ext4_write_inline_data_end()
From: Zhang Yi <yi.zhang@...wei.com>
commit 55ce2f649b9e88111270333a8127e23f4f8f42d7 upstream
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().
Cc: stable@...r.kernel.org
Signed-off-by: Zhang Yi <yi.zhang@...wei.com>
Reviewed-by: Jan Kara <jack@...e.cz>
Signed-off-by: Theodore Ts'o <tytso@....edu>
Link: https://lore.kernel.org/r/20210716122024.1105856-3-yi.zhang@huawei.com
Reviewed-by: Cheng Nie <niecheng1@...ontech.com>
Signed-off-by: Dandan Zhang <zhangdandan@...ontech.com>
Signed-off-by: WangYuli <wangyuli@...ontech.com>
---
fs/ext4/inline.c | 15 +++++----------
fs/ext4/inode.c | 7 +++++--
2 files changed, 10 insertions(+), 12 deletions(-)
diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
index 71bb3cfc5933..de04bd5fb551 100644
--- a/fs/ext4/inline.c
+++ b/fs/ext4/inline.c
@@ -745,18 +745,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);
@@ -769,7 +764,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. */
@@ -778,7 +773,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 d8a8e4ee5ff8..44a715e6aae1 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1428,6 +1428,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);
@@ -1450,13 +1451,14 @@ static int ext4_write_end(struct file *file,
if (i_size_changed || inline_data)
ext4_mark_inode_dirty(handle, inode);
+errout:
if (pos + len > inode->i_size && 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;
@@ -1538,6 +1540,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);
@@ -1566,6 +1569,7 @@ static int ext4_journalled_write_end(struct file *file,
ret = ret2;
}
+errout:
if (pos + len > inode->i_size && ext4_can_truncate(inode))
/* if we have allocated more blocks and copied
* less. We will have blocks allocated outside
@@ -1573,7 +1577,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;
--
2.43.4
Powered by blists - more mailing lists