| From 3a051f657a7c263dee30836f5df8f6c048864429 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Wed, 13 Mar 2024 20:26:20 +0900 |
| Subject: f2fs: truncate page cache before clearing flags when aborting atomic |
| write |
| |
| From: Sunmin Jeong <s_min.jeong@samsung.com> |
| |
| [ Upstream commit 74b0ebcbdde4c7fe23c979e4cfc2fdbf349c39a3 ] |
| |
| In f2fs_do_write_data_page, FI_ATOMIC_FILE flag selects the target inode |
| between the original inode and COW inode. When aborting atomic write and |
| writeback occur simultaneously, invalid data can be written to original |
| inode if the FI_ATOMIC_FILE flag is cleared meanwhile. |
| |
| To prevent the problem, let's truncate all pages before clearing the flag |
| |
| Atomic write thread Writeback thread |
| f2fs_abort_atomic_write |
| clear_inode_flag(inode, FI_ATOMIC_FILE) |
| __writeback_single_inode |
| do_writepages |
| f2fs_do_write_data_page |
| - use dn of original inode |
| truncate_inode_pages_final |
| |
| Fixes: 3db1de0e582c ("f2fs: change the current atomic write way") |
| Cc: stable@vger.kernel.org #v5.19+ |
| Reviewed-by: Sungjong Seo <sj1557.seo@samsung.com> |
| Reviewed-by: Yeongjin Gil <youngjin.gil@samsung.com> |
| Signed-off-by: Sunmin Jeong <s_min.jeong@samsung.com> |
| Reviewed-by: Daeho Jeong <daehojeong@google.com> |
| Reviewed-by: Chao Yu <chao@kernel.org> |
| Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| fs/f2fs/segment.c | 4 +++- |
| 1 file changed, 3 insertions(+), 1 deletion(-) |
| |
| diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c |
| index dfc7fd8aa1e8f..7a0143825e19d 100644 |
| --- a/fs/f2fs/segment.c |
| +++ b/fs/f2fs/segment.c |
| @@ -192,6 +192,9 @@ void f2fs_abort_atomic_write(struct inode *inode, bool clean) |
| if (!f2fs_is_atomic_file(inode)) |
| return; |
| |
| + if (clean) |
| + truncate_inode_pages_final(inode->i_mapping); |
| + |
| release_atomic_write_cnt(inode); |
| clear_inode_flag(inode, FI_ATOMIC_COMMITTED); |
| clear_inode_flag(inode, FI_ATOMIC_REPLACE); |
| @@ -201,7 +204,6 @@ void f2fs_abort_atomic_write(struct inode *inode, bool clean) |
| F2FS_I(inode)->atomic_write_task = NULL; |
| |
| if (clean) { |
| - truncate_inode_pages_final(inode->i_mapping); |
| f2fs_i_size_write(inode, fi->original_i_size); |
| fi->original_i_size = 0; |
| } |
| -- |
| 2.43.0 |
| |